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