001/*- 002 * #%L 003 * Smile CDR - CDR 004 * %% 005 * Copyright (C) 2016 - 2026 Smile CDR, Inc. 006 * %% 007 * All rights reserved. 008 * #L% 009 */ 010package ca.cdr.api.fhir.client; 011 012import ca.cdr.api.model.json.oauth.SmartConfigurationJson; 013import ca.uhn.fhir.jpa.bulk.export.model.BulkExportResponseJson; 014import ca.uhn.fhir.rest.api.server.bulk.BulkExportJobParameters; 015import ca.uhn.fhir.rest.client.api.IGenericClient; 016import jakarta.annotation.Nonnull; 017 018import java.time.Duration; 019 020/** 021 * An {@link IGenericClient} with the FHIR endpoint operations it does not model yet. 022 * <p> 023 * Each method here is a candidate for upstreaming into HAPI FHIR's {@link IGenericClient}. Once one 024 * is, it moves there and is removed from this interface. 025 * </p> 026 */ 027public interface IExtendedGenericClient extends IGenericClient { 028 029 /** 030 * Fetches the endpoint's SMART App Launch discovery document from 031 * {@code [base]/.well-known/smart-configuration}. 032 * 033 * @return the discovery document. Every member is optional: a server with SMART disabled 034 * returns an empty document, and one without the {@code sso-openid-connect} capability 035 * omits {@code issuer} and {@code jwks_uri}. 036 * @throws AssertionError if the server does not answer {@code 200 OK} 037 * @see <a href="https://hl7.org/fhir/smart-app-launch/conformance.html">SMART App Launch: Conformance</a> 038 */ 039 @Nonnull 040 SmartConfigurationJson getSmartConfiguration(); 041 042 /** 043 * Kicks off an asynchronous Bulk Data export by {@code POST}ing the parameters as a FHIR 044 * {@code Parameters} resource with {@code Prefer: respond-async} and {@code Cache-Control: no-cache}. 045 * The latter makes the server start a new export job rather than reuse a recent one with the same 046 * parameters. 047 * <p> 048 * The export style picks the endpoint: {@code SYSTEM} (or none) uses {@code [base]/$export}, 049 * {@code PATIENT} uses {@code [base]/Patient/$export}, and {@code GROUP} uses 050 * {@code [base]/Group/[groupId]/$export}. The output format defaults to 051 * {@code application/fhir+ndjson} when the parameters name none. 052 * </p> 053 * 054 * @param theParameters what to export: style, resource types, {@code _since}/{@code _until}, 055 * type filters, patients, group and MDM expansion 056 * @return the status polling URL from the response's {@code Content-Location} header, to pass 057 * to {@link #awaitBulkExport(String)} 058 * @throws IllegalArgumentException if a {@code GROUP} export has no group ID 059 * @throws AssertionError if the server does not answer {@code 202 Accepted} with a 060 * {@code Content-Location} 061 * @see <a href="https://hl7.org/fhir/uv/bulkdata/export.html">FHIR Bulk Data Access: Export</a> 062 */ 063 @Nonnull 064 String startBulkExport(@Nonnull BulkExportJobParameters theParameters); 065 066 /** 067 * Polls a Bulk Data export's status URL until the export completes, for up to five minutes, 068 * once a second. 069 * 070 * @param thePollUrl the polling URL returned by {@link #startBulkExport(BulkExportJobParameters)} 071 * @return the completion manifest, listing the output files 072 * @throws AssertionError if the export fails, or is still running after five minutes 073 * @see #awaitBulkExport(String, Duration, Duration) 074 */ 075 @Nonnull 076 BulkExportResponseJson awaitBulkExport(@Nonnull String thePollUrl); 077 078 /** 079 * Polls a Bulk Data export's status URL until the export completes. 080 * <p> 081 * A {@code 202 Accepted} means the export is still running, so polling continues. A 082 * {@code 200 OK} carries the completion manifest. Any other status means the export failed. 083 * </p> 084 * 085 * @param thePollUrl the polling URL returned by {@link #startBulkExport(BulkExportJobParameters)} 086 * @param theTimeout how long to keep polling before giving up 087 * @param thePollInterval how long to wait between polls 088 * @return the completion manifest, listing the output files 089 * @throws AssertionError if the server answers anything but {@code 200} or {@code 202}, giving 090 * the status and body, or if the export is still running when 091 * {@code theTimeout} passes, giving its last {@code X-Progress} 092 * @throws IllegalStateException if the thread is interrupted while waiting between polls 093 */ 094 @Nonnull 095 BulkExportResponseJson awaitBulkExport( 096 @Nonnull String thePollUrl, @Nonnull Duration theTimeout, @Nonnull Duration thePollInterval); 097}