Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Minor FHIR API fixes #1266

Merged
merged 7 commits into from
Mar 18, 2024
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.function.Function;
import java.util.stream.Collectors;

import org.elasticsearch.index.query.RegexpFlag;
import org.elasticsearch.script.Script;
import org.slf4j.Logger;

Expand Down Expand Up @@ -467,7 +468,7 @@
}

private void visit(RegexpPredicate regexp) {
deque.push(QueryBuilders.regexp(r -> r.boost(this.boost).field(toFieldPath(regexp)).value(regexp.getArgument()).caseInsensitive(regexp.isCaseInsensitive())));
deque.push(QueryBuilders.regexp(r -> r.boost(this.boost).field(toFieldPath(regexp)).value(regexp.getArgument()).caseInsensitive(regexp.isCaseInsensitive()).flags(RegexpFlag.NONE.name())));

Check warning on line 471 in commons/com.b2international.index/src/com/b2international/index/es/query/Es8QueryBuilder.java

View check run for this annotation

Codecov / codecov/patch

commons/com.b2international.index/src/com/b2international/index/es/query/Es8QueryBuilder.java#L471

Added line #L471 was not covered by tests
}

private void visit(RangePredicate<?> range) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ private void visit(PrefixPredicate predicate) {
}

private void visit(RegexpPredicate regexp) {
deque.push(QueryBuilders.regexpQuery(toFieldPath(regexp), regexp.getArgument()).caseInsensitive(regexp.isCaseInsensitive()));
deque.push(QueryBuilders.regexpQuery(toFieldPath(regexp), regexp.getArgument()).caseInsensitive(regexp.isCaseInsensitive()).flags(RegexpFlag.NONE));
}

