Skip to content

Commit 57f9850

Browse files
committed
Returning OperationOutcome when there are no matches. Added data initialization to include IG examples
1 parent 60df337 commit 57f9850

15 files changed

+340
-4
lines changed

.vscode/launch.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
{
2+
"configurations": [
3+
{
4+
"type": "java",
5+
"name": "Spring Boot-Application<hapi-fhir-jpaserver-starter>",
6+
"request": "launch",
7+
"cwd": "${workspaceFolder}",
8+
"mainClass": "ca.uhn.fhir.jpa.starter.Application",
9+
"projectName": "hapi-fhir-jpaserver-starter",
10+
"vmArgs": [
11+
"-XX:TieredStopAtLevel=1",
12+
// "-Ddebug=true",
13+
// "-Dloader.debug=true",
14+
"-Dhapi.fhir.bulk_export_enabled=false",
15+
"-Dspring.batch.job.enabled=false",
16+
"-Dspring.main.allow-bean-definition-overriding=true",
17+
"-Dhapi.fhir.cdshooks.enabled=true",
18+
"-Dhapi.fhir.cr.enabled=true",
19+
"-Dspring.main.allow-bean-definition-overriding=true"
20+
21+
],
22+
"envFile": "${workspaceFolder}/.env"
23+
}
24+
]
25+
}

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
"**/.settings": true,
66
"**/.factorypath": true
77
},
8+
"java.compile.nullAnalysis.mode": "disabled",
89
"java.configuration.updateBuildConfiguration": "automatic"
910
}

src/main/java/ca/uhn/fhir/jpa/starter/AppProperties.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -974,6 +974,9 @@ public void setResource_dbhistory_enabled(Boolean resource_dbhistory_enabled) {
974974

975975
// custom properties
976976

977+
@Getter @Setter
978+
private List<String> initialData = new ArrayList<>();
979+
977980
@Getter @Setter
978981
private String matchValidationHeader = "X-Match-Validation";
979982

src/main/java/ca/uhn/fhir/jpa/starter/Application.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import ca.uhn.fhir.jpa.starter.cdshooks.StarterCdsHooksConfig;
88
import ca.uhn.fhir.jpa.starter.cr.StarterCrDstu3Config;
99
import ca.uhn.fhir.jpa.starter.cr.StarterCrR4Config;
10+
import ca.uhn.fhir.jpa.starter.custom.DataInitializer;
1011
import ca.uhn.fhir.jpa.starter.mdm.MdmConfig;
1112
import ca.uhn.fhir.jpa.starter.operations.IdentityMatching;
1213
import ca.uhn.fhir.jpa.starter.security.CertInterceptor;
@@ -164,4 +165,11 @@ public ServletRegistrationBean<RestfulServer> hapiServletRegistration(RestfulSer
164165
return servletRegistrationBean;
165166
}
166167

168+
169+
// Ensure data is loaded when the application starts
170+
@Bean
171+
public DataInitializer dataInitializer() {
172+
return new DataInitializer();
173+
}
174+
167175
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package ca.uhn.fhir.jpa.starter.custom;
2+
3+
import java.nio.charset.StandardCharsets;
4+
import org.hl7.fhir.instance.model.api.IBaseResource;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.core.io.Resource;
9+
import org.springframework.core.io.ResourceLoader;
10+
import org.springframework.core.io.support.ResourcePatternUtils;
11+
import org.springframework.util.FileCopyUtils;
12+
13+
import ca.uhn.fhir.context.FhirContext;
14+
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
15+
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
16+
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
17+
import ca.uhn.fhir.jpa.starter.AppProperties;
18+
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
19+
import jakarta.annotation.PostConstruct;
20+
21+
public class DataInitializer {
22+
23+
private static final Logger logger = LoggerFactory.getLogger(DataInitializer.class);
24+
25+
@Autowired
26+
private FhirContext fhirContext;
27+
28+
@Autowired
29+
private DaoRegistry daoRegistry;
30+
31+
@Autowired
32+
private AppProperties appProperties;
33+
34+
@Autowired
35+
private ResourceLoader resourceLoader;
36+
37+
@Autowired
38+
private JpaStorageSettings storageSettings;
39+
40+
41+
@PostConstruct
42+
public void initializeData() {
43+
44+
if (appProperties.getInitialData() == null || appProperties.getInitialData().isEmpty()) {
45+
return;
46+
}
47+
48+
logger.info("Initializing data");
49+
50+
// Disable referential integrity checks so that resources can be loaded in any order
51+
storageSettings.setEnforceReferentialIntegrityOnWrite(false);
52+
53+
for (String directoryPath : appProperties.getInitialData()) {
54+
logger.info("Loading resources from directory: " + directoryPath);
55+
56+
Resource[] resources = null;
57+
58+
try {
59+
resources = ResourcePatternUtils.getResourcePatternResolver(resourceLoader).getResources("classpath:" + directoryPath + "/**/*.json");
60+
} catch (Exception e) {
61+
logger.error("Error loading resources from directory: " + directoryPath, e);
62+
continue;
63+
}
64+
65+
for (Resource resource : resources) {
66+
try {
67+
String resourceText = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()), StandardCharsets.UTF_8);
68+
69+
IBaseResource fhirResource = fhirContext.newJsonParser().parseResource(resourceText);
70+
71+
IFhirResourceDao<IBaseResource> dao = daoRegistry.getResourceDao(fhirResource);
72+
dao.update(fhirResource, new SystemRequestDetails());
73+
logger.info("Loaded resource: " + resource.getFilename());
74+
} catch (Exception e) {
75+
logger.error("Error loading resource: " + resource.getFilename(), e);
76+
}
77+
}
78+
79+
}
80+
81+
// Re-enable referential integrity checks if they were previously enabled
82+
storageSettings.setEnforceReferentialIntegrityOnWrite(appProperties.getEnforce_referential_integrity_on_write());
83+
84+
}
85+
86+
}

src/main/java/ca/uhn/fhir/jpa/starter/operations/IdentityMatching.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
import org.springframework.core.io.ResourceLoader;
2727
import org.springframework.core.io.support.ResourcePatternUtils;
2828
import java.io.IOException;
29-
import java.time.Instant;
3029
import java.util.ArrayList;
3130
import java.util.EnumSet;
3231
import java.util.HashSet;
@@ -67,7 +66,7 @@ public IdentityMatching(AppProperties appProperties, IFhirResourceDao<Patient> p
6766
* Extends the HL7 FHIR patient $match operation: http://hl7.org/fhir/R4/patient-operation-match.html
6867
*/
6968
@Operation(name = "$match", typeName = "Patient")
70-
public Bundle patientMatchOperation(
69+
public Resource patientMatchOperation(
7170
@ResourceParam Parameters params,
7271
HttpServletRequest theServletRequest,
7372
HttpServletResponse theServletResponse
@@ -117,7 +116,7 @@ public Bundle patientMatchOperation(
117116
* $idi-match operation defined in Identity Matching IG STU2
118117
*/
119118
@Operation(name = "$idi-match", typeName = "Patient")
120-
public Bundle idiMatchOperation(
119+
public Resource idiMatchOperation(
121120
@ResourceParam Parameters params,
122121
HttpServletRequest theServletRequest,
123122
HttpServletResponse theServletResponse
@@ -163,7 +162,7 @@ public Bundle idiMatchOperation(
163162
}
164163

165164

166-
protected Bundle doMatch(
165+
protected Resource doMatch(
167166
IdentityMatchParams params,
168167
HttpServletRequest theServletRequest,
169168
HttpServletResponse theServletResponse
@@ -335,6 +334,19 @@ else if(com.hasSystem() && com.getSystem().toCode().equals(ContactPoint.ContactP
335334

336335
}
337336

337+
338+
339+
// no matches found... return an OperationOutcome instead
340+
if (outputBundle.getEntry().isEmpty()) {
341+
String message = "No matches found.";
342+
OperationOutcome outcome = new OperationOutcome();
343+
outcome.addIssue().setCode(OperationOutcome.IssueType.NOTFOUND).setSeverity(OperationOutcome.IssueSeverity.INFORMATION)
344+
.setDiagnostics(message);
345+
346+
return outcome;
347+
}
348+
349+
338350
outputBundle.setType(Bundle.BundleType.COLLECTION);
339351
outputBundle.setMeta(new Meta().addProfile("http://hl7.org/fhir/us/identity-matching/StructureDefinition/idi-match-bundle"));
340352

src/main/resources/application.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ spring:
9595
# hibernate.search.backend.analysis.configurer: ca.uhn.fhir.jpa.search.HapiHSearchAnalysisConfigurers$HapiElasticAnalysisConfigurer
9696
hapi:
9797
fhir:
98+
initialdata:
99+
- examples
98100
match-validation-header: X-Match-Validation
99101
match-validation-level: DEFAULT
100102

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"resourceType":"Organization","id":"abc-hospital","text":{"status":"generated","div":"<div xmlns=\"http://www.w3.org/1999/xhtml\"><p class=\"res-header-id\"><b>Generated Narrative: Organization abc-hospital</b></p><a name=\"abc-hospital\"> </a><a name=\"hcabc-hospital\"> </a><a name=\"abc-hospital-en-US\"> </a><p><b>identifier</b>: <code>urn:oid:2.16.528.1</code>/91654\u00a0(use:\u00a0official,\u00a0), <code>urn:oid:2.16.840.1.113883.2.4.6.1</code>/17-0112278\u00a0(use:\u00a0usual,\u00a0)</p><p><b>name</b>: Burgers University Medical Center</p><blockquote><p><b>contact</b></p><p><b>telecom</b>: ph: 022-655 2300(Work)</p></blockquote><blockquote><p><b>contact</b></p><p><b>address</b>: Galapagosweg 91 Den Burg 9105 PZ NLD (work)</p></blockquote><blockquote><p><b>contact</b></p><p><b>address</b>: PO Box 2311 Den Burg 9100 AA NLD (work)</p></blockquote><blockquote><p><b>contact</b></p><p><b>telecom</b>: ph: 022-655 2334</p></blockquote><blockquote><p><b>contact</b></p><p><b>telecom</b>: ph: 022-655 2335</p></blockquote></div>"},"identifier":[{"use":"official","system":"urn:oid:2.16.528.1","value":"91654"},{"use":"usual","system":"urn:oid:2.16.840.1.113883.2.4.6.1","value":"17-0112278"}],"name":"Burgers University Medical Center","contact":[{"telecom":[{"system":"phone","value":"022-655 2300","use":"work"}]},{"address":{"use":"work","line":["Galapagosweg 91"],"city":"Den Burg","postalCode":"9105 PZ","country":"NLD"}},{"address":{"use":"work","line":["PO Box 2311"],"city":"Den Burg","postalCode":"9100 AA","country":"NLD"}},{"telecom":[{"system":"phone","value":"022-655 2334"}]},{"telecom":[{"system":"phone","value":"022-655 2335"}]}]}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"resourceType":"Organization","id":"def-idp","text":{"status":"generated","div":"<div xmlns=\"http://www.w3.org/1999/xhtml\"><p class=\"res-header-id\"><b>Generated Narrative: Organization def-idp</b></p><a name=\"def-idp\"> </a><a name=\"hcdef-idp\"> </a><a name=\"def-idp-en-US\"> </a><p><b>identifier</b>: <code>http://www.secureidp.com/units</code>/SecureIdp</p><p><b>name</b>: Secure Idp</p><blockquote><p><b>contact</b></p><p><b>telecom</b>: <a href=\"tel:+15552343523\">+1 555 234 3523</a>, <a href=\"mailto:gastro@acme.org\">gastro@acme.org</a></p></blockquote></div>"},"identifier":[{"system":"http://www.secureidp.com/units","value":"SecureIdp"}],"name":"Secure Idp","contact":[{"telecom":[{"system":"phone","value":"+1 555 234 3523","use":"work"},{"system":"email","value":"gastro@acme.org","use":"work"}]}]}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"resourceType":"Organization","id":"xyz-payer","text":{"status":"generated","div":"<div xmlns=\"http://www.w3.org/1999/xhtml\"><p class=\"res-header-id\"><b>Generated Narrative: Organization xyz-payer</b></p><a name=\"xyz-payer\"> </a><a name=\"hcxyz-payer\"> </a><a name=\"xyz-payer-en-US\"> </a><p><b>identifier</b>: <code>urn:oid:2.16.840.1.113883.3.19.2.3</code>/666666</p><p><b>name</b>: XYZ Insurance</p><p><b>alias</b>: ABC Insurance</p><blockquote><p><b>contact</b></p><p><b>telecom</b>: <a href=\"tel:+15552343523\">+1 555 234 3523</a>, <a href=\"mailto:info@xyz-payer.org\">info@xyz-payer.org</a></p></blockquote></div>"},"identifier":[{"system":"urn:oid:2.16.840.1.113883.3.19.2.3","value":"666666"}],"name":"XYZ Insurance","alias":["ABC Insurance"],"contact":[{"telecom":[{"system":"phone","value":"+1 555 234 3523","use":"work"},{"system":"email","value":"info@xyz-payer.org","use":"work"}]}]}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
{
2+
"resourceType": "Patient",
3+
"id": "ExamplePatient",
4+
"meta": {
5+
"lastUpdated": "2020-07-07T13:26:22.0314215+00:00",
6+
"profile": [
7+
"http://hl7.org/fhir/us/identity-matching/StructureDefinition/IDI-Patient"
8+
]
9+
},
10+
"language": "en-US",
11+
"text": {
12+
"status": "generated",
13+
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\"><p class=\"res-header-id\"><b>Generated Narrative: Patient ExamplePatient</b></p><a name=\"ExamplePatient\"> </a><a name=\"hcExamplePatient\"> </a><a name=\"ExamplePatient-en-US\"> </a><div style=\"display: inline-block; background-color: #d9e0e7; padding: 6px; margin: 4px; border: 1px solid #8da1b4; border-radius: 5px; line-height: 60%\"><p style=\"margin-bottom: 0px\">Last updated: 2020-07-07 13:26:22+0000; Language: en-US</p><p style=\"margin-bottom: 0px\">Profile: <a href=\"StructureDefinition-IDI-Patient.html\">IDI Patient</a></p></div><p style=\"border: 1px #661aff solid; background-color: #e6e6ff; padding: 10px;\">Johnny Beegood Male, DoB: 1986-05-01 ( Member Number)</p><hr/><table class=\"grid\"><tr><td style=\"background-color: #f3f5da\" title=\"Record is active\">Active:</td><td>true</td><td style=\"background-color: #f3f5da\" title=\"Known Marital status of Patient\">Marital Status:</td><td colspan=\"3\"><span title=\"Codes:{http://terminology.hl7.org/CodeSystem/v3-NullFlavor UNK}\">unknown</span></td></tr><tr><td style=\"background-color: #f3f5da\" title=\"Ways to contact the Patient\">Contact Detail</td><td colspan=\"3\"><ul><li>ph: 301-555-2112(Mobile)</li><li>123 Main Street Pittsburgh PA 12519 </li></ul></td></tr></table></div>"
14+
},
15+
"identifier": [
16+
{
17+
"type": {
18+
"coding": [
19+
{
20+
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
21+
"code": "MB"
22+
}
23+
]
24+
},
25+
"system": "https://www.xyzhealthplan.com/fhir/memberidentifier",
26+
"value": "1234-234-1243-12345678901"
27+
}
28+
],
29+
"active": true,
30+
"name": [
31+
{
32+
"family": "Beegood",
33+
"given": [
34+
"Johnny"
35+
]
36+
}
37+
],
38+
"telecom": [
39+
{
40+
"system": "phone",
41+
"value": "301-555-2112",
42+
"use": "mobile"
43+
}
44+
],
45+
"gender": "male",
46+
"birthDate": "1986-05-01",
47+
"address": [
48+
{
49+
"type": "physical",
50+
"line": [
51+
"123 Main Street"
52+
],
53+
"city": "Pittsburgh",
54+
"state": "PA",
55+
"postalCode": "12519"
56+
}
57+
],
58+
"maritalStatus": {
59+
"coding": [
60+
{
61+
"system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor",
62+
"code": "UNK"
63+
}
64+
]
65+
}
66+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
{
2+
"resourceType": "Patient",
3+
"id": "ExamplePatientL0",
4+
"meta": {
5+
"lastUpdated": "2021-11-01T13:26:22.0314215+00:00",
6+
"profile": [
7+
"http://hl7.org/fhir/us/identity-matching/StructureDefinition/IDI-Patient-L0"
8+
]
9+
},
10+
"language": "en-US",
11+
"text": {
12+
"status": "generated",
13+
"div": "<div xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en-US\" lang=\"en-US\"><p class=\"res-header-id\"><b>Generated Narrative: Patient ExamplePatientL0</b></p><a name=\"ExamplePatientL0\"> </a><a name=\"hcExamplePatientL0\"> </a><a name=\"ExamplePatientL0-en-US\"> </a><div style=\"display: inline-block; background-color: #d9e0e7; padding: 6px; margin: 4px; border: 1px solid #8da1b4; border-radius: 5px; line-height: 60%\"><p style=\"margin-bottom: 0px\">Last updated: 2021-11-01 13:26:22+0000; Language: en-US</p><p style=\"margin-bottom: 0px\">Profile: <a href=\"StructureDefinition-IDI-Patient-L0.html\">IDI Patient L0</a></p></div><p style=\"border: 1px #661aff solid; background-color: #e6e6ff; padding: 10px;\">Nancy Paeshent Female, DoB: 1988-02-11 ( Medical record number)</p><hr/><table class=\"grid\"><tr><td style=\"background-color: #f3f5da\" title=\"Record is active\">Active:</td><td>true</td><td style=\"background-color: #f3f5da\" title=\"Known Marital status of Patient\">Marital Status:</td><td colspan=\"3\"><span title=\"Codes:{http://terminology.hl7.org/CodeSystem/v3-NullFlavor UNK}\">unknown</span></td></tr><tr><td style=\"background-color: #f3f5da\" title=\"Ways to contact the Patient\">Contact Detail</td><td colspan=\"3\">321 South Maple Street Scranton PA 18503 </td></tr></table></div>"
14+
},
15+
"identifier": [
16+
{
17+
"type": {
18+
"coding": [
19+
{
20+
"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
21+
"code": "MR"
22+
}
23+
]
24+
},
25+
"system": "https://www.xyzhealthplan.com/fhir/memberidentifier",
26+
"value": "4004-202-9999-12345678901"
27+
}
28+
],
29+
"active": true,
30+
"name": [
31+
{
32+
"family": "Paeshent",
33+
"given": [
34+
"Nancy"
35+
]
36+
}
37+
],
38+
"gender": "female",
39+
"birthDate": "1988-02-11",
40+
"address": [
41+
{
42+
"type": "physical",
43+
"line": [
44+
"321 South Maple Street"
45+
],
46+
"city": "Scranton",
47+
"state": "PA",
48+
"postalCode": "18503"
49+
}
50+
],
51+
"maritalStatus": {
52+
"coding": [
53+
{
54+
"system": "http://terminology.hl7.org/CodeSystem/v3-NullFlavor",
55+
"code": "UNK"
56+
}
57+
]
58+
}
59+
}

0 commit comments

Comments
 (0)