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