Skip to content

Commit f4fa727

Browse files
alex-dzedajonathan-cantu-icf
authored andcommitted
BFD-4648: Update BFD v3 to C4BB 2.2.0 (#3112)
1 parent c99f20c commit f4fa727

47 files changed

Lines changed: 1341 additions & 836 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

apps/bfd-model-idr/README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,20 +60,24 @@ This will generate the StructureDefinition and CodeSystem resources necessary fo
6060

6161
To reduce dependencies on tx.fhir.org as well as improve the speed of validation, we use matchbox to run a local FHIR server. Read more about matchbox at <https://ahdis.github.io/matchbox/>
6262

63-
Note: Matchbox uses a significant amount of memory. Allocating at least 8GB of RAM is recommended, and more may be necessary in the future.
63+
Note: Matchbox uses a good bit of memory. Allocating at least 8GB of RAM is recommended. When new version dependencies are added, the heap allocated required should be re-evaluated. The compose setup is optimized to GC aggressively to reduce the impact.
6464

6565
To start matchbox, run
6666

6767
```sh
6868
docker compose up -d
6969
```
7070

71-
Note, it takes several minutes and requires a good bit of RAM. It'll be ready once it says that packages have been loaded and some obviously untrue amount of RAM (generally half of what it actually used) was used. Additionally, one can check the logs for "Finished engines during startup" or running a health check using
71+
Note, it takes several minutes and requires a good bit of RAM. Once the uploads from matchbox-setup are completed, matchbox should be ready to use. Additionally, matchbox has a health check available at:
7272

7373
```sh
7474
curl -X GET "http://localhost:8080/matchboxv3/actuator/health"
7575
```
7676

77+
### Referencing New/Updated Dependencies for Matchbox
78+
79+
As new versions of IGs are released, they may have multiple nested dependencies. This takes up a significant amount of memory if loaded directly into Matchbox. To eliminate heap errors while still being able to accurately validate profiles and terminology, we download the FHIR Packages locally, untar them, and upload relevant resources directly to Matchbox. The list of resources + packages are in matchbox_profiles.txt. To add a new IG reference, follow the syntax in that file. Packages are only uploaded using docker compose up (by calling setup_matchbox.py), so restart the composition if adding more dependencies.
80+
7781
### Create FHIR files with synthetic data
7882

7983
Requires Matchbox to be active.

apps/bfd-model-idr/application.yaml

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,32 @@ spring:
1414
jpa:
1515
properties:
1616
hibernate.dialect: org.hibernate.dialect.PostgreSQLDialect
17+
hibernate.search.enabled: false
18+
hibernate.cache.use_second_level_cache: false
19+
hibernate.cache.use_query_cache: false
1720
matchbox:
1821
fhir:
1922
context:
2023
displayIssuesAreWarnings: false
2124
txServer: http://localhost:8080/matchboxv3/tx
2225
onlyOneEngine: true
23-
igsPreloaded: hl7.fhir.us.carin-bb#2.1.0
26+
fhirVersion: R4
27+
suppressR5: true
28+
logging:
29+
level:
30+
ca.uhn.fhir: ERROR
31+
ca.uhn.fhir.rest.server.ResourceBinding: ERROR
32+
ch.ahdis.matchbox: DEBUG
2433
hapi:
2534
fhir:
26-
implementationguides:
27-
carin:
28-
name: hl7.fhir.us.carin-bb
29-
version: 2.1.0
35+
fhir_version: R4
36+
mdm_enabled: false
37+
openapi_enabled: false
38+
narrative_enabled: false
39+
jpa:
40+
subscription_matching_enabled: false
41+
bulk_export_enabled: false
42+
dao_scheduling_enabled: false
43+
enforce_referential_integrity_on_delete: false
44+
enforce_referential_integrity_on_write: false
3045

apps/bfd-model-idr/augment_sample_resources.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@
5151
"CLM_NGACO_CPTATN_SW": "CLM_NGACO_CPTATN_SW",
5252
"CLM_ACO_CARE_MGMT_HCBS_SW": "CLM_ACO_CARE_MGMT_HCBS_SW",
5353
"CLM_PD_STUS_CD": "CLM_PD_STUS_CD",
54+
"CLM_NRLN_RIC_CD": "CLM_NRLN_RIC_CD",
55+
"CLM_RIC_CD": "CLM_RIC_CD",
5456
"GEO_BLG_SSA_STATE_CD": "GEO_BLG_SSA_STATE_CD",
5557
}
5658

