package com.aol.micro.server.rest.client.nio;
import java.net.URI;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import lombok.Getter;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureCallback;
import org.springframework.web.client.AsyncRequestCallback;
import org.springframework.web.client.AsyncRestTemplate;
import org.springframework.web.client.ResponseExtractor;
import org.springframework.web.client.RestClientException;
import com.aol.micro.server.rest.jackson.JacksonUtil;
public class NIORestClient {
@Getter
private final AsyncRestTemplate template;
// GET
public <T> CompletableFuture<ResponseEntity<T>> getForEntity(String url,
Class<T> responseType, Object... uriVariables)
throws RestClientException {
return toCompletableFuture(template.getForEntity(url, responseType,
uriVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> getForEntity(String url,
Class<T> responseType, Map<String, ?> urlVariables)
throws RestClientException {
return toCompletableFuture(template.getForEntity(url, responseType,
urlVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> getForEntity(URI url,
Class<T> responseType) throws RestClientException {
return toCompletableFuture(template.getForEntity(url, responseType));
}
// HEAD
public CompletableFuture<HttpHeaders> headForHeaders(String url,
Object... uriVariables) throws RestClientException {
return toCompletableFuture(template.headForHeaders(url, uriVariables));
}
public CompletableFuture<HttpHeaders> headForHeaders(String url,
Map<String, ?> uriVariables) throws RestClientException {
return toCompletableFuture(template.headForHeaders(url, uriVariables));
}
public CompletableFuture<HttpHeaders> headForHeaders(URI url)
throws RestClientException {
return toCompletableFuture(template.headForHeaders(url));
}
public CompletableFuture<URI> postForLocation(String url,
HttpEntity<?> request, Object... uriVariables)
throws RestClientException {
return toCompletableFuture(template.postForLocation(url, request,
uriVariables));
}
public CompletableFuture<URI> postForLocation(String url,
HttpEntity<?> request, Map<String, ?> uriVariables)
throws RestClientException {
return toCompletableFuture(template.postForLocation(url, request,
uriVariables));
}
public CompletableFuture<URI> postForLocation(URI url, HttpEntity<?> request)
throws RestClientException {
return toCompletableFuture(template.postForLocation(url, request));
}
public <T> CompletableFuture<ResponseEntity<T>> postForEntity(String url,
HttpEntity<?> request, Class<T> responseType,
Object... uriVariables) throws RestClientException {
return toCompletableFuture(template.postForEntity(url, request,
responseType, uriVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> postForEntity(String url,
HttpEntity<?> request, Class<T> responseType,
Map<String, ?> uriVariables) throws RestClientException {
return toCompletableFuture(template.postForEntity(url, request,
responseType, uriVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> postForEntity(URI url,
HttpEntity<?> request, Class<T> responseType)
throws RestClientException {
return toCompletableFuture(template.postForEntity(url, request,
responseType));
}
public CompletableFuture<?> put(String url, HttpEntity<?> request,
Object... uriVariables) throws RestClientException {
return toCompletableFuture(template.put(url, request, uriVariables));
}
public CompletableFuture<?> put(String url, HttpEntity<?> request,
Map<String, ?> uriVariables) throws RestClientException {
return toCompletableFuture(template.put(url, request, uriVariables));
}
public CompletableFuture<?> put(URI url, HttpEntity<?> request)
throws RestClientException {
return toCompletableFuture(template.put(url, request));
}
public CompletableFuture<?> delete(String url, Object... urlVariables)
throws RestClientException {
return toCompletableFuture(template.delete(url, urlVariables));
}
public CompletableFuture<?> delete(String url, Map<String, ?> urlVariables)
throws RestClientException {
return toCompletableFuture(template.delete(url, urlVariables));
}
public CompletableFuture<?> delete(URI url) throws RestClientException {
return toCompletableFuture(template.delete(url));
}
public CompletableFuture<Set<HttpMethod>> optionsForAllow(String url,
Object... uriVariables) throws RestClientException {
return toCompletableFuture(template.optionsForAllow(url, uriVariables));
}
public CompletableFuture<Set<HttpMethod>> optionsForAllow(String url,
Map<String, ?> uriVariables) throws RestClientException {
return toCompletableFuture(template.optionsForAllow(url, uriVariables));
}
public CompletableFuture<Set<HttpMethod>> optionsForAllow(URI url)
throws RestClientException {
return toCompletableFuture(template.optionsForAllow(url));
}
public <T> CompletableFuture<ResponseEntity<T>> exchange(String url,
HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType, Object... uriVariables)
throws RestClientException {
return toCompletableFuture(template.exchange(url, method,
requestEntity, responseType, uriVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> exchange(String url,
HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType, Map<String, ?> uriVariables)
throws RestClientException {
return toCompletableFuture(template.exchange(url, method,
requestEntity, responseType, uriVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> exchange(URI url,
HttpMethod method, HttpEntity<?> requestEntity,
Class<T> responseType) throws RestClientException {
return toCompletableFuture(template.exchange(url, method,
requestEntity, responseType));
}
public <T> CompletableFuture<ResponseEntity<T>> exchange(String url,
HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType, Object... uriVariables)
throws RestClientException {
return toCompletableFuture(template.exchange(url, method,
requestEntity, responseType, uriVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> exchange(String url,
HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType,
Map<String, ?> uriVariables) throws RestClientException {
return toCompletableFuture(template.exchange(url, method,
requestEntity, responseType, uriVariables));
}
public <T> CompletableFuture<ResponseEntity<T>> exchange(URI url,
HttpMethod method, HttpEntity<?> requestEntity,
ParameterizedTypeReference<T> responseType)
throws RestClientException {
return toCompletableFuture(template.exchange(url, method,
requestEntity, responseType));
}
public <T> CompletableFuture<T> execute(String url, HttpMethod method,
AsyncRequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, Object... urlVariables)
throws RestClientException {
return toCompletableFuture(template.execute(url, method,
requestCallback, responseExtractor, urlVariables));
}
public <T> CompletableFuture<T> execute(String url, HttpMethod method,
AsyncRequestCallback requestCallback,
ResponseExtractor<T> responseExtractor, Map<String, ?> urlVariables)
throws RestClientException {
return toCompletableFuture(template.execute(url, method,
requestCallback, responseExtractor, urlVariables));
}
public <T> CompletableFuture<T> execute(URI url, HttpMethod method,
AsyncRequestCallback requestCallback,
ResponseExtractor<T> responseExtractor) throws RestClientException {
return toCompletableFuture(template.execute(url, method,
requestCallback, responseExtractor));
}
public NIORestClient(AsyncRestTemplate template) {
super();
this.template = template;
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setObjectMapper(JacksonUtil.getMapper());
template.getMessageConverters().add(converter);
}
<T> CompletableFuture<T> toCompletableFuture(
final ListenableFuture<T> listenableFuture) {
// create an instance of CompletableFuture
CompletableFuture<T> completable = new CompletableFuture<T>() {
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
// propagate cancel to the listenable future
boolean result = listenableFuture.cancel(mayInterruptIfRunning);
super.cancel(mayInterruptIfRunning);
return result;
}
};
// add callback
listenableFuture.addCallback(new ListenableFutureCallback<T>() {
@Override
public void onSuccess(T result) {
completable.complete(result);
}
@Override
public void onFailure(Throwable t) {
completable.completeExceptionally(t);
}
});
return completable;
}
}