Skip to content

Commit

Permalink
IBM FHIR Server CapabilityStatement is invalid #2436
Browse files Browse the repository at this point in the history
- Add implementation for the various Capabilities statements
- Add FHIRPath validation to IT tests
- Add configuration property for URL

Signed-off-by: Paul Bastide <pbastide@us.ibm.com>
  • Loading branch information
prb112 authored and tbieste committed Jun 9, 2021
1 parent 6567376 commit d47474d
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 2 deletions.
6 changes: 6 additions & 0 deletions docs/src/pages/guides/FHIRServerUsersGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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|
Expand Down Expand Up @@ -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|
Expand Down Expand Up @@ -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|
Expand All @@ -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|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* (C) Copyright IBM Corp. 2017, 2020
* (C) Copyright IBM Corp. 2017, 2021
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand All @@ -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;
Expand All @@ -33,13 +35,19 @@
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;
import com.ibm.fhir.model.type.Xhtml;
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.
Expand All @@ -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());
Expand All @@ -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<FHIRPathNode> result = evaluator.evaluate(evaluationContext, "(kind != 'instance') or implementation.exists()");
Iterator<FHIRPathNode> 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<FHIRPathNode> result = evaluator.evaluate(evaluationContext, "(kind != 'instance') or implementation.exists()");
Iterator<FHIRPathNode> iter = result.iterator();
boolean instance = false;
while (iter.hasNext()) {
FHIRPathBooleanValue node = iter.next().as(FHIRPathBooleanValue.class);
instance = node._boolean();
}
assertTrue(instance);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -505,6 +541,7 @@ private CapabilityStatement buildCapabilityStatement() throws Exception {
.build())
.rest(rest)
.instantiates(buildInstantiates())
.implementation(impl)
.build();

try {
Expand Down

0 comments on commit d47474d

Please sign in to comment.