@@ -411,7 +413,7 @@ def next_row_num(supporting_info):
411413

412414
filename = "out/temporary-sample.json"
413415

414-
cur_sample_data["lastUpdated"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S.%fZ")
416+
cur_sample_data["lastUpdated"] = "2026-01-01T03:02:28.000000Z"
415417

416418
with Path(filename).open("w") as f:
417419
json.dump(cur_sample_data, f, indent=4)

apps/bfd-model-idr/compile_resources.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def main():
238238
print("Executing Transform")
239239
execute_cmd = f"java -jar validator_cli.jar {input_file} -output {args.output} -transform \
240240
{args.resource} -version 4.0.1 -ig {compiled_map_path} \
241-
-ig hl7.fhir.us.carin-bb#2.1.0 {map_imports} {sushi_resources} -tx {MATCHBOX_SERVER}/tx"
241+
-ig hl7.fhir.us.carin-bb#2.2.0 {map_imports} {sushi_resources} -tx {MATCHBOX_SERVER}/tx"
242242
stdout, stderr = run_command(execute_cmd, cwd=script_dir)
243243

244244
print("Execution output:")

apps/bfd-model-idr/dictionary-support-files/ExplanationOfBenefit.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1211,7 +1211,7 @@
12111211
- CCLFA.CLM_1_REV_CNTR_ANSI_RSN_CD
12121212
sourceView: V2_MDCR_CLM_ANSI_SGNTR
12131213
sourceColumn: CLM_1_REV_CNTR_ANSI_RSN_CD
1214-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CODE').code
1214+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CD').code
12151215
notes: ANSI reason and group codes are unordered.
12161216
- inputPath: LineItemComponent.CLM_1_REV_CNTR_ANSI_GRP_CD
12171217
appliesTo:
@@ -1228,7 +1228,7 @@
12281228
- CCLFA.CLM_1_REV_CNTR_ANSI_GRP_CD
12291229
sourceView: V2_MDCR_CLM_ANSI_SGNTR
12301230
sourceColumn: CLM_1_REV_CNTR_ANSI_GRP_CD
1231-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CODE').code
1231+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CD').code
12321232
notes: ANSI reason and group codes are unordered.
12331233
- inputPath: LineItemComponent.CLM_2_REV_CNTR_ANSI_RSN_CD
12341234
appliesTo:
@@ -1243,7 +1243,7 @@
12431243
- REV_CNTR_2ND_ANSI_CD
12441244
sourceView: V2_MDCR_CLM_ANSI_SGNTR
12451245
sourceColumn: CLM_2_REV_CNTR_ANSI_RSN_CD
1246-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CODE').code
1246+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CD').code
12471247
notes: ANSI reason and group codes are unordered.
12481248
- inputPath: LineItemComponent.CLM_2_REV_CNTR_ANSI_GRP_CD
12491249
appliesTo:
@@ -1258,7 +1258,7 @@
12581258
- REV_CNTR_2ND_ANSI_CD
12591259
sourceView: V2_MDCR_CLM_ANSI_SGNTR
12601260
sourceColumn: CLM_2_REV_CNTR_ANSI_GRP_CD
1261-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CODE').code
1261+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CD').code
12621262
notes: ANSI reason and group codes are unordered.
12631263
- inputPath: LineItemComponent.CLM_3_REV_CNTR_ANSI_RSN_CD
12641264
appliesTo:
@@ -1273,7 +1273,7 @@
12731273
- REV_CNTR_3RD_ANSI_CD
12741274
sourceView: V2_MDCR_CLM_ANSI_SGNTR
12751275
sourceColumn: CLM_3_REV_CNTR_ANSI_RSN_CD
1276-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CODE').code
1276+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CD').code
12771277
notes: ANSI reason and group codes are unordered.
12781278
- inputPath: LineItemComponent.CLM_3_REV_CNTR_ANSI_GRP_CD
12791279
appliesTo:
@@ -1288,7 +1288,7 @@
12881288
- REV_CNTR_3RD_ANSI_CD
12891289
sourceView: V2_MDCR_CLM_ANSI_SGNTR
12901290
sourceColumn: CLM_3_REV_CNTR_ANSI_GRP_CD
1291-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CODE').code
1291+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CD').code
12921292
notes: ANSI reason and group codes are unordered.
12931293
- inputPath: LineItemComponent.CLM_4_REV_CNTR_ANSI_RSN_CD
12941294
appliesTo:
@@ -1303,7 +1303,7 @@
13031303
- REV_CNTR_4TH_ANSI_CD
13041304
sourceView: V2_MDCR_CLM_ANSI_SGNTR
13051305
sourceColumn: CLM_4_REV_CNTR_ANSI_RSN_CD
1306-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CODE').code
1306+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-RSN-CD').code
13071307
notes: ANSI reason and group codes are unordered.
13081308
- inputPath: LineItemComponent.CLM_4_REV_CNTR_ANSI_GRP_CD
13091309
appliesTo:
@@ -1318,7 +1318,7 @@
13181318
- REV_CNTR_4TH_ANSI_CD
13191319
sourceView: V2_MDCR_CLM_ANSI_SGNTR
13201320
sourceColumn: CLM_4_REV_CNTR_ANSI_GRP_CD
1321-
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CODE').code
1321+
fhirPath: ExplanationOfBenefit.item.adjudication.reason.coding.where(system='https://bluebutton.cms.gov/fhir/CodeSystem/ANSI-GRP-CD').code
13221322
notes: ANSI reason and group codes are unordered.
13231323
- inputPath: LineItemComponent.CLM_LINE_NCVRD_CHRG_AMT
13241324
appliesTo:

apps/bfd-model-idr/docker-compose.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,32 @@
11
services:
22
matchbox:
3-
image: europe-west6-docker.pkg.dev/ahdis-ch/ahdis/matchbox:v4.0.18
3+
image: europe-west6-docker.pkg.dev/ahdis-ch/ahdis/matchbox:v4.1.5
44
container_name: matchbox
55
restart: on-failure
66
ports:
77
- "8080:8080"
88
depends_on:
99
- matchbox-db
10-
entrypoint: ["java", "-Xms2G", "-Xmx10G", "-Dfhir.settings.path=/config/fhir-settings.json", "-Dspring.config.additional-location=optional:file:/config/application.yaml,optional:file:application.yaml", "-jar", "/matchbox.jar"]
10+
entrypoint: ["java", "-Xms512m", "-Xmx6G", "-XX:+UseZGC", "-XX:ZUncommitDelay=30", "-XX:MaxMetaspaceSize=512m", "-Dfhir.settings.path=/config/fhir-settings.json", "-Dspring.config.additional-location=optional:file:/config/application.yaml", "-jar", "/matchbox.jar"]
11+
healthcheck:
12+
test: ["CMD", "curl", "-f", "http://localhost:8080/matchboxv3/fhir/metadata"]
13+
interval: 5s
14+
timeout: 5s
15+
retries: 30
1116
volumes:
1217
- ./:/config/
18+
matchbox-setup:
19+
image: ghcr.io/astral-sh/uv:python3.14-alpine
20+
volumes:
21+
- ./:/app
22+
working_dir: /app
23+
depends_on:
24+
matchbox:
25+
condition: service_healthy
26+
environment:
27+
- UV_PYTHON=3.14.3
28+
- UV_PROJECT_ENVIRONMENT=/tmp/.venv
29+
command: uv run setup_matchbox.py --url http://matchbox:8080/matchboxv3/fhir
1330
matchbox-db:
1431
image: postgres:17.7
1532
container_name: matchbox-db
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"fhirVersion": "R4",
3+
"suppressR5": true
4+
}

apps/bfd-model-idr/maps/Coverage-Base.map

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ group createCoverageBase(source src: CoverageBase, target tgt: BFDCoverage){
1717
} "Add ID key";
1818
src -> tgt.meta = create('Meta') as tgtMeta then{
1919
src.lastUpdated as lastUpdated -> tgtMeta.lastUpdated = lastUpdated "Set lastUpdated";
20-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Coverage|2.1.0" "Set C4BB profile";
21-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-coverage|6.1.0" "Set US Core profile";
20+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Coverage|2.2.0" "Set C4BB profile";
21+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-coverage|7.0.0" "Set US Core profile";
2222
} "add metadata";
2323
src.XREF_EFCTV_BENE_SK as beneSk -> tgt.beneficiary = create('Reference') as tgtReference,
2424
tgtReference.reference = append("Patient/",beneSk) "Set bene_sk";
@@ -174,7 +174,10 @@ group createPartDCoverage(source src: CoverageBase, target tgt: BFDCoverage){
174174

175175
src.BENE_ENRLMT_EMPLR_SBSDY_SW as switch -> tgt.extension = create('Extension') as tgtExtension then{
176176
src -> tgtExtension.url = "https://bluebutton.cms.gov/fhir/StructureDefinition/BENE-ENRLMT-EMPLR-SBSDY-SW" "Add url";
177-
src -> tgtExtension.value = switch "Add value";
177+
src -> tgtExtension.value = create('Coding') as tgtCoding then{
178+
src -> tgtCoding.system = "https://bluebutton.cms.gov/fhir/CodeSystem/BENE-ENRLMT-EMPLR-SBSDY-SW" "add system";
179+
src -> tgtCoding.code = switch "Add code";
180+
} "Add coding";
178181
} "Add RDS switch ";
179182

180183
//Coverage Type Code Extension
@@ -492,7 +495,7 @@ group AddPartBCoverageElements(source src: CoverageBase, target tgt: BFDCoverage
492495

493496
group SetOrganizationEntryCMS(source src : CoverageBase, target tgt : Organization) {
494497
src -> tgt.meta = create('Meta') as tgtMeta then{
495-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.1.0" "set profile";
498+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.2.0" "set profile";
496499
} "add metadata";
497500

498501
src -> tgt.id = "cms-org" "set org id";
@@ -519,7 +522,7 @@ group SetOrganizationEntryCMS(source src : CoverageBase, target tgt : Organizati
519522
//Source this information from the respective tables
520523
group SetOrganizationEntryPartCD(source src : CoverageBase, target tgt : Organization) {
521524
src -> tgt.meta = create('Meta') as tgtMeta then{
522-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.1.0" "set profile";
525+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.2.0" "set profile";
523526
} "add metadata";
524527

525528
src -> tgt.id = "insurer-org" "set org id";

apps/bfd-model-idr/maps/ExplanationOfBenefit-Base.map

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -566,8 +566,8 @@ group addProcedures(source src: ProcedureComponent, target tgt: BackboneElement)
566566
group createInsurerOrgPartAB(source src: ExplanationOfBenefitBase, target tgtOrg: Organization){
567567
src -> tgtOrg.id = "insurer-org" "Set org id";
568568
src -> tgtOrg.meta = create('Meta') as tgtMeta then {
569-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.1.0" "Set org profile";
570-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization|6.1.0" "Set org profile";
569+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.2.0" "Set org profile";
570+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization|7.0.0" "Set org profile";
571571
} "Set organization metadata";
572572
src -> tgtOrg.active = "true" "set org status";
573573
src -> tgtOrg.name = "Centers for Medicare & Medicaid Services" "set org name";
@@ -594,8 +594,8 @@ group createOrg(source src: Provider, target tgt: Organization){
594594

595595
//when PRVDR_SK is missing (eg NPI) these won't conform, so don't add the profile.
596596
src.PRVDR_SK as sk -> tgt.meta = create('Meta') as tgtMeta then {
597-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.1.0" "Set org profile";
598-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization|6.1.0" "Set org profile";
597+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Organization|2.2.0" "Set org profile";
598+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-organization|7.0.0" "Set org profile";
599599
} "Set Org metadata";
600600
src -> tgt.active = "true" "set org status";
601601

@@ -631,8 +631,8 @@ group createPractitioner(source src: Provider, target tgt: Practitioner){
631631
} "Add qualifier code and id num";
632632

633633
src -> tgt.meta = create('Meta') as tgtMeta then {
634-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Practitioner|2.1.0" "Set profile";
635-
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner|6.1.0" "Set profile";
634+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Practitioner|2.2.0" "Set profile";
635+
src -> tgtMeta.profile = "http://hl7.org/fhir/us/core/StructureDefinition/us-core-practitioner|7.0.0" "Set profile";
636636
} "Set practitioner metadata";
637637

638638
src -> tgt.identifier = create('Identifier') as tgtId then {

0 commit comments

Comments
 (0)