private void visit(RangePredicate<?> range) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ public void ensureUrlIsUniqueGlobally() throws Exception {
// create a resource with ID
var codeSystemId = IDs.base62UUID();
CodeSystemRestRequests.createCodeSystem(codeSystemId).statusCode(201);
var codeSystemUrlToUse = CodeSystemRestRequests.getCodeSystemUrl(codeSystemId);
var codeSystemUrlToUse = CodeSystemRestRequests.getSnomedIntUrl(codeSystemId);

// simulate that the user only has access to another resource
String token = RestExtensions.generateToken(Permission.requireAll(Permission.OPERATION_BROWSE, "another-resource"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public Builder inactive(final boolean isInactive) {

@JsonProperty("include")
@JsonFormat(with = JsonFormat.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)
public Builder profiles(Collection<Include> includes) {
public Builder includes(Collection<Include> includes) {
this.includes = includes;
return this;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2021-2023 B2i Healthcare, https://b2ihealthcare.com
* Copyright 2021-2024 B2i Healthcare, https://b2ihealthcare.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,16 +15,21 @@
*/
package com.b2international.snowowl.fhir.core.request.codesystem;

import java.util.Optional;

import com.b2international.commons.CompareUtils;
import com.b2international.commons.exceptions.NotFoundException;
import com.b2international.commons.http.AcceptLanguageHeader;
import com.b2international.snowowl.core.RepositoryManager;
import com.b2international.snowowl.core.ServiceProvider;
import com.b2international.snowowl.core.events.Request;
import com.b2international.snowowl.core.uri.ResourceURLSchemaSupport;
import com.b2international.snowowl.fhir.core.model.ResourceResponseEntry;
import com.b2international.snowowl.fhir.core.model.codesystem.CodeSystem;
import com.b2international.snowowl.fhir.core.model.dt.Code;
import com.b2international.snowowl.fhir.core.request.FhirRequests;
import com.b2international.snowowl.fhir.core.search.Summary;
import com.google.common.base.Strings;

/**
* @since 8.0
Expand All @@ -45,7 +50,42 @@ public FhirRequest(String system, String version) {

@Override
public final R execute(ServiceProvider context) {
CodeSystem codeSystem = FhirRequests
// try as is via the URL + version (optional) config
CodeSystem codeSystem = fetchCodeSystemByUrlAndVersion(context)
.or(() -> fetchCodeSystemByIdAndVersion(context))
.or(() -> {
// perform the third step only if there is a version specified
if (Strings.isNullOrEmpty(version)) {
return Optional.empty();
} else {
return fetchCodeSystemByUrl(context, system)
// if there is a codesystem with the specified URL then construct a versioned form using its official URL schema from its tooling
.flatMap((cs) -> fetchCodeSystemByUrl(context, context.service(RepositoryManager.class).get(cs.getToolingId()).service(ResourceURLSchemaSupport.class).withVersion(system, version, null)));
}
})
.orElseThrow(() -> new NotFoundException("CodeSystem", system));

return doExecute(context, codeSystem);
}

private Optional<? extends CodeSystem> fetchCodeSystemByIdAndVersion(ServiceProvider context) {
return FhirRequests
.codeSystems().prepareSearch()
.one()
.filterById(system)
.filterByVersion(version)
.setSummary(configureSummary())
.buildAsync()
.getRequest()
.execute(context)
.first()
.map(ResourceResponseEntry.class::cast)
.map(ResourceResponseEntry::getResponseResource)
.map(CodeSystem.class::cast);
}

private Optional<CodeSystem> fetchCodeSystemByUrlAndVersion(ServiceProvider context) {
return FhirRequests
.codeSystems().prepareSearch()
.one()
.filterByUrl(system)
Expand All @@ -57,25 +97,22 @@ public final R execute(ServiceProvider context) {
.first()
.map(ResourceResponseEntry.class::cast)
.map(ResourceResponseEntry::getResponseResource)
.map(CodeSystem.class::cast)
.or(() -> {
return FhirRequests
.codeSystems().prepareSearch()
.one()
.filterById(system)
.filterByVersion(version)
.setSummary(configureSummary())
.buildAsync()
.getRequest()
.execute(context)
.first()
.map(ResourceResponseEntry.class::cast)
.map(ResourceResponseEntry::getResponseResource)
.map(CodeSystem.class::cast);
})
.orElseThrow(() -> new NotFoundException("CodeSystem", system));

return doExecute(context, codeSystem);
.map(CodeSystem.class::cast);
}

private Optional<CodeSystem> fetchCodeSystemByUrl(ServiceProvider context, String url) {
return FhirRequests
.codeSystems().prepareSearch()
.one()
.filterByUrl(url)
.setSummary(configureSummary())
.buildAsync()
.getRequest()
.execute(context)
.first()
.map(ResourceResponseEntry.class::cast)
.map(ResourceResponseEntry::getResponseResource)
.map(CodeSystem.class::cast);
}

protected String configureSummary() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
<setEntry value="org.apache.commons.cli@default:default"/>
<setEntry value="org.apache.commons.commons-codec@default:default"/>
<setEntry value="org.apache.commons.commons-collections4@default:default"/>
<setEntry value="org.apache.commons.commons-compress@default:default"/>
<setEntry value="org.apache.commons.commons-io@default:default"/>
<setEntry value="org.apache.commons.lang3@default:default"/>
<setEntry value="org.apache.commons.logging@default:default"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import com.b2international.snowowl.fhir.core.model.codesystem.LookupRequest;
import com.b2international.snowowl.fhir.core.model.dt.Coding;
import com.b2international.snowowl.fhir.tests.FhirRestTest;
import com.b2international.snowowl.snomed.common.SnomedTerminologyComponentConstants;
import com.b2international.snowowl.snomed.common.SnomedConstants.Concepts;
import com.b2international.snowowl.test.commons.codesystem.CodeSystemRestRequests;

Expand Down Expand Up @@ -87,7 +88,26 @@ public class FhirCodeSystemLookupOperationTest extends FhirRestTest {
@Test
public void GET_CodeSystem_$lookup_Existing_Versioned() throws Exception {
givenAuthenticatedRequest(FHIR_ROOT_CONTEXT)
.queryParam("system", CodeSystemRestRequests.getCodeSystemUrl("version/20020131"))
.queryParam("system", CodeSystemRestRequests.getSnomedIntUrl("version/20020131"))
.queryParam("code", Concepts.ROOT_CONCEPT)
.queryParam("_format", "json")
.when().get(CODESYSTEM_LOOKUP)
.then().assertThat()
.statusCode(200)
.body("resourceType", equalTo("Parameters"))
.body("parameter[0].name", equalTo("name"))
.body("parameter[0].valueString", equalTo("SNOMEDCT/2002-01-31"))
.body("parameter[1].name", equalTo("version"))
.body("parameter[1].valueString", equalTo("2002-01-31"))
.body("parameter[2].name", equalTo("display"))
.body("parameter[2].valueString", equalTo("SNOMED CT Concept"));
}

@Test
public void GET_CodeSystem_$lookup_Existing_Versioned_ViaVersionField() throws Exception {
givenAuthenticatedRequest(FHIR_ROOT_CONTEXT)
.queryParam("system", String.join("/", SnomedTerminologyComponentConstants.SNOMED_URI_SCT, Concepts.MODULE_SCT_CORE))
.queryParam("version", "20020131")
.queryParam("code", Concepts.ROOT_CONCEPT)
.queryParam("_format", "json")
.when().get(CODESYSTEM_LOOKUP)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,6 @@ public class FhirRestTest extends FhirTest {

public static final String FHIR_ROOT_CONTEXT = "/fhir"; //$NON-NLS-N$

protected static final String SNOMED_VERSION = "2018-07-31";

public static final String SNOMEDCT_URL = SnomedTerminologyComponentConstants.SNOMED_URI_SCT + "/900000000000207008";

public static final class Endpoints {
Expand Down Expand Up @@ -74,7 +72,7 @@ public void after() {
}

protected final String getTestCodeSystemUrl() {
return CodeSystemRestRequests.getCodeSystemUrl(getTestCodeSystemId());
return CodeSystemRestRequests.getSnomedIntUrl(getTestCodeSystemId());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ public Promise<ResponseEntity<byte[]>> subsumes(
@ApiResponse(responseCode = "200", description = "OK")
@ApiResponse(responseCode = "400", description = "Bad request")
@ApiResponse(responseCode = "404", description = "Code system not found")
@GetMapping(value = "/{codeSystemId:**}/$subsumes", produces = {
@GetMapping(value = "/{id:**}/$subsumes", produces = {
APPLICATION_FHIR_JSON_VALUE,
APPLICATION_FHIR_XML_VALUE,
TEXT_JSON_VALUE,
Expand All @@ -153,7 +153,7 @@ public Promise<ResponseEntity<byte[]>> subsumes(
public Promise<ResponseEntity<byte[]>> subsumes(

@Parameter(description = "The id of the code system to invoke the operation on")
@PathVariable("codeSystemId")
@PathVariable("id")
String codeSystemId,

@Parameter(description = "The \"A\" code that is to be tested")
Expand Down Expand Up @@ -293,7 +293,7 @@ public Promise<ResponseEntity<byte[]>> subsumes(
@ApiResponse(responseCode = "404", description = "Not found")
@ApiResponse(responseCode = "400", description = "Bad request")
@PostMapping(
value = "/{codeSystemId:**}/$subsumes",
value = "/{id:**}/$subsumes",
consumes = {
APPLICATION_FHIR_JSON_VALUE,
APPLICATION_FHIR_XML_VALUE,
Expand All @@ -314,7 +314,7 @@ public Promise<ResponseEntity<byte[]>> subsumes(
public Promise<ResponseEntity<byte[]>> subsumes(

@Parameter(description = "The id of the code system to invoke the operation on")
@PathVariable("codeSystemId")
@PathVariable("id")
String codeSystemId,

@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The operation's input parameters", content = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ public Promise<ResponseEntity<byte[]>> validateCode(
@ApiResponse(responseCode = "400", description = "Bad request"),
@ApiResponse(responseCode = "404", description = "Code system not found")
})
@GetMapping(value = "/{codeSystemId:**}/$validate-code", produces = {
@GetMapping(value = "/{id:**}/$validate-code", produces = {
APPLICATION_FHIR_JSON_VALUE,
APPLICATION_FHIR_XML_VALUE,
TEXT_JSON_VALUE,
Expand All @@ -268,7 +268,7 @@ public Promise<ResponseEntity<byte[]>> validateCode(
public Promise<ResponseEntity<byte[]>> validateCodeInstance(

@Parameter(description = "The id of the code system to validate against")
@PathVariable(value = "codeSystemId")
@PathVariable(value = "id")
String codeSystemId,

@Parameter(description = "The code to be validated")
Expand Down Expand Up @@ -330,7 +330,7 @@ public Promise<ResponseEntity<byte[]>> validateCodeInstance(
/**
* <code><b>POST /CodeSystem/{id}/$validate-code</b></code>
* <p>
* All parameters are in the request body, except the codeSystemId.
* All parameters are in the request body, except the id.
*
* @param codeSystemId
* @param requestBody - an {@link InputStream} whose contents can be deserialized to FHIR parameters
Expand All @@ -348,7 +348,7 @@ public Promise<ResponseEntity<byte[]>> validateCodeInstance(
@ApiResponse(responseCode = "404", description = "Not found")
@ApiResponse(responseCode = "400", description = "Bad request")
@PostMapping(
value = "/{codeSystemId:**}/$validate-code",
value = "/{id:**}/$validate-code",
consumes = {
APPLICATION_FHIR_JSON_VALUE,
APPLICATION_FHIR_XML_VALUE,
Expand All @@ -369,7 +369,7 @@ public Promise<ResponseEntity<byte[]>> validateCodeInstance(
public Promise<ResponseEntity<byte[]>> validateCode(

@Parameter(description = "The id of the code system to validate against")
@PathVariable(value = "codeSystemId")
@PathVariable(value = "id")
String codeSystemId,

@io.swagger.v3.oas.annotations.parameters.RequestBody(description = "The operation's input parameters", content = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ public Promise<ResponseEntity<byte[]>> translate(
@ApiResponse(responseCode = "200", description = "OK")
@ApiResponse(responseCode = "400", description = "Bad request")
@ApiResponse(responseCode = "404", description = "Concept map not found")
@GetMapping(value = "/{conceptMapId:**}/$translate", produces = {
@GetMapping(value = "/{id:**}/$translate", produces = {
APPLICATION_FHIR_JSON_VALUE,
APPLICATION_FHIR_XML_VALUE,
TEXT_JSON_VALUE,
Expand All @@ -267,7 +267,7 @@ public Promise<ResponseEntity<byte[]>> translate(
public Promise<ResponseEntity<byte[]>> translateInstance(

@Parameter(description = "The id of the Concept Map to base the translation on")
@PathVariable("conceptMapId")
@PathVariable("id")
String conceptMapId,

@Parameter(description = "The code to translate")
Expand Down
Loading
Loading