1 package org.oxerr.vividseats.client.rescu.impl;
2
3 import java.util.function.Supplier;
4
5 import org.apache.commons.lang3.ArrayUtils;
6 import org.oxerr.rescu.ext.singleton.RestProxyFactorySingletonImpl;
7 import org.oxerr.vividseats.client.VividSeatsClient;
8 import org.oxerr.vividseats.client.inventory.ListingService;
9 import org.oxerr.vividseats.client.rescu.impl.inventory.ListingServiceImpl;
10 import org.oxerr.vividseats.client.rescu.resource.inventory.ListingResource;
11
12 import com.fasterxml.jackson.annotation.JsonInclude.Include;
13 import com.fasterxml.jackson.databind.DeserializationFeature;
14 import com.fasterxml.jackson.databind.ObjectMapper;
15 import com.fasterxml.jackson.databind.SerializationFeature;
16 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
17
18 import io.github.poshjosh.ratelimiter.store.BandwidthsStore;
19 import jakarta.ws.rs.HeaderParam;
20 import si.mazi.rescu.ClientConfig;
21 import si.mazi.rescu.IRestProxyFactory;
22 import si.mazi.rescu.Interceptor;
23 import si.mazi.rescu.RestProxyFactoryImpl;
24 import si.mazi.rescu.serialization.jackson.DefaultJacksonObjectMapperFactory;
25 import si.mazi.rescu.serialization.jackson.JacksonObjectMapperFactory;
26
27 public class ResCUVividSeatsClient implements VividSeatsClient {
28
29 private static final String DEFAULT_BASE_URL = "https://brokers.vividseats.com/webservices";
30
31 private final String baseUrl;
32
33 private final IRestProxyFactory restProxyFactory;
34
35 private final ListingService listingService;
36
37
38
39
40
41
42
43 public ResCUVividSeatsClient(String token, Interceptor... interceptors) {
44 this(DEFAULT_BASE_URL, token, interceptors);
45 }
46
47
48
49
50
51
52
53
54 public ResCUVividSeatsClient(String token, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
55 this(DEFAULT_BASE_URL, token, bandwidthsStore, interceptors);
56 }
57
58
59
60
61
62
63
64 public ResCUVividSeatsClient(Supplier<String> tokenSupplier, Interceptor... interceptors) {
65 this(DEFAULT_BASE_URL, tokenSupplier, interceptors);
66 }
67
68
69
70
71
72
73
74
75 public ResCUVividSeatsClient(Supplier<String> tokenSupplier, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
76 this(DEFAULT_BASE_URL, tokenSupplier, bandwidthsStore, interceptors);
77 }
78
79
80
81
82
83
84
85
86 public ResCUVividSeatsClient(String baseUrl, String token, Interceptor... interceptors) {
87 this(baseUrl, () -> token, interceptors);
88 }
89
90
91
92
93
94
95
96
97 public ResCUVividSeatsClient(String baseUrl, Supplier<String> tokenSupplier, Interceptor... interceptors) {
98 this(baseUrl, tokenSupplier, BandwidthsStore.ofDefaults(), interceptors);
99 }
100
101
102
103
104
105
106
107
108
109 public ResCUVividSeatsClient(String baseUrl, String token, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
110 this(baseUrl, () -> token, bandwidthsStore, interceptors);
111 }
112
113
114
115
116
117
118
119
120
121 public ResCUVividSeatsClient(String baseUrl, Supplier<String> tokenSupplier, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
122 this.baseUrl = baseUrl;
123 JacksonObjectMapperFactory jacksonObjectMapperFactory = createJacksonObjectMapperFactory();
124 var clientConfigV1 = createClientConfigV1(jacksonObjectMapperFactory);
125 var clientConfig = createClientConfig(jacksonObjectMapperFactory, tokenSupplier);
126 this.restProxyFactory = new RestProxyFactorySingletonImpl(new RestProxyFactoryImpl());
127 this.listingService = new ListingServiceImpl(
128 tokenSupplier,
129 this.restProxyFactory.createProxy(org.oxerr.vividseats.client.rescu.resource.v1.inventory.ListingResource.class, baseUrl, clientConfigV1, interceptors),
130 createProxy(ListingResource.class, clientConfig, bandwidthsStore, interceptors)
131 );
132 }
133
134 @Override
135 public ListingService getListingService() {
136 return this.listingService;
137 }
138
139 protected <I> I createProxy(Class<I> restInterface, ClientConfig clientConfig, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
140 var rateLimiterInterceptor = new RateLimiterInterceptor(bandwidthsStore);
141 return createProxy(restInterface, clientConfig, ArrayUtils.add(interceptors, rateLimiterInterceptor));
142 }
143
144 protected <I> I createProxy(Class<I> restInterface, ClientConfig clientConfig, Interceptor... interceptors) {
145 return this.restProxyFactory.createProxy(restInterface, baseUrl, clientConfig, interceptors);
146 }
147
148 protected ClientConfig createClientConfigV1(JacksonObjectMapperFactory jacksonObjectMapperFactory) {
149 var clientConfig = new ClientConfig();
150 clientConfig.setJacksonObjectMapperFactory(jacksonObjectMapperFactory);
151 return clientConfig;
152 }
153
154 protected ClientConfig createClientConfig(JacksonObjectMapperFactory jacksonObjectMapperFactory, Supplier<String> tokenSupplier) {
155 var clientConfig = new ClientConfig();
156 clientConfig.addDefaultParam(HeaderParam.class, "Api-token", new Object() {
157
158 @Override
159 public String toString() {
160 return tokenSupplier.get();
161 }
162
163 });
164 clientConfig.setJacksonObjectMapperFactory(jacksonObjectMapperFactory);
165 return clientConfig;
166 }
167
168 protected JacksonObjectMapperFactory createJacksonObjectMapperFactory() {
169 return new DefaultJacksonObjectMapperFactory() {
170
171 @Override
172 public void configureObjectMapper(ObjectMapper objectMapper) {
173 super.configureObjectMapper(objectMapper);
174 objectMapper.registerModule(new JavaTimeModule());
175 objectMapper.setSerializationInclusion(Include.NON_ABSENT);
176 objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
177 objectMapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
178 objectMapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
179 }
180
181 };
182 }
183
184 }