From f1591f04a65c4442dd958f1faff31b8fb9788332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20P=C3=A9teri?= Date: Fri, 22 Sep 2023 19:10:09 +0200 Subject: [PATCH] feat(fhir): Add missing properties to CapabilityStatement --- .../CapabilityStatement.java | 39 +++++++++ .../capabilitystatement/Implementation.java | 4 + .../CapabilityStatementRestTest.java | 10 +++ .../fhir/rest/FhirMetadataController.java | 79 +++++++++++++------ 4 files changed, 106 insertions(+), 26 deletions(-) diff --git a/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/CapabilityStatement.java b/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/CapabilityStatement.java index 0d96a0e3c1f..c65ff3754cc 100644 --- a/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/CapabilityStatement.java +++ b/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/CapabilityStatement.java @@ -262,6 +262,45 @@ public Collection getDocuments() { return documents; } + public CapabilityStatement withUrl(Uri resourceUrl, Uri baseUrl) { + return new CapabilityStatement( + getId(), + getMeta(), + getImplicitRules(), + getLanguage(), + getText(), + resourceUrl, + getVersion(), + getName(), + getTitle(), + getStatus(), + getExperimental(), + getDate(), + getPublisher(), + getContacts(), + getDescription(), + getUsageContexts(), + getJurisdictions(), + getPurpose(), + getToolingId(), + + getResourceType(), + getIdentifiers(), + getCopyright(), + getKind(), + getInstantiates(), + getImports(), + getSoftware(), + getImplementation().withUrl(baseUrl), + getFhirVersion(), + getFormats(), + getPatchFormats(), + getImplementationGuides(), + getRests(), + getMessagings(), + getDocuments()); + } + public static Builder builder(String id) { return new Builder(id); } diff --git a/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/Implementation.java b/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/Implementation.java index 0b84445567d..d9b050442fc 100644 --- a/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/Implementation.java +++ b/fhir/com.b2international.snowowl.fhir.core/src/com/b2international/snowowl/fhir/core/model/capabilitystatement/Implementation.java @@ -67,6 +67,10 @@ public Reference getCustodian() { return custodian; } + public Implementation withUrl(final Uri url) { + return new Implementation(getDescription(), url, getCustodian()); + } + public static Builder builder() { return new Builder(); } diff --git a/fhir/com.b2international.snowowl.fhir.rest.tests/src/com/b2international/snowowl/fhir/rest/tests/capabilitystatement/CapabilityStatementRestTest.java b/fhir/com.b2international.snowowl.fhir.rest.tests/src/com/b2international/snowowl/fhir/rest/tests/capabilitystatement/CapabilityStatementRestTest.java index 299aa1c6b47..67f1fc15642 100644 --- a/fhir/com.b2international.snowowl.fhir.rest.tests/src/com/b2international/snowowl/fhir/rest/tests/capabilitystatement/CapabilityStatementRestTest.java +++ b/fhir/com.b2international.snowowl.fhir.rest.tests/src/com/b2international/snowowl/fhir/rest/tests/capabilitystatement/CapabilityStatementRestTest.java @@ -21,6 +21,7 @@ import org.junit.Test; +import com.b2international.snowowl.fhir.core.codesystems.CapabilityStatementKind; import com.b2international.snowowl.fhir.core.model.capabilitystatement.CapabilityStatement; import com.b2international.snowowl.fhir.core.model.operationdefinition.OperationDefinition; import com.b2international.snowowl.fhir.tests.FhirRestTest; @@ -40,6 +41,15 @@ public void capabilityStatementTest() { .assertThat() .statusCode(200) .body("resourceType", equalTo("CapabilityStatement")) + .body("url", notNullValue()) + .body("version", notNullValue()) + .body("name", notNullValue()) + .body("title", notNullValue()) + .body("status", notNullValue()) + .body("date", notNullValue()) + .body("description", notNullValue()) + .body("kind", equalTo(CapabilityStatementKind.INSTANCE.getCodeValue())) + .body("fhirVersion", equalTo("4.0.1")) .body("rest[0]", notNullValue()) .body("rest[0].resource[0]", notNullValue()); diff --git a/fhir/com.b2international.snowowl.fhir.rest/src/com/b2international/snowowl/fhir/rest/FhirMetadataController.java b/fhir/com.b2international.snowowl.fhir.rest/src/com/b2international/snowowl/fhir/rest/FhirMetadataController.java index 41a8b108b79..eeedbaeb739 100644 --- a/fhir/com.b2international.snowowl.fhir.rest/src/com/b2international/snowowl/fhir/rest/FhirMetadataController.java +++ b/fhir/com.b2international.snowowl.fhir.rest/src/com/b2international/snowowl/fhir/rest/FhirMetadataController.java @@ -21,14 +21,12 @@ import static com.b2international.snowowl.core.rest.OpenAPIExtensions.B2I_OPENAPI_X_NAME; import static com.google.common.collect.Maps.newHashMap; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.Supplier; import java.util.stream.Collectors; import org.eclipse.core.runtime.Platform; +import org.osgi.framework.Version; import org.springdoc.webmvc.api.OpenApiWebMvcResource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; @@ -36,6 +34,7 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.mvc.method.annotation.MvcUriComponentsBuilder; +import org.springframework.web.util.UriComponents; import org.springframework.web.util.UriComponentsBuilder; import com.b2international.commons.StringUtils; @@ -43,6 +42,7 @@ import com.b2international.snowowl.core.ApplicationContext; import com.b2international.snowowl.core.CoreActivator; import com.b2international.snowowl.core.config.SnowOwlConfiguration; +import com.b2international.snowowl.core.date.Dates; import com.b2international.snowowl.core.rest.FhirApiConfig; import com.b2international.snowowl.core.rest.SnowOwlOpenApiWebMvcResource; import com.b2international.snowowl.fhir.core.codesystems.CapabilityStatementKind; @@ -87,12 +87,12 @@ public class FhirMetadataController extends AbstractFhirController { @Autowired private FhirApiConfig config; - private static class Holder { - CapabilityStatement capabilityStatement; - Map operationMap; - } + private record StatementAndOperations ( + CapabilityStatement capabilityStatement, + Map operationMap + ) { } - private final Supplier capabilityStatementSupplier = Suppliers.memoize(this::initCache); + private final Supplier capabilityStatementSupplier = Suppliers.memoize(this::initCache); @Operation( summary="Retrieve the capability statement", @@ -108,7 +108,11 @@ private static class Holder { }) @GetMapping(value="/metadata") public CapabilityStatement metadata() { - return capabilityStatementSupplier.get().capabilityStatement; + final String resourceUrl = MvcUriComponentsBuilder.fromMethodName(FhirMetadataController.class, "metadata").toUriString(); + final String baseUrl = MvcUriComponentsBuilder.fromController(FhirMetadataController.class).toUriString(); + + final CapabilityStatement capabilityStatement = capabilityStatementSupplier.get().capabilityStatement(); + return capabilityStatement.withUrl(new Uri(resourceUrl), new Uri(baseUrl)); } /** @@ -137,8 +141,7 @@ public OperationDefinition operationDefinition( return operationDefinition; } - private Holder initCache() { - final Holder holder = new Holder(); + private StatementAndOperations initCache() { // XXX: we know that the subclass is instantiated (in SnowOwlApiConfig) final OpenAPI openAPI = ((SnowOwlOpenApiWebMvcResource) openApiWebMvcResource).getOpenApi(); final Collection resources = collectResources(openAPI); @@ -148,12 +151,12 @@ private Holder initCache() { .mode(RestfulCapabilityMode.SERVER) .resources(resources); - holder.operationMap = newHashMap(); + final Map operationMap = newHashMap(); for (final OperationDefinition operationDefinition : operationDefinitions) { for (final Code code : operationDefinition.getResources()) { final String key = code.getCodeValue() + operationDefinition.getName(); - holder.operationMap.put(key, operationDefinition); + operationMap.put(key, operationDefinition); restBuilder.addOperation(com.b2international.snowowl.fhir.core.model.capabilitystatement.Operation.builder() .name(operationDefinition.getName()) @@ -162,34 +165,58 @@ private Holder initCache() { } } - final String serverVersion = Platform.getBundle(CoreActivator.PLUGIN_ID) - .getVersion() - .toString(); + CapabilityStatement capabilityStatement = createCapabilityStatement(restBuilder); - String description = ApplicationContext.getServiceForClass(SnowOwlConfiguration.class).getDescription(); + return new StatementAndOperations(capabilityStatement, operationMap); + } + + private CapabilityStatement createCapabilityStatement(final Rest.Builder restBuilder) { - holder.capabilityStatement = CapabilityStatement.builder() - .name("FHIR Capability statement for Snow Owl© Terminology Server") + final Version bundleVersion = Platform.getBundle(CoreActivator.PLUGIN_ID).getVersion(); + final String softwareVersion = bundleVersion.toString(); + final String qualifier = bundleVersion.getQualifier(); + final Date date = getDateFromQualifier(qualifier); + + final String description = ApplicationContext.getServiceForClass(SnowOwlConfiguration.class) + .getDescription(); + + return CapabilityStatement.builder() + // .url(...) is added later + .version(softwareVersion) + .name("snow-owl-capability-statement") + .title("FHIR Capability statement for Snow Owl© Terminology Server") + .description("This statement describes FHIR resource types and operations supported by the terminology server.") .status(PublicationStatus.ACTIVE) - .experimental(false) + .date(date) .kind(CapabilityStatementKind.INSTANCE.getCode()) .fhirVersion("4.0.1") + .experimental(false) .addInstantiate(new Uri("http://hl7.org/fhir/CapabilityStatement/terminology-server")) .software(Software.builder() .name("Snow Owl©") - .version(serverVersion) - .build()) + .version(softwareVersion) + .build()) .implementation(Implementation.builder() .url("https://b2ihealthcare.com") .description(description) - .build()) + .build()) .addFormat(new Code(AbstractFhirController.APPLICATION_FHIR_JSON)) .addRest(restBuilder.build()) .build(); - - return holder; } + private Date getDateFromQualifier(final String qualifier) { + if (StringUtils.isEmpty(qualifier) || "qualifier".equals(qualifier)) { + return Dates.todayGmt(); + } + + try { + return Dates.parse(qualifier, "yyyyMMddHHmm"); + } catch (IllegalArgumentException e) { + return Dates.todayGmt(); + } + } + private Collection collectResources(final OpenAPI openAPI) { final Paths paths = openAPI.getPaths(); final List tags = openAPI.getTags();