diff --git a/docs/src/pages/guides/FHIRServerUsersGuide.md b/docs/src/pages/guides/FHIRServerUsersGuide.md index 756edd26503..c6f74a61298 100644 --- a/docs/src/pages/guides/FHIRServerUsersGuide.md +++ b/docs/src/pages/guides/FHIRServerUsersGuide.md @@ -1958,6 +1958,8 @@ This section contains reference information about each of the configuration prop |`fhirServer/core/defaultPageSize`|integer|Sets the page size for search and history request results when no `_count` parameter is specified.| |`fhirServer/core/maxPageSize`|integer|Sets the maximum page size for search and history request results. If a user-specified `_count` parameter value exceeds the maximum page size, then a warning is logged and the maximum page size will be used.| |`fhirServer/core/maxPageIncludeCount`|integer|Sets the maximum number of 'include' resources allowed per page for search and history request results. If the number of 'include' resources returned for a page of results from a search or history request will exceed the maximum number of 'include' resources allowed per page, then an error will be returned in the request results.| +|`fhirServer/core/capabilitiesUrl`|string|The URL that is embedded in the default Capabilities statement| +|`fhirServer/term/capabilitiesUrl`|string|The URL that is embedded in the Terminology Capabilities statement using `mode=terminology`| |`fhirServer/term/disableCaching`|boolean|Indicates whether caching is disabled for the FHIR terminology module, this includes caching in `CodeSystemSupport`, `ValueSetSupport`, `GraphTermServiceProvider`, and `RemoteTermServiceProvider`| |`fhirServer/term/graphTermServiceProviders`|array of objects|The `graphTermServiceProviders` element is an array of objects| |`fhirServer/term/graphTermServiceProviders/enabled`|boolean|Indicates whether the graph term service provider should be used by the FHIR term service to access code system content| @@ -2114,6 +2116,8 @@ This section contains reference information about each of the configuration prop |`fhirServer/core/defaultPageSize`|10| |`fhirServer/core/maxPageSize`|1000| |`fhirServer/core/maxPageIncludeCount`|1000| +|`fhirServer/core/capabilitiesUrl`|string|null| +|`fhirServer/term/capabilitiesUrl`|string|null| |`fhirServer/term/cachingDisabled`|false| |`fhirServer/term/graphTermServiceProviders/enabled`|false| |`fhirServer/term/graphTermServiceProviders/timeLimit`|90000| @@ -2240,6 +2244,7 @@ must restart the server for that change to take effect. |`fhirServer/core/defaultPageSize`|Y|Y| |`fhirServer/core/maxPageSize`|Y|Y| |`fhirServer/core/maxPageIncludeCount`|Y|Y| +|`fhirServer/core/capabilitiesUrl`|Y|Y| |`fhirServer/term/cachingDisabled`|N|N| |`fhirServer/term/graphTermServiceProviders/enabled`|N|N| |`fhirServer/term/graphTermServiceProviders/timeLimit`|N|N| @@ -2252,6 +2257,7 @@ must restart the server for that change to take effect. |`fhirServer/term/remoteTermServiceProviders/headers`|N|N| |`fhirServer/term/remoteTermServiceProviders/httpTimeout`|N|N| |`fhirServer/term/remoteTermServiceProviders/supports`|N|N| +|`fhirServer/term/capabilitiesUrl`|Y|Y| |`fhirServer/resources/open`|Y|Y| |`fhirServer/resources/Resource/interactions`|Y|Y| |`fhirServer/resources/Resource/searchParameters`|Y|Y| diff --git a/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java b/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java index 67d044e3856..c7fab53cd0f 100644 --- a/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java +++ b/fhir-config/src/main/java/com/ibm/fhir/config/FHIRConfiguration.java @@ -40,8 +40,10 @@ public class FHIRConfiguration { public static final String PROPERTY_DEFAULT_PAGE_SIZE = "fhirServer/core/defaultPageSize"; public static final String PROPERTY_MAX_PAGE_SIZE = "fhirServer/core/maxPageSize"; public static final String PROPERTY_MAX_PAGE_INCLUDE_COUNT = "fhirServer/core/maxPageIncludeCount"; + public static final String PROPERTY_CAPABILITIES_URL = "fhirServer/core/capabilitiesUrl"; // Terminology service properties + public static final String PROPERTY_TERM_SERVICE_CAPABILITIES_URL = "fhirServer/term/capabilitiesUrl"; public static final String PROPERTY_GRAPH_TERM_SERVICE_PROVIDER_ENABLED = "fhirServer/term/graphTermServiceProvider/enabled"; public static final String PROPERTY_GRAPH_TERM_SERVICE_PROVIDER_TIME_LIMIT = "fhirServer/term/graphTermServiceProvider/timeLimit"; public static final String PROPERTY_GRAPH_TERM_SERVICE_PROVIDER_CONFIGURATION = "fhirServer/term/graphTermServiceProvider/configuration"; diff --git a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/BasicServerTest.java b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/BasicServerTest.java index 40e2eb4fb96..c6cca3022af 100644 --- a/fhir-server-test/src/test/java/com/ibm/fhir/server/test/BasicServerTest.java +++ b/fhir-server-test/src/test/java/com/ibm/fhir/server/test/BasicServerTest.java @@ -1,5 +1,5 @@ /* - * (C) Copyright IBM Corp. 2017, 2020 + * (C) Copyright IBM Corp. 2017, 2021 * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +14,8 @@ import java.io.StringWriter; import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; import java.util.List; import javax.json.JsonObject; @@ -33,6 +35,7 @@ import com.ibm.fhir.model.resource.OperationOutcome; import com.ibm.fhir.model.resource.Patient; import com.ibm.fhir.model.resource.Resource; +import com.ibm.fhir.model.resource.TerminologyCapabilities; import com.ibm.fhir.model.test.TestUtil; import com.ibm.fhir.model.type.ContactPoint; import com.ibm.fhir.model.type.Narrative; @@ -40,6 +43,11 @@ import com.ibm.fhir.model.type.code.ContactPointSystem; import com.ibm.fhir.model.type.code.ContactPointUse; import com.ibm.fhir.model.type.code.NarrativeStatus; +import com.ibm.fhir.path.FHIRPathBooleanValue; +import com.ibm.fhir.path.FHIRPathNode; +import com.ibm.fhir.path.evaluator.FHIRPathEvaluator; +import com.ibm.fhir.path.evaluator.FHIRPathEvaluator.EvaluationContext; +import com.ibm.fhir.path.exception.FHIRPathException; /** * Basic sniff test of the FHIR Server. @@ -52,7 +60,7 @@ public class BasicServerTest extends FHIRServerTestBase { * Verify the 'metadata' API. */ @Test(groups = { "server-basic" }) - public void testMetadataAPI() { + public void testMetadataAPI() throws FHIRPathException { WebTarget target = getWebTarget(); Response response = target.path("metadata").request().get(); assertResponse(response, Response.Status.OK.getStatusCode()); @@ -63,6 +71,40 @@ public void testMetadataAPI() { assertEquals(6, conf.getFormat().size()); assertNotNull(conf.getVersion()); assertNotNull(conf.getName()); + + FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator(); + EvaluationContext evaluationContext = new EvaluationContext(conf); + Collection result = evaluator.evaluate(evaluationContext, "(kind != 'instance') or implementation.exists()"); + Iterator iter = result.iterator(); + boolean instance = false; + while (iter.hasNext()) { + FHIRPathBooleanValue node = iter.next().as(FHIRPathBooleanValue.class); + instance = node._boolean(); + } + assertTrue(instance); + } + + @Test(groups = { "server-basic" }) + public void testMetadataAPITerminology() throws FHIRPathException { + WebTarget target = getWebTarget(); + Response response = target.path("metadata").queryParam("mode", "terminology").request().get(); + assertResponse(response, Response.Status.OK.getStatusCode()); + + TerminologyCapabilities conf = response.readEntity(TerminologyCapabilities.class); + assertNotNull(conf); + assertNotNull(conf.getVersion()); + assertNotNull(conf.getName()); + + FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator(); + EvaluationContext evaluationContext = new EvaluationContext(conf); + Collection result = evaluator.evaluate(evaluationContext, "(kind != 'instance') or implementation.exists()"); + Iterator iter = result.iterator(); + boolean instance = false; + while (iter.hasNext()) { + FHIRPathBooleanValue node = iter.next().as(FHIRPathBooleanValue.class); + instance = node._boolean(); + } + assertTrue(instance); } /** diff --git a/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java b/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java index 656b56fc3ce..3d9a57becdf 100644 --- a/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java +++ b/fhir-server/src/main/java/com/ibm/fhir/server/resources/Capabilities.java @@ -194,6 +194,24 @@ private Resource computeCapabilityStatement(String mode) { private TerminologyCapabilities buildTerminologyCapabilities() { FHIRBuildIdentifier buildInfo = new FHIRBuildIdentifier(); String buildDescription = FHIR_SERVER_NAME + " version " + buildInfo.getBuildVersion() + " build id " + buildInfo.getBuildId() + ""; + + /* + * The following checks to see if there is a Terminology Service URL that we want to inline into the Terminology Capabilities Statement + * else the minimal implementation.description. + */ + String customTerminologyImpl = FHIRConfigHelper.getStringProperty(FHIRConfiguration.PROPERTY_TERM_SERVICE_CAPABILITIES_URL, null); + TerminologyCapabilities.Implementation impl; + if (customTerminologyImpl != null) { + impl = TerminologyCapabilities.Implementation.builder() + .description(string(buildDescription)) + .url(com.ibm.fhir.model.type.Url.of(customTerminologyImpl)) + .build(); + } else { + impl = TerminologyCapabilities.Implementation.builder() + .description(string(buildDescription)) + .build(); + } + return TerminologyCapabilities.builder() .status(PublicationStatus.ACTIVE) .experimental(com.ibm.fhir.model.type.Boolean.TRUE) @@ -209,6 +227,7 @@ private TerminologyCapabilities buildTerminologyCapabilities() { .version(string(buildInfo.getBuildVersion())) .id(buildInfo.getBuildId()) .build()) + .implementation(impl) .codeSystem(buildCodeSystem()) .expansion(Expansion.builder() .hierarchical(com.ibm.fhir.model.type.Boolean.FALSE) @@ -483,6 +502,23 @@ private CapabilityStatement buildCapabilityStatement() throws Exception { format.add(Code.of(FHIRMediaType.APPLICATION_XML)); format.add(Code.of(FHIRMediaType.APPLICATION_FHIR_XML)); + /* + * The following checks to see if there is a IBM FHIR Server Service URL that we want to inline into the Capabilities Statement + * else the minimal implementation.description. + */ + String customImpl = FHIRConfigHelper.getStringProperty(FHIRConfiguration.PROPERTY_CAPABILITIES_URL, null); + CapabilityStatement.Implementation impl; + if (customImpl != null) { + impl = CapabilityStatement.Implementation.builder() + .description(string(buildDescription)) + .url(com.ibm.fhir.model.type.Url.of(customImpl)) + .build(); + } else { + impl = CapabilityStatement.Implementation.builder() + .description(string(buildDescription)) + .build(); + } + // Finally, create the CapabilityStatement resource itself. CapabilityStatement conformance = CapabilityStatement.builder() .status(PublicationStatus.ACTIVE) @@ -505,6 +541,7 @@ private CapabilityStatement buildCapabilityStatement() throws Exception { .build()) .rest(rest) .instantiates(buildInstantiates()) + .implementation(impl) .build(); try {