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
011public class ContextApiHttpClientImpl extends AutoCloseableService implements ContextApiHttpClient {
012    private final ApiHttpClient client;
013
014    private final boolean closeHttpClient;
015
016    private Map<Object, Object> contextMap;
017
018    private final Consumer<ContextAware<ContextApiHttpClient>> consumer;
019
020    public ContextApiHttpClientImpl(final ApiHttpClient client) {
021        this(client, new HashMap<>(), null);
022    }
023
024    public ContextApiHttpClientImpl(final ApiHttpClient client, final Map<Object, Object> contextMap) {
025        this(client, contextMap, null);
026    }
027
028    public ContextApiHttpClientImpl(final ApiHttpClient client, final Map<Object, Object> contextMap,
029            final Consumer<ContextAware<ContextApiHttpClient>> consumer) {
030        this(client, contextMap, consumer, true);
031    }
032
033    public ContextApiHttpClientImpl(final ApiHttpClient client, final boolean closeHttpClient) {
034        this(client, new HashMap<>(), null, closeHttpClient);
035    }
036
037    public ContextApiHttpClientImpl(final ApiHttpClient client, final Map<Object, Object> contextMap,
038            final boolean closeHttpClient) {
039        this(client, contextMap, null, closeHttpClient);
040    }
041
042    public ContextApiHttpClientImpl(final ApiHttpClient client, final Map<Object, Object> contextMap,
043            final Consumer<ContextAware<ContextApiHttpClient>> consumer, final boolean closeHttpClient) {
044        this.client = client;
045        this.contextMap = contextMap;
046        this.consumer = consumer;
047        this.closeHttpClient = closeHttpClient;
048    }
049
050    public ContextApiHttpClientImpl(final ContextApiHttpClientImpl c) {
051        this.client = c.client;
052        this.contextMap = c.contextMap;
053        this.consumer = c.consumer;
054        this.closeHttpClient = c.closeHttpClient;
055    }
056
057    public Map<Object, Object> getContextMap() {
058        return contextMap;
059    }
060
061    public ContextApiHttpClient withContextMap(final Map<Object, Object> contextMap) {
062        final ContextApiHttpClientImpl client = copy();
063        client.contextMap = new HashMap<>(contextMap);
064
065        return client;
066    }
067
068    @SuppressWarnings("unchecked")
069    public <T> T getContext(Class<T> key) {
070        return (T) contextMap.get(key);
071    }
072
073    public <T> ContextApiHttpClient addContext(final T value) {
074        final ContextApiHttpClientImpl client = copy();
075        final Map<Object, Object> contextMap = new HashMap<>(client.contextMap);
076        contextMap.put(value.getClass(), value);
077        if (value instanceof ClassReferenceContext) {
078            contextMap.put(((ClassReferenceContext) value).classReference(), value);
079        }
080        client.contextMap = contextMap;
081
082        return client;
083    }
084
085    public Object getContext(final Object key) {
086        return contextMap.get(key);
087    }
088
089    public ContextApiHttpClient addContext(final Object key, final Object value) {
090        final ContextApiHttpClientImpl client = copy();
091        final Map<Object, Object> contextMap = new HashMap<>(client.contextMap);
092        contextMap.put(key, value);
093        client.contextMap = contextMap;
094
095        return client;
096    }
097
098    private ContextApiHttpClientImpl copy() {
099        return new ContextApiHttpClientImpl(this);
100    }
101
102    private void restoreContext() {
103        Optional.ofNullable(consumer).ifPresent(c -> c.accept(this));
104    }
105
106    @Override
107    public ResponseSerializer getSerializerService() {
108        return client.getSerializerService();
109    }
110
111    @Override
112    public URI getBaseUri() {
113        return client.getBaseUri();
114    }
115
116    @Override
117    public CompletableFuture<ApiHttpResponse<byte[]>> execute(final ApiHttpRequest request) {
118        restoreContext();
119        return client.execute(request.withContextMap(contextMap));
120    }
121
122    @Override
123    protected void internalClose() {
124        if (closeHttpClient) {
125            closeQuietly(client);
126        }
127        contextMap.values().forEach(o -> {
128            if (o instanceof AutoCloseable) {
129                closeQuietly((AutoCloseable) o);
130            }
131        });
132    }
133}