001
002package io.vrap.rmf.base.client;
003
004import java.net.URI;
005import java.util.HashMap;
006import java.util.Map;
007import java.util.Optional;
008import java.util.concurrent.CompletableFuture;
009import java.util.function.Consumer;
010
011import com.fasterxml.jackson.core.type.TypeReference;
012import com.fasterxml.jackson.databind.JavaType;
013
014public class ContextApiHttpClientImpl extends AutoCloseableService implements ContextApiHttpClient {
015    private final ApiHttpClient client;
016
017    private Map<Object, Object> contextMap;
018
019    private final Consumer<ContextAware<ContextApiHttpClient>> consumer;
020
021    public ContextApiHttpClientImpl(ApiHttpClient client) {
022        this(client, new HashMap<>(), null);
023    }
024
025    public ContextApiHttpClientImpl(ApiHttpClient client, Map<Object, Object> contextMap) {
026        this(client, contextMap, null);
027    }
028
029    public ContextApiHttpClientImpl(ApiHttpClient client, Map<Object, Object> contextMap,
030            Consumer<ContextAware<ContextApiHttpClient>> consumer) {
031        this.client = client;
032        this.contextMap = contextMap;
033        this.consumer = consumer;
034    }
035
036    public ContextApiHttpClientImpl(final ContextApiHttpClientImpl c) {
037        this.client = c.client;
038        this.contextMap = c.contextMap;
039        this.consumer = c.consumer;
040    }
041
042    public Map<Object, Object> getContextMap() {
043        return contextMap;
044    }
045
046    public ContextApiHttpClient withContextMap(final Map<Object, Object> contextMap) {
047        final ContextApiHttpClientImpl client = copy();
048        client.contextMap = new HashMap<>(contextMap);
049
050        return client;
051    }
052
053    @SuppressWarnings("unchecked")
054    public <T> T getContext(Class<T> key) {
055        return (T) contextMap.get(key);
056    }
057
058    public <T> ContextApiHttpClient addContext(T value) {
059        final ContextApiHttpClientImpl client = copy();
060        final Map<Object, Object> contextMap = new HashMap<>(client.contextMap);
061        contextMap.put(value.getClass(), value);
062        client.contextMap = contextMap;
063
064        return client;
065    }
066
067    public Object getContext(Object key) {
068        return contextMap.get(key);
069    }
070
071    public ContextApiHttpClient addContext(Object key, Object value) {
072        final ContextApiHttpClientImpl client = copy();
073        final Map<Object, Object> contextMap = new HashMap<>(client.contextMap);
074        contextMap.put(key, value);
075        client.contextMap = contextMap;
076
077        return client;
078    }
079
080    private ContextApiHttpClientImpl copy() {
081        return new ContextApiHttpClientImpl(this);
082    }
083
084    private void restoreContext() {
085        Optional.ofNullable(consumer).ifPresent(c -> c.accept(this));
086    }
087
088    @Override
089    public <O> CompletableFuture<ApiHttpResponse<O>> execute(ApiHttpRequest request, Class<O> outputType) {
090        restoreContext();
091        return client.execute(request.withContextMap(contextMap), outputType);
092    }
093
094    @Override
095    public <O> CompletableFuture<ApiHttpResponse<O>> execute(ApiHttpRequest request, TypeReference<O> outputType) {
096        restoreContext();
097        return client.execute(request.withContextMap(contextMap), outputType);
098    }
099
100    @Override
101    public <O> CompletableFuture<ApiHttpResponse<O>> execute(ApiHttpRequest request, JavaType outputType) {
102        restoreContext();
103        return client.execute(request.withContextMap(contextMap), outputType);
104    }
105
106    @Override
107    public <O> CompletableFuture<ApiHttpResponse<O>> execute(ClientRequestCommand<O> method) {
108        restoreContext();
109        return method.execute(this);
110    }
111
112    @Override
113    public ResponseSerializer getSerializerService() {
114        return client.getSerializerService();
115    }
116
117    @Override
118    public URI getBaseUri() {
119        return client.getBaseUri();
120    }
121
122    @Override
123    public CompletableFuture<ApiHttpResponse<byte[]>> execute(ApiHttpRequest request) {
124        restoreContext();
125        return client.execute(request.withContextMap(contextMap));
126    }
127
128    @Override
129    protected void internalClose() {
130        closeQuietly(client);
131    }
132}