001package org.hl7.fhir.r4.utils.client.network;
002
003import java.io.IOException;
004import java.net.URI;
005import java.util.Map;
006import java.util.concurrent.TimeUnit;
007
008import org.hl7.fhir.r4.model.Bundle;
009import org.hl7.fhir.r4.model.Resource;
010import org.hl7.fhir.r4.utils.client.EFhirClientException;
011import org.hl7.fhir.utilities.ToolingClientLogger;
012
013import okhttp3.Headers;
014import okhttp3.MediaType;
015import okhttp3.Request;
016import okhttp3.RequestBody;
017
018public class Client {
019
020  public static final String DEFAULT_CHARSET = "UTF-8";
021  private static final long DEFAULT_TIMEOUT = 5000;
022  private ToolingClientLogger logger;
023  private FhirLoggingInterceptor fhirLoggingInterceptor;
024  private int retryCount;
025  private long timeout = DEFAULT_TIMEOUT;
026  private String base;
027  
028  public String getBase() {
029    return base;
030  }
031
032  public void setBase(String base) {
033    this.base = base;
034  }
035
036
037  public ToolingClientLogger getLogger() {
038    return logger;
039  }
040
041  public void setLogger(ToolingClientLogger logger) {
042    this.logger = logger;
043    this.fhirLoggingInterceptor = new FhirLoggingInterceptor(logger);
044  }
045
046  public int getRetryCount() {
047    return retryCount;
048  }
049
050  public void setRetryCount(int retryCount) {
051    this.retryCount = retryCount;
052  }
053
054  public long getTimeout() {
055    return timeout;
056  }
057
058  public void setTimeout(long timeout) {
059    this.timeout = timeout;
060  }
061
062  public <T extends Resource> ResourceRequest<T> issueOptionsRequest(URI optionsUri, String resourceFormat,
063      String message, long timeout) throws IOException {
064    Request.Builder request = new Request.Builder().method("OPTIONS", null).url(optionsUri.toURL());
065
066    return executeFhirRequest(request, resourceFormat, new Headers.Builder().build(), message, retryCount, timeout);
067  }
068
069  public <T extends Resource> ResourceRequest<T> issueGetResourceRequest(URI resourceUri, String resourceFormat,
070      Headers headers, String message, long timeout) throws IOException {
071    Request.Builder request = new Request.Builder().url(resourceUri.toURL());
072
073    return executeFhirRequest(request, resourceFormat, headers, message, retryCount, timeout);
074  }
075
076  public int tester(int trytry) {
077    return 5;
078  }
079
080  public <T extends Resource> ResourceRequest<T> issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat,
081      String message, long timeout) throws IOException {
082    return issuePutRequest(resourceUri, payload, resourceFormat, new Headers.Builder().build(), message, timeout);
083  }
084
085  public <T extends Resource> ResourceRequest<T> issuePutRequest(URI resourceUri, byte[] payload, String resourceFormat,
086      Headers headers, String message, long timeout) throws IOException {
087    if (payload == null)
088      throw new EFhirClientException("PUT requests require a non-null payload");
089    RequestBody body = RequestBody.create(payload);
090    Request.Builder request = new Request.Builder().url(resourceUri.toURL()).put(body);
091
092    return executeFhirRequest(request, resourceFormat, headers, message, retryCount, timeout);
093  }
094
095  public <T extends Resource> ResourceRequest<T> issuePostRequest(URI resourceUri, byte[] payload,
096      String resourceFormat, String message, long timeout) throws IOException {
097    return issuePostRequest(resourceUri, payload, resourceFormat, new Headers.Builder().build(), message, timeout);
098  }
099
100  public <T extends Resource> ResourceRequest<T> issuePostRequest(URI resourceUri, byte[] payload,
101      String resourceFormat, Headers headers, String message, long timeout) throws IOException {
102    if (payload == null)
103      throw new EFhirClientException("POST requests require a non-null payload");
104    RequestBody body = RequestBody.create(MediaType.parse(resourceFormat + ";charset=" + DEFAULT_CHARSET), payload);
105    Request.Builder request = new Request.Builder().url(resourceUri.toURL()).post(body);
106
107    return executeFhirRequest(request, resourceFormat, headers, message, retryCount, timeout);
108  }
109
110  public boolean issueDeleteRequest(URI resourceUri) throws IOException {
111    Request.Builder request = new Request.Builder().url(resourceUri.toURL()).delete();
112    return executeFhirRequest(request, null, new Headers.Builder().build(), null, retryCount, timeout)
113        .isSuccessfulRequest();
114  }
115
116  public Bundle issueGetFeedRequest(URI resourceUri, String resourceFormat) throws IOException {
117    Request.Builder request = new Request.Builder().url(resourceUri.toURL());
118
119    return executeBundleRequest(request, resourceFormat, new Headers.Builder().build(), null, retryCount, timeout);
120  }
121
122  public Bundle issuePostFeedRequest(URI resourceUri, Map<String, String> parameters, String resourceName,
123      Resource resource, String resourceFormat) throws IOException {
124    String boundary = "----WebKitFormBoundarykbMUo6H8QaUnYtRy";
125    byte[] payload = ByteUtils.encodeFormSubmission(parameters, resourceName, resource, boundary);
126    RequestBody body = RequestBody.create(MediaType.parse(resourceFormat + ";charset=" + DEFAULT_CHARSET), payload);
127    Request.Builder request = new Request.Builder().url(resourceUri.toURL()).post(body);
128
129    return executeBundleRequest(request, resourceFormat, new Headers.Builder().build(), null, retryCount, timeout);
130  }
131
132  public Bundle postBatchRequest(URI resourceUri, byte[] payload, String resourceFormat, String message, int timeout)
133      throws IOException {
134    if (payload == null)
135      throw new EFhirClientException("POST requests require a non-null payload");
136    RequestBody body = RequestBody.create(MediaType.parse(resourceFormat + ";charset=" + DEFAULT_CHARSET), payload);
137    Request.Builder request = new Request.Builder().url(resourceUri.toURL()).post(body);
138
139    return executeBundleRequest(request, resourceFormat, new Headers.Builder().build(), message, retryCount, timeout);
140  }
141
142  public <T extends Resource> Bundle executeBundleRequest(Request.Builder request, String resourceFormat,
143      Headers headers, String message, int retryCount, long timeout) throws IOException {
144    return new FhirRequestBuilder(request, base).withLogger(fhirLoggingInterceptor).withResourceFormat(resourceFormat)
145        .withRetryCount(retryCount).withMessage(message)
146        .withHeaders(headers == null ? new Headers.Builder().build() : headers)
147        .withTimeout(timeout, TimeUnit.MILLISECONDS).executeAsBatch();
148  }
149
150  public <T extends Resource> ResourceRequest<T> executeFhirRequest(Request.Builder request, String resourceFormat,
151      Headers headers, String message, int retryCount, long timeout) throws IOException {
152    return new FhirRequestBuilder(request, base).withLogger(fhirLoggingInterceptor).withResourceFormat(resourceFormat)
153        .withRetryCount(retryCount).withMessage(message)
154        .withHeaders(headers == null ? new Headers.Builder().build() : headers)
155        .withTimeout(timeout, TimeUnit.MILLISECONDS).execute();
156  }
157}