View Javadoc
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  	 * Constructs a client with the specified token.
39  	 *
40  	 * @param token the token to access the API.
41  	 * @param interceptors the interceptors to intercept the requests.
42  	 */
43  	public ResCUVividSeatsClient(String token, Interceptor... interceptors) {
44  		this(DEFAULT_BASE_URL, token, interceptors);
45  	}
46  
47  	/**
48  	 * Constructs a client with the specified token.
49  	 *
50  	 * @param token the token to access the API.
51  	 * @param bandwidthsStore the bandwidths store to store the bandwidth.
52  	 * @param interceptors the interceptors to intercept the requests.
53  	 */
54  	public ResCUVividSeatsClient(String token, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
55  		this(DEFAULT_BASE_URL, token, bandwidthsStore, interceptors);
56  	}
57  
58  	/**
59  	 * Constructs a client with the specified token.
60  	 *
61  	 * @param tokenSupplier the token supplier to access the API.
62  	 * @param interceptors the interceptors to intercept the requests.
63  	 */
64  	public ResCUVividSeatsClient(Supplier<String> tokenSupplier, Interceptor... interceptors) {
65  		this(DEFAULT_BASE_URL, tokenSupplier, interceptors);
66  	}
67  
68  	/**
69  	 * Constructs a client with the specified token.
70  	 *
71  	 * @param tokenSupplier the token supplier to access the API.
72  	 * @param bandwidthsStore the bandwidths store to store the bandwidth.
73  	 * @param interceptors the interceptors to intercept the requests.
74  	 */
75  	public ResCUVividSeatsClient(Supplier<String> tokenSupplier, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
76  		this(DEFAULT_BASE_URL, tokenSupplier, bandwidthsStore, interceptors);
77  	}
78  
79  	/**
80  	 * Constructs a client with the specified base URL and token.
81  	 *
82  	 * @param baseUrl the base URL of the API.
83  	 * @param token the token to access the API.
84  	 * @param interceptors the interceptors to intercept the requests.
85  	 */
86  	public ResCUVividSeatsClient(String baseUrl, String token, Interceptor... interceptors) {
87  		this(baseUrl, () -> token, interceptors);
88  	}
89  
90  	/**
91  	 * Constructs a client with the specified base URL and token.
92  	 *
93  	 * @param baseUrl the base URL of the API.
94  	 * @param tokenSupplier the token supplier to access the API.
95  	 * @param interceptors the interceptors to intercept the requests.
96  	 */
97  	public ResCUVividSeatsClient(String baseUrl, Supplier<String> tokenSupplier, Interceptor... interceptors) {
98  		this(baseUrl, tokenSupplier, BandwidthsStore.ofDefaults(), interceptors);
99  	}
100 
101 	/**
102 	 * Constructs a client with the specified base URL, token and bandwidths store.
103 	 *
104 	 * @param baseUrl the base URL of the API.
105 	 * @param token the token to access the API.
106 	 * @param bandwidthsStore the bandwidths store to store the bandwidth.
107 	 * @param interceptors the interceptors to intercept the requests.
108 	 */
109 	public ResCUVividSeatsClient(String baseUrl, String token, BandwidthsStore<String> bandwidthsStore, Interceptor... interceptors) {
110 		this(baseUrl, () -> token, bandwidthsStore, interceptors);
111 	}
112 
113 	/**
114 	 * Constructs a client with the specified base URL, token supplier, bandwidths store and interceptors.
115 	 *
116 	 * @param baseUrl the base URL of the API.
117 	 * @param tokenSupplier the token supplier to access the API.
118 	 * @param bandwidthsStore the bandwidths store to store the bandwidth.
119 	 * @param interceptors the interceptors to intercept the requests.
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 }