001/*-
002 * #%L
003 * Smile CDR - CDR
004 * %%
005 * Copyright (C) 2016 - 2024 Smile CDR, Inc.
006 * %%
007 * All rights reserved.
008 * #L%
009 */
010package ca.cdr.api.fhirgw.json;
011
012import ca.cdr.api.fhirgw.model.RetryStrategyEnum;
013import ca.cdr.api.model.json.IModelJson;
014import ca.uhn.fhir.model.api.annotation.ExampleSupplier;
015import ca.uhn.fhir.rest.api.EncodingEnum;
016import com.fasterxml.jackson.annotation.JsonProperty;
017import io.swagger.v3.oas.annotations.media.Schema;
018import org.springframework.lang.NonNull;
019
020import java.util.Arrays;
021import java.util.Collections;
022import java.util.List;
023import java.util.function.Supplier;
024
025/**
026 * Contains the definition for an individual Smile CDR FHIR Gateway target server
027 */
028@Schema(
029                name = "GatewayTarget",
030                description = "Contains the definition for an individual Smile CDR FHIR Gateway target server")
031@ExampleSupplier(GatewayTargetJson.ExampleSupplier.class)
032public class GatewayTargetJson implements IModelJson, Cloneable {
033
034        public static final int DEFAULT_TIMEOUT = 60 * 1000;
035        public static final Boolean DEFAULT_USE_HTTP_POST_FOR_ALL_SEARCHES = Boolean.FALSE;
036        public static final Boolean DEFAULT_SERVER_CAPABILITY_STATEMENT_VALIDATION_ENABLED = Boolean.TRUE;
037        public static final Boolean DEFAULT_ALLOWED_TO_FAIL = Boolean.FALSE;
038
039        @JsonProperty("id")
040        @Schema(description = "An internal ID for the target server")
041        private String myId;
042
043        @JsonProperty("baseUrl")
044        @Schema(description = "The base URL for the target server")
045        private String myBaseUrl;
046
047        @JsonProperty("fixedEndpointUrl")
048        @Schema(
049                        description =
050                                        "If specified, will create a mapping between the baseUrl of the target, and this endpoint. When a bundle link is received that refers to this fixed endpoint, we will associate it to this target.")
051        private String myFixedEndpointUrl;
052
053        @JsonProperty("httpBasicCredentials")
054        @Schema(
055                        description =
056                                        "If specified, these credentials (in the form `username:password`) will be passed in all client requests to the target server")
057        private String myHttpBasicCredentials;
058
059        @JsonProperty("connectTimeoutMillis")
060        @Schema(
061                        description =
062                                        "Specifies a connection timeout (in millis) to use for communication with the target server. Default is "
063                                                        + DEFAULT_TIMEOUT)
064        private Integer myConnectTimeoutMillis;
065
066        @JsonProperty("socketTimeoutMillis")
067        @Schema(
068                        description =
069                                        "Specifies a socket timeout (in millis) to use for communication with the target server. Default is "
070                                                        + DEFAULT_TIMEOUT)
071        private Integer mySocketTimeoutMillis;
072
073        @JsonProperty("clientInterceptorClasses")
074        @Schema(
075                        description =
076                                        "If specified, signals to FHIR Gateway to load a comma-delimited list of CLIENT_RESPONSE interceptor classes that will allow the user to overwrite the HTTP response")
077        private String myClientInterceptorClasses;
078
079        public String getClientInterceptorClasses() {
080                return myClientInterceptorClasses;
081        }
082
083        public GatewayTargetJson setClientInterceptorClasses(String myClientInterceptorClasses) {
084                this.myClientInterceptorClasses = myClientInterceptorClasses;
085                return this;
086        }
087
088        @JsonProperty("resourceIdPrefix")
089        @Schema(
090                        description =
091                                        "If specified, provides a prefix that will be added to all resource IDs and local references for the target server before returning to the client")
092        private String myResourceIdPrefix;
093
094        @JsonProperty("useHttpPostForAllSearches")
095        @Schema(
096                        description =
097                                        "If set to true, FHIR search and paging operations against the target server will be performed using an HTTP POST instead of a GET. Default is `false`")
098        private Boolean myUseHttpPostForAllSearches;
099
100        @JsonProperty("serverCapabilityStatementValidationEnabled")
101        @Schema(
102                        description =
103                                        "If set to false, FHIR Gateway will not validate the target server's CapabilityStatement with a request to /metadata. Default is `true`")
104        private Boolean myServerCapabilityStatementValidationEnabled;
105
106        @JsonProperty("alternateValidationPath")
107        @Schema(
108                        description =
109                                        "An alternate validation path which can be used to validate the target server using a HTTP GET request.")
110        private String alternateValidationPath;
111
112        @JsonProperty("headersToForward")
113        @Schema(
114                        description =
115                                        "Any headers specified by name will be copied from the incoming client request and added to requests to the target server")
116        private List<String> myHeadersToForward;
117
118        @JsonProperty("allowedToFail")
119        @Schema(
120                        description =
121                                        "If set to true, FHIR search operations against the target server that fail will not return an error to the client, unless all targets for a given request have failed. This flag does not apply to read routes. Default is `false`")
122        private Boolean myAllowedToFail;
123
124        @JsonProperty("forcedEncoding")
125        @Schema(
126                        description =
127                                        "If set, any requests containing a payload will have their payload re-encoded to the defined content-type before being forwarded to the target server")
128        private EncodingEnum myForcedEncoding;
129
130        @JsonProperty("retryStrategy")
131        @Schema(
132                        description =
133                                        "If set, failed requests to this target will be retried using the specified retry configurations.")
134        private GatewayTargetRetryStrategyJson myRetryStrategy;
135
136        public Boolean getAllowedToFail() {
137                if (myAllowedToFail == null) {
138                        myAllowedToFail = DEFAULT_ALLOWED_TO_FAIL;
139                }
140                return myAllowedToFail;
141        }
142
143        public void setAllowedToFail(Boolean theAllowedToFail) {
144                myAllowedToFail = theAllowedToFail;
145        }
146
147        public List<String> getHeadersToForward() {
148                if (myHeadersToForward == null) {
149                        myHeadersToForward = Collections.emptyList();
150                }
151                return myHeadersToForward;
152        }
153
154        public void setHeadersToForward(@NonNull List<String> theHeaders) {
155                myHeadersToForward = Collections.unmodifiableList(theHeaders);
156        }
157
158        public Boolean getUseHttpPostForAllSearches() {
159                if (myUseHttpPostForAllSearches == null) {
160                        myUseHttpPostForAllSearches = DEFAULT_USE_HTTP_POST_FOR_ALL_SEARCHES;
161                }
162                return myUseHttpPostForAllSearches;
163        }
164
165        public void setUseHttpPostForAllSearches(Boolean theUseHttpPostForAllSearches) {
166                myUseHttpPostForAllSearches = theUseHttpPostForAllSearches;
167        }
168
169        public Boolean getServerCapabilityStatementValidationEnabled() {
170                if (myServerCapabilityStatementValidationEnabled == null) {
171                        myServerCapabilityStatementValidationEnabled = DEFAULT_SERVER_CAPABILITY_STATEMENT_VALIDATION_ENABLED;
172                }
173                return myServerCapabilityStatementValidationEnabled;
174        }
175
176        public GatewayTargetJson setServerCapabilityStatementValidationEnabled(
177                        Boolean theServerCapabilityStatementValidationEnabled) {
178                myServerCapabilityStatementValidationEnabled = theServerCapabilityStatementValidationEnabled;
179                return this;
180        }
181
182        public String getAlternateValidationPath() {
183                return alternateValidationPath;
184        }
185
186        public GatewayTargetJson setAlternateValidationPath(String theAlternateValidationPath) {
187                alternateValidationPath = theAlternateValidationPath;
188                return this;
189        }
190
191        public String getResourceIdPrefix() {
192                return myResourceIdPrefix;
193        }
194
195        public GatewayTargetJson setResourceIdPrefix(String theResourceIdPrefix) {
196                myResourceIdPrefix = theResourceIdPrefix;
197                return this;
198        }
199
200        public Integer getConnectTimeoutMillis() {
201                return myConnectTimeoutMillis;
202        }
203
204        public GatewayTargetJson setConnectTimeoutMillis(Integer theConnectTimeoutMillis) {
205                myConnectTimeoutMillis = theConnectTimeoutMillis;
206                return this;
207        }
208
209        public Integer getSocketTimeoutMillis() {
210                return mySocketTimeoutMillis;
211        }
212
213        public GatewayTargetJson setSocketTimeoutMillis(Integer theSocketTimeoutMillis) {
214                mySocketTimeoutMillis = theSocketTimeoutMillis;
215                return this;
216        }
217
218        public String getHttpBasicCredentials() {
219                return myHttpBasicCredentials;
220        }
221
222        public GatewayTargetJson setHttpBasicCredentials(String theHttpBasicCredentials) {
223                myHttpBasicCredentials = theHttpBasicCredentials;
224                return this;
225        }
226
227        public String getId() {
228                return myId;
229        }
230
231        public GatewayTargetJson setId(String theId) {
232                myId = theId;
233                return this;
234        }
235
236        public String getBaseUrl() {
237                return myBaseUrl;
238        }
239
240        public GatewayTargetJson setBaseUrl(String theBaseUrl) {
241                myBaseUrl = theBaseUrl;
242                return this;
243        }
244
245        public int getConnectTimeoutOrDefault() {
246                if (getConnectTimeoutMillis() != null) {
247                        return getConnectTimeoutMillis();
248                }
249                return DEFAULT_TIMEOUT;
250        }
251
252        public int getSocketTimeoutOrDefault() {
253                if (getSocketTimeoutMillis() != null) {
254                        return getSocketTimeoutMillis();
255                }
256                return DEFAULT_TIMEOUT;
257        }
258
259        public EncodingEnum getForcedEncoding() {
260                return myForcedEncoding;
261        }
262
263        public void setForcedEncoding(EncodingEnum theForcedEncoding) {
264                myForcedEncoding = theForcedEncoding;
265        }
266
267        public GatewayTargetRetryStrategyJson getRetryStrategy() {
268                return myRetryStrategy;
269        }
270
271        public void setRetryStrategy(GatewayTargetRetryStrategyJson theRetryStrategy) {
272                myRetryStrategy = theRetryStrategy;
273        }
274
275        @Override
276        public GatewayTargetJson clone() {
277                try {
278                        return (GatewayTargetJson) super.clone();
279                } catch (CloneNotSupportedException theE) {
280                        throw new UnsupportedOperationException();
281                }
282        }
283
284        public void setFixedEndpointUrl(String theFixedTargetUrl) {
285                myFixedEndpointUrl = theFixedTargetUrl;
286        }
287
288        public String getFixedEndpointUrl() {
289                return myFixedEndpointUrl;
290        }
291
292        public static class ExampleSupplier implements Supplier<GatewayTargetJson> {
293
294                @Override
295                public GatewayTargetJson get() {
296                        GatewayTargetRetryStrategyJson gatewayTargetRetryStrategyJson = new GatewayTargetRetryStrategyJson();
297                        gatewayTargetRetryStrategyJson.setBackoffStrategy(RetryStrategyEnum.EXPONENTIAL);
298                        gatewayTargetRetryStrategyJson.setBackoffInterval(100);
299                        gatewayTargetRetryStrategyJson.setMaxRetries(2);
300                        gatewayTargetRetryStrategyJson.setErrorRetryClasses(
301                                        Collections.singletonList("ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException"));
302
303                        GatewayTargetJson targetJson = new GatewayTargetJson();
304                        targetJson.setRetryStrategy(gatewayTargetRetryStrategyJson);
305                        targetJson.setBaseUrl("http://localhost:8000").setId("target1").setAllowedToFail(true);
306                        targetJson.setHeadersToForward(Arrays.asList("Sample-Header-1", "Sample-Header-2"));
307
308                        return targetJson;
309                }
310        }
311}