Skip to content

Commit 08802d2

Browse files
authored
Merge pull request #982 from b2ihealthcare/issue/FHIR_version_URI_validation
fix(fhir): Validate system URL against version given in subsumption request
2 parents 0ee6ca0 + 7320746 commit 08802d2

File tree

2 files changed

+63
-69
lines changed

2 files changed

+63
-69
lines changed

fhir/com.b2international.snowowl.fhir.rest.tests/src/com/b2international/snowowl/fhir/rest/tests/codesystem/FhirCodeSystemSubsumesOperationTest.java

+32-35
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public class FhirCodeSystemSubsumesOperationTest extends FhirRestTest {
3434

3535
private static final String PROCEDURE = "71388002";
3636
private static final String ORGANISM_TOP_LEVEL = "410607006";
37+
private static final Object MICROORGANISM = "264395009";
3738

3839
@Test
3940
public void GET_CodeSystem_$subsumes_Subsumes() throws Exception {
@@ -87,39 +88,35 @@ public class FhirCodeSystemSubsumesOperationTest extends FhirRestTest {
8788
.body("parameter[0].valueCode", equalTo(SubsumptionType.EQUIVALENT.name()));
8889
}
8990

90-
// @Test
91-
// public void subsumedByWithVersionTest() throws Exception {
92-
//
93-
// String responseString = givenAuthenticatedRequest(FHIR_ROOT_CONTEXT)
94-
// .queryParam("codeA", BACTERIA) //Bacteria
95-
// .queryParam("codeB", MICROORGANISM) //Microorganism (parent)
96-
// .queryParam("system", "http://snomed.info/sct/900000000000207008/version/20180131")
97-
// .when().get(CODESYSTEM_SUBSUMES)
98-
// .then().assertThat()
99-
// .statusCode(200)
100-
// .extract().asString();
101-
//
102-
// SubsumptionResult result = convertToSubsumptionResult(responseString);
103-
// Assert.assertEquals(SubsumptionType.SUBSUMED_BY, result.getOutcome());
104-
// }
105-
//
106-
// //invalid
107-
// @Test
108-
// public void twoVersionsTest() throws Exception {
109-
//
110-
// givenAuthenticatedRequest(FHIR_ROOT_CONTEXT)
111-
// .queryParam("codeA", BACTERIA) //Bacteria
112-
// .queryParam("codeB", MICROORGANISM) //Microorganism (parent)
113-
// .queryParam("system", "http://snomed.info/sct/900000000000207008/version/20170131")
114-
// .queryParam("version", "2018-01-31")
115-
// .when().get(CODESYSTEM_SUBSUMES)
116-
// .then()
117-
// .body("resourceType", equalTo("OperationOutcome"))
118-
// .body("issue.severity", hasItem("error"))
119-
// .body("issue.code", hasItem("invalid"))
120-
// .body("issue.diagnostics", hasItem("Version specified in the URI [http://snomed.info/sct/900000000000207008/version/20170131] "
121-
// + "does not match the version set in the request [2018-01-31]"))
122-
// .statusCode(400);
123-
// }
91+
@Test
92+
public void GET_CodeSystem_$subsumes_SubsumedBy_WithVersion() throws Exception {
93+
94+
givenAuthenticatedRequest(FHIR_ROOT_CONTEXT)
95+
.queryParam("codeA", BACTERIA) //Bacteria
96+
.queryParam("codeB", MICROORGANISM) //Microorganism (parent)
97+
.queryParam("system", "http://snomed.info/sct/900000000000207008/version/20180131")
98+
.when().get(CODESYSTEM_SUBSUMES)
99+
.then().assertThat()
100+
.statusCode(200)
101+
.body("parameter[0].name", equalTo("outcome"))
102+
.body("parameter[0].valueCode", equalTo(SubsumptionType.SUBSUMED_BY.name()));
103+
}
124104

125-
}
105+
@Test
106+
public void GET_CodeSystem_$subsumes_SubsumedBy_WithAmbiguousVersions() throws Exception {
107+
108+
givenAuthenticatedRequest(FHIR_ROOT_CONTEXT)
109+
.queryParam("codeA", BACTERIA) //Bacteria
110+
.queryParam("codeB", MICROORGANISM) //Microorganism (parent)
111+
.queryParam("system", "http://snomed.info/sct/900000000000207008/version/20170131")
112+
.queryParam("version", "2018-01-31")
113+
.when().get(CODESYSTEM_SUBSUMES)
114+
.then()
115+
.body("resourceType", equalTo("OperationOutcome"))
116+
.body("issue[0].severity", equalTo("error"))
117+
.body("issue[0].code", equalTo("invalid"))
118+
.body("issue[0].diagnostics", equalTo("Version specified in the URI [http://snomed.info/sct/900000000000207008/version/20170131] "
119+
+ "does not match the version set in the request [2018-01-31]"))
120+
.statusCode(400);
121+
}
122+
}

fhir/com.b2international.snowowl.fhir.rest/src/com/b2international/snowowl/fhir/rest/FhirCodeSystemSubsumesOperationController.java

+31-34
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2021 B2i Healthcare Pte Ltd, http://b2i.sg
2+
* Copyright 2021-2022 B2i Healthcare Pte Ltd, http://b2i.sg
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -15,9 +15,9 @@
1515
*/
1616
package com.b2international.snowowl.fhir.rest;
1717

18-
import org.springframework.util.StringUtils;
1918
import org.springframework.web.bind.annotation.*;
2019

20+
import com.b2international.commons.StringUtils;
2121
import com.b2international.snowowl.core.events.util.Promise;
2222
import com.b2international.snowowl.fhir.core.exceptions.BadRequestException;
2323
import com.b2international.snowowl.fhir.core.model.codesystem.SubsumptionRequest;
@@ -190,51 +190,48 @@ private void validateSubsumptionRequest(String codeSystemId, String codeA, Strin
190190

191191
private void validateSubsumptionRequest(String codeSystemId, String codeA, String codeB, String system, String version, Coding codingA, Coding codingB) {
192192

193-
//check the systems
193+
// check the systems
194194
if (StringUtils.isEmpty(system) && StringUtils.isEmpty(codeSystemId)) {
195195
throw new BadRequestException("Parameter 'system' is not specified for subsumption testing.", "SubsumptionRequest.system");
196196
}
197197

198-
//TODO: this probably incorrect as codeSystemId is an internal id vs. system that is external
199-
if (!StringUtils.isEmpty(system) && !StringUtils.isEmpty(codeSystemId)) {
200-
if (!codeSystemId.equals(system)) {
201-
throw new BadRequestException(String.format("Parameter 'system: %s' and path parameter 'codeSystem: %s' are not the same.", system, codeSystemId), "SubsumptionRequest.system");
202-
}
203-
}
204-
205-
//all empty
206-
if (StringUtils.isEmpty(codeA) && StringUtils.isEmpty(codeA) && codingA == null && codingB == null) {
207-
throw new BadRequestException("No codes or Codings are provided for subsumption testing.", "SubsumptionRequest");
198+
// TODO: this probably incorrect as codeSystemId is an internal id vs. system that is external
199+
if (!StringUtils.isEmpty(system) && !StringUtils.isEmpty(codeSystemId) && !codeSystemId.equals(system)) {
200+
throw new BadRequestException(String.format("Parameter 'system: %s' and path parameter 'codeSystem: %s' are not the same.", system, codeSystemId), "SubsumptionRequest.system");
208201
}
209202

210-
//No codes
211-
if (StringUtils.isEmpty(codeA) && StringUtils.isEmpty(codeA)) {
203+
if (StringUtils.isEmpty(codeA) && StringUtils.isEmpty(codeB)) {
204+
// No codes and no codings
205+
if (codingA == null && codingB == null) {
206+
throw new BadRequestException("No codes or Codings are provided for subsumption testing.", "SubsumptionRequest");
207+
}
208+
209+
// One coding is present, but the other is missing (both can not be missing as it was handled above)
212210
if (codingA == null || codingB == null) {
213211
throw new BadRequestException("No Codings are provided for subsumption testing.", "SubsumptionRequest.Coding");
214212
}
215-
}
216-
217-
//No codings
218-
if (codingA == null && codingB == null) {
219-
if (StringUtils.isEmpty(codeA) || StringUtils.isEmpty(codeB)) {
220-
throw new BadRequestException("No codes are provided for subsumption testing.", "SubsumptionRequest.code");
221-
}
222-
}
223-
224-
//Codes are there
225-
if (!StringUtils.isEmpty(codeA) && !StringUtils.isEmpty(codeA)) {
213+
214+
// Both codings are present at this point
215+
216+
} else {
217+
218+
// Some codes were provided, but a coding is also present, ambiguous
226219
if (codingA != null || codingB != null) {
227220
throw new BadRequestException("Provide either codes or Codings.", "SubsumptionRequest");
228221
}
229-
}
230-
231-
//Coding are there
232-
if (codingA != null && codingB != null) {
233-
if (!StringUtils.isEmpty(codeA) || !StringUtils.isEmpty(codeA)) {
234-
throw new BadRequestException("Provide either codes or Codings.", "SubsumptionRequest");
222+
223+
// One code is present, but the other is missing (both can not be missing as it was handled in the outer "if" block above)
224+
if (StringUtils.isEmpty(codeA) || StringUtils.isEmpty(codeB)) {
225+
throw new BadRequestException("No codes are provided for subsumption testing.", "SubsumptionRequest.code");
235226
}
227+
228+
// Both codes are present at this point
236229
}
237-
}
238230

239-
231+
// Check system (URL) against version
232+
if (!StringUtils.isEmpty(system) && !StringUtils.isEmpty(version) && !system.endsWith("/" + version)) {
233+
throw new BadRequestException(String.format("Version specified in the URI [%s] does not match the version set in the request [%s]",
234+
system, version));
235+
}
236+
}
240237
}

0 commit comments

Comments
 (0)