001
002package com.commercetools.api.defaultconfig;
003
004import java.net.URI;
005import java.time.Duration;
006import java.util.List;
007import java.util.Map;
008import java.util.Objects;
009import java.util.Set;
010import java.util.concurrent.ExecutorService;
011import java.util.concurrent.ScheduledExecutorService;
012import java.util.function.Function;
013import java.util.function.Predicate;
014import java.util.function.Supplier;
015import java.util.function.UnaryOperator;
016
017import javax.annotation.Nullable;
018
019import com.commercetools.api.client.*;
020import com.commercetools.api.client.error.ApiHttpExceptionFactory;
021
022import io.vrap.rmf.base.client.*;
023import io.vrap.rmf.base.client.error.HttpExceptionFactory;
024import io.vrap.rmf.base.client.http.*;
025import io.vrap.rmf.base.client.oauth2.ClientCredentials;
026import io.vrap.rmf.base.client.oauth2.TokenStorage;
027import io.vrap.rmf.base.client.oauth2.TokenSupplier;
028
029import org.slf4j.event.Level;
030
031import dev.failsafe.spi.Scheduler;
032
033/**
034 * Builder to create a {@link ApiRoot} or a project scoped {@link ProjectApiRoot}
035 */
036public class ApiRootBuilder {
037    private static final String PROJECT_KEY_MUST_BE_SET = "projectKey must be set";
038    private final ClientBuilder builder;
039    private String projectKey;
040
041    private ApiRootBuilder(ClientBuilder builder) {
042        builder.withHttpExceptionFactory(ApiHttpExceptionFactory::of);
043        this.builder = builder;
044    }
045
046    public static ApiRootBuilder of() {
047        return new ApiRootBuilder(ClientBuilder.of());
048    }
049
050    public static ApiRootBuilder of(ExecutorService httpClientExecutorService) {
051        return new ApiRootBuilder(ClientBuilder.of(httpClientExecutorService));
052    }
053
054    public static ApiRootBuilder of(final ApiHttpClient httpClient) {
055        return new ApiRootBuilder(ClientBuilder.of(httpClient));
056    }
057
058    public static ApiRootBuilder of(final VrapHttpClient httpClient) {
059        return new ApiRootBuilder(ClientBuilder.of(httpClient));
060    }
061
062    public static ApiRootBuilder of(final HandlerStack stack) {
063        return new ApiRootBuilder(ClientBuilder.of(stack));
064    }
065
066    public ApiRootBuilder withProjectKey(final String projectKey) {
067        this.projectKey = projectKey;
068
069        return this;
070    }
071
072    public ApiRootBuilder withAuthCircuitBreaker() {
073        return with(ClientBuilder::withAuthCircuitBreaker);
074    }
075
076    public ApiRootBuilder withoutAuthCircuitBreaker() {
077        return with(ClientBuilder::withoutAuthCircuitBreaker);
078    }
079
080    public ApiRootBuilder withAuthRetries(final int authRetries) {
081        return with(clientBuilder -> clientBuilder.withAuthRetries(authRetries));
082    }
083
084    public ApiRootBuilder withHandlerStack(final HandlerStack stack) {
085        return with(clientBuilder -> clientBuilder.withHandlerStack(stack));
086    }
087
088    public ApiRootBuilder withHttpClient(final VrapHttpClient httpClient) {
089        return with(clientBuilder -> clientBuilder.withHttpClient(httpClient));
090    }
091
092    public ApiRootBuilder withSerializer(final ResponseSerializer serializer) {
093        return with(clientBuilder -> clientBuilder.withSerializer(serializer));
094    }
095
096    public ApiRootBuilder withSerializer(final Supplier<ResponseSerializer> serializer) {
097        return with(clientBuilder -> clientBuilder.withSerializer(serializer));
098    }
099
100    public ApiRootBuilder withHttpExceptionFactory(final HttpExceptionFactory factory) {
101        return with(clientBuilder -> clientBuilder.withHttpExceptionFactory(factory));
102    }
103
104    public ApiRootBuilder withHttpExceptionFactory(final Function<ResponseSerializer, HttpExceptionFactory> factory) {
105        return with(clientBuilder -> clientBuilder.withHttpExceptionFactory(factory));
106    }
107
108    public ApiRootBuilder withHttpExceptionFactory(final Supplier<HttpExceptionFactory> factory) {
109        return with(clientBuilder -> clientBuilder.withHttpExceptionFactory(factory));
110    }
111
112    public ApiRootBuilder defaultClient(final ClientCredentials credentials) {
113        return defaultClient(credentials, ServiceRegion.GCP_EUROPE_WEST1);
114    }
115
116    public ApiRootBuilder defaultClient(final ClientCredentials credentials, ServiceRegionConfig serviceRegion) {
117        return defaultClient(URI.create(serviceRegion.getApiUrl())).withClientCredentialsFlow(credentials,
118            serviceRegion.getOAuthTokenUrl());
119    }
120
121    public ApiRootBuilder defaultClient(final ClientCredentials credentials, final String tokenEndpoint,
122            final String apiEndpoint) {
123        return defaultClient(URI.create(apiEndpoint)).withClientCredentialsFlow(credentials, tokenEndpoint);
124    }
125
126    public ApiRootBuilder defaultClient(final String apiEndpoint, final ClientCredentials credentials,
127            final String tokenEndpoint) {
128        return defaultClient(URI.create(apiEndpoint)).withClientCredentialsFlow(credentials, tokenEndpoint);
129    }
130
131    public ApiRootBuilder defaultClient(final String apiEndpoint) {
132        return defaultClient(URI.create(apiEndpoint));
133    }
134
135    public ApiRootBuilder defaultClient(final URI apiEndpoint) {
136        return with(clientBuilder -> clientBuilder.defaultClient(apiEndpoint)
137                .withInternalLoggerFactory(ApiInternalLoggerFactory::get));
138    }
139
140    public ApiRootBuilder withOAuthExecutorService(final ExecutorService executorService) {
141        return with(clientBuilder -> clientBuilder.withOAuthExecutorService(executorService));
142    }
143
144    public ApiRootBuilder withOAuthExecutorService(final Supplier<ExecutorService> executorService) {
145        return with(clientBuilder -> clientBuilder.withOAuthExecutorService(executorService));
146    }
147
148    public ApiRootBuilder withClientCredentialsFlow(final ClientCredentials credentials, final String tokenEndpoint) {
149        return with(clientBuilder -> clientBuilder.withClientCredentialsFlow(credentials, tokenEndpoint));
150    }
151
152    public ApiRootBuilder withClientCredentialsFlow(final ClientCredentials credentials, final String tokenEndpoint,
153            final Supplier<HandlerStack> httpClient) {
154        return with(clientBuilder -> clientBuilder.withClientCredentialsFlow(credentials, tokenEndpoint, httpClient));
155    }
156
157    public ApiRootBuilder withClientCredentialsFlow(final ClientCredentials credentials, final String tokenEndpoint,
158            final VrapHttpClient httpClient) {
159        return with(clientBuilder -> clientBuilder.withClientCredentialsFlow(credentials, tokenEndpoint, httpClient));
160    }
161
162    public ApiRootBuilder withClientCredentialsFlow(final ClientCredentials credentials, final URI tokenEndpoint) {
163        return with(clientBuilder -> clientBuilder.withClientCredentialsFlow(credentials, tokenEndpoint));
164    }
165
166    public ApiRootBuilder withClientCredentialsFlow(final ClientCredentials credentials, final URI tokenEndpoint,
167            final Supplier<HandlerStack> httpClient) {
168        return with(clientBuilder -> clientBuilder.withClientCredentialsFlow(credentials, tokenEndpoint, httpClient));
169    }
170
171    public ApiRootBuilder withClientCredentialsFlow(final ClientCredentials credentials, final URI tokenEndpoint,
172            final VrapHttpClient httpClient) {
173        return with(clientBuilder -> clientBuilder.withClientCredentialsFlow(credentials, tokenEndpoint, httpClient));
174    }
175
176    public ApiRootBuilder withStaticTokenFlow(final AuthenticationToken token) {
177        return with(clientBuilder -> clientBuilder.withStaticTokenFlow(token));
178    }
179
180    public ApiRootBuilder withAnonymousSessionFlow(final ClientCredentials credentials, final String tokenEndpoint) {
181        return with(clientBuilder -> clientBuilder.withAnonymousSessionFlow(credentials, tokenEndpoint));
182    }
183
184    public ApiRootBuilder withAnonymousSessionFlow(final ClientCredentials credentials, final String tokenEndpoint,
185            final Supplier<HandlerStack> httpClient) {
186        return with(clientBuilder -> clientBuilder.withAnonymousSessionFlow(credentials, tokenEndpoint, httpClient));
187    }
188
189    public ApiRootBuilder withAnonymousSessionFlow(final ClientCredentials credentials, final String tokenEndpoint,
190            final VrapHttpClient httpClient) {
191        return with(clientBuilder -> clientBuilder.withAnonymousSessionFlow(credentials, tokenEndpoint, httpClient));
192    }
193
194    public ApiRootBuilder withAnonymousRefreshFlow(final ClientCredentials credentials,
195            final ServiceRegion serviceRegion, final TokenStorage storage) {
196        withApiBaseUrl(serviceRegion.getApiUrl());
197        Objects.requireNonNull(projectKey, PROJECT_KEY_MUST_BE_SET);
198        return withAnonymousRefreshFlow(credentials, serviceRegion.getAnonymousFlowTokenURL(projectKey),
199            serviceRegion.getOAuthTokenUrl(), storage);
200    }
201
202    public ApiRootBuilder withAnonymousRefreshFlow(final ClientCredentials credentials,
203            final ServiceRegion serviceRegion, final String projectKey, final TokenStorage storage) {
204        withApiBaseUrl(serviceRegion.getApiUrl());
205        withProjectKey(projectKey);
206        return withAnonymousRefreshFlow(credentials, serviceRegion.getAnonymousFlowTokenURL(projectKey),
207            serviceRegion.getOAuthTokenUrl(), storage);
208    }
209
210    public ApiRootBuilder withAnonymousRefreshFlow(final ClientCredentials credentials, final String anonTokenEndpoint,
211            final String refreshTokenEndpoint, final TokenStorage storage) {
212        return with(clientBuilder -> clientBuilder.withAnonymousRefreshFlow(credentials, anonTokenEndpoint,
213            refreshTokenEndpoint, storage));
214    }
215
216    public ApiRootBuilder withAnonymousRefreshFlow(final ClientCredentials credentials, final String anonTokenEndpoint,
217            final String refreshTokenEndpoint, final TokenStorage storage, final Supplier<HandlerStack> httpClient) {
218        return with(clientBuilder -> clientBuilder.withAnonymousRefreshFlow(credentials, anonTokenEndpoint,
219            refreshTokenEndpoint, storage, httpClient));
220    }
221
222    public ApiRootBuilder withAnonymousRefreshFlow(final ClientCredentials credentials, final String anonTokenEndpoint,
223            final String refreshTokenEndpoint, final TokenStorage storage, final VrapHttpClient httpClient) {
224        return with(clientBuilder -> clientBuilder.withAnonymousRefreshFlow(credentials, anonTokenEndpoint,
225            refreshTokenEndpoint, storage, httpClient));
226    }
227
228    public ApiRootBuilder withGlobalCustomerPasswordFlow(final ClientCredentials credentials, final String email,
229            final String password, final String tokenEndpoint) {
230        return with(
231            clientBuilder -> clientBuilder.withGlobalCustomerPasswordFlow(credentials, email, password, tokenEndpoint));
232    }
233
234    public ApiRootBuilder withGlobalCustomerPasswordFlow(final ClientCredentials credentials, final String email,
235            final String password, final String tokenEndpoint, final Supplier<HandlerStack> httpClient) {
236        return with(clientBuilder -> clientBuilder.withGlobalCustomerPasswordFlow(credentials, email, password,
237            tokenEndpoint, httpClient));
238    }
239
240    public ApiRootBuilder withGlobalCustomerPasswordFlow(final ClientCredentials credentials, final String email,
241            final String password, final String tokenEndpoint, final VrapHttpClient httpClient) {
242        return with(clientBuilder -> clientBuilder.withGlobalCustomerPasswordFlow(credentials, email, password,
243            tokenEndpoint, httpClient));
244    }
245
246    public ApiRootBuilder addAcceptGZipMiddleware() {
247        return with(ClientBuilder::addAcceptGZipMiddleware);
248    }
249
250    public ApiRootBuilder withErrorMiddleware() {
251        return with(ClientBuilder::withErrorMiddleware);
252    }
253
254    public ApiRootBuilder withErrorMiddleware(ErrorMiddleware.ExceptionMode exceptionMode) {
255        return with(clientBuilder -> clientBuilder.withErrorMiddleware(exceptionMode));
256    }
257
258    public ApiRootBuilder withErrorMiddleware(final ErrorMiddleware errorMiddleware) {
259        return with(clientBuilder -> clientBuilder.withErrorMiddleware(errorMiddleware));
260    }
261
262    public ApiRootBuilder withTelemetryMiddleware(final Supplier<TelemetryMiddleware> telemetryMiddleware) {
263        return with(clientBuilder -> clientBuilder.withTelemetryMiddleware(telemetryMiddleware));
264    }
265
266    public ApiRootBuilder withTelemetryMiddleware(final TelemetryMiddleware telemetryMiddleware) {
267        return with(clientBuilder -> clientBuilder.withTelemetryMiddleware(telemetryMiddleware));
268    }
269
270    public ApiRootBuilder addConcurrentModificationMiddleware() {
271        return addConcurrentModificationMiddleware(ConcurrentModificationMiddleware.of());
272    }
273
274    public ApiRootBuilder addConcurrentModificationMiddleware(final int maxRetries) {
275        return addConcurrentModificationMiddleware(ConcurrentModificationMiddleware.of(maxRetries));
276    }
277
278    public ApiRootBuilder addConcurrentModificationMiddleware(final int maxRetries, final long delay,
279            final long maxDelay) {
280        return addConcurrentModificationMiddleware(ConcurrentModificationMiddleware.of(maxRetries, delay, maxDelay));
281    }
282
283    public ApiRootBuilder addConcurrentModificationMiddleware(ConcurrentModificationMiddleware middleware) {
284        return addMiddleware(middleware);
285    }
286
287    public ApiRootBuilder addNotFoundExceptionMiddleware(NotFoundExceptionMiddleware notFoundExceptionMiddleware) {
288        return with(clientBuilder -> clientBuilder.addNotFoundExceptionMiddleware(notFoundExceptionMiddleware));
289    }
290
291    public ApiRootBuilder addNotFoundExceptionMiddleware() {
292        return with(ClientBuilder::addNotFoundExceptionMiddleware);
293    }
294
295    public ApiRootBuilder addNotFoundExceptionMiddleware(final Set<ApiHttpMethod> method) {
296        return with(clientBuilder -> clientBuilder.addNotFoundExceptionMiddleware(method));
297    }
298
299    public ApiRootBuilder addNotFoundExceptionMiddleware(final Predicate<ApiHttpRequest> requestPredicate) {
300        return with(clientBuilder -> clientBuilder.addNotFoundExceptionMiddleware(requestPredicate));
301    }
302
303    public ApiRootBuilder withRetryMiddleware(final Supplier<RetryRequestMiddleware> retryMiddleware) {
304        return with(clientBuilder -> clientBuilder.withRetryMiddleware(retryMiddleware));
305    }
306
307    public ApiRootBuilder withRetryMiddleware(final RetryRequestMiddleware retryMiddleware) {
308        return with(clientBuilder -> clientBuilder.withRetryMiddleware(retryMiddleware));
309    }
310
311    public ApiRootBuilder withRetryMiddleware(final int maxRetries) {
312        return with(clientBuilder -> clientBuilder.withRetryMiddleware(maxRetries));
313    }
314
315    public ApiRootBuilder withRetryMiddleware(final int maxRetries, List<Integer> statusCodes) {
316        return with(clientBuilder -> clientBuilder.withRetryMiddleware(maxRetries, statusCodes));
317    }
318
319    public ApiRootBuilder withRetryMiddleware(final int maxRetries, List<Integer> statusCodes,
320            final List<Class<? extends Throwable>> failures) {
321        return with(clientBuilder -> clientBuilder.withRetryMiddleware(maxRetries, statusCodes, failures));
322    }
323
324    public ApiRootBuilder withRetryMiddleware(final int maxRetries, final long delay, final long maxDelay,
325            List<Integer> statusCodes, final List<Class<? extends Throwable>> failures,
326            final FailsafeRetryPolicyBuilderOptions fn) {
327        return with(
328            clientBuilder -> clientBuilder.withRetryMiddleware(maxRetries, delay, maxDelay, statusCodes, failures, fn));
329    }
330
331    public ApiRootBuilder withRetryMiddleware(final int maxRetries, final long delay, final long maxDelay,
332            final FailsafeRetryPolicyBuilderOptions fn) {
333        return with(clientBuilder -> clientBuilder.withRetryMiddleware(maxRetries, delay, maxDelay, fn));
334    }
335
336    public ApiRootBuilder withRetryMiddleware(final ScheduledExecutorService executorService, final int maxRetries) {
337        return with(clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries));
338    }
339
340    public ApiRootBuilder withRetryMiddleware(final ScheduledExecutorService executorService, final int maxRetries,
341            List<Integer> statusCodes) {
342        return with(clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, statusCodes));
343    }
344
345    public ApiRootBuilder withRetryMiddleware(final ScheduledExecutorService executorService, final int maxRetries,
346            List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
347        return with(
348            clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, statusCodes, failures));
349    }
350
351    public ApiRootBuilder withRetryMiddleware(final ScheduledExecutorService executorService, final int maxRetries,
352            final long delay, final long maxDelay, List<Integer> statusCodes,
353            final List<Class<? extends Throwable>> failures, final FailsafeRetryPolicyBuilderOptions fn) {
354        return with(clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, delay, maxDelay,
355            statusCodes, failures, fn));
356    }
357
358    public ApiRootBuilder withRetryMiddleware(final ScheduledExecutorService executorService, final int maxRetries,
359            final long delay, final long maxDelay, final FailsafeRetryPolicyBuilderOptions fn) {
360        return with(
361            clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, delay, maxDelay, fn));
362    }
363
364    public ApiRootBuilder withRetryMiddleware(final ExecutorService executorService, final int maxRetries) {
365        return with(clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries));
366    }
367
368    public ApiRootBuilder withRetryMiddleware(final ExecutorService executorService, final int maxRetries,
369            List<Integer> statusCodes) {
370        return with(clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, statusCodes));
371    }
372
373    public ApiRootBuilder withRetryMiddleware(final ExecutorService executorService, final int maxRetries,
374            List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
375        return with(
376            clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, statusCodes, failures));
377    }
378
379    public ApiRootBuilder withRetryMiddleware(final ExecutorService executorService, final int maxRetries,
380            final long delay, final long maxDelay, List<Integer> statusCodes,
381            final List<Class<? extends Throwable>> failures, final FailsafeRetryPolicyBuilderOptions fn) {
382        return with(clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, delay, maxDelay,
383            statusCodes, failures, fn));
384    }
385
386    public ApiRootBuilder withRetryMiddleware(final ExecutorService executorService, final int maxRetries,
387            final long delay, final long maxDelay, final FailsafeRetryPolicyBuilderOptions fn) {
388        return with(
389            clientBuilder -> clientBuilder.withRetryMiddleware(executorService, maxRetries, delay, maxDelay, fn));
390    }
391
392    public ApiRootBuilder withRetryMiddleware(final Scheduler scheduler, final int maxRetries) {
393        return with(clientBuilder -> clientBuilder.withRetryMiddleware(scheduler, maxRetries));
394    }
395
396    public ApiRootBuilder withRetryMiddleware(final Scheduler scheduler, final int maxRetries,
397            List<Integer> statusCodes) {
398        return with(clientBuilder -> clientBuilder.withRetryMiddleware(scheduler, maxRetries, statusCodes));
399    }
400
401    public ApiRootBuilder withRetryMiddleware(final Scheduler scheduler, final int maxRetries,
402            List<Integer> statusCodes, final List<Class<? extends Throwable>> failures) {
403        return with(clientBuilder -> clientBuilder.withRetryMiddleware(scheduler, maxRetries, statusCodes, failures));
404    }
405
406    public ApiRootBuilder withRetryMiddleware(final Scheduler scheduler, final int maxRetries, final long delay,
407            final long maxDelay, List<Integer> statusCodes, final List<Class<? extends Throwable>> failures,
408            final FailsafeRetryPolicyBuilderOptions fn) {
409        return with(clientBuilder -> clientBuilder.withRetryMiddleware(scheduler, maxRetries, delay, maxDelay,
410            statusCodes, failures, fn));
411    }
412
413    public ApiRootBuilder withRetryMiddleware(final Scheduler scheduler, final int maxRetries, final long delay,
414            final long maxDelay, final FailsafeRetryPolicyBuilderOptions fn) {
415        return with(clientBuilder -> clientBuilder.withRetryMiddleware(scheduler, maxRetries, delay, maxDelay, fn));
416    }
417
418    public ApiRootBuilder withQueueMiddleware(final Supplier<QueueRequestMiddleware> queueMiddleware) {
419        return with(clientBuilder -> clientBuilder.withQueueMiddleware(queueMiddleware));
420    }
421
422    public ApiRootBuilder withQueueMiddleware(final QueueRequestMiddleware queueMiddleware) {
423        return with(clientBuilder -> clientBuilder.withQueueMiddleware(queueMiddleware));
424    }
425
426    public ApiRootBuilder withQueueMiddleware(final int maxRequests, final Duration maxWaitTime) {
427        return with(clientBuilder -> clientBuilder.withQueueMiddleware(maxRequests, maxWaitTime));
428    }
429
430    public ApiRootBuilder withQueueMiddleware(final Scheduler scheduler, final int maxRequests,
431            final Duration maxWaitTime) {
432        return with(clientBuilder -> clientBuilder.withQueueMiddleware(scheduler, maxRequests, maxWaitTime));
433    }
434
435    public ApiRootBuilder withQueueMiddleware(final ScheduledExecutorService executorService, final int maxRequests,
436            final Duration maxWaitTime) {
437        return with(clientBuilder -> clientBuilder.withQueueMiddleware(executorService, maxRequests, maxWaitTime));
438    }
439
440    public ApiRootBuilder withQueueMiddleware(final ExecutorService executorService, final int maxRequests,
441            final Duration maxWaitTime) {
442        return with(clientBuilder -> clientBuilder.withQueueMiddleware(executorService, maxRequests, maxWaitTime));
443    }
444
445    public ApiRootBuilder withOAuthMiddleware(final Supplier<OAuthMiddleware> oAuthMiddleware) {
446        return with(clientBuilder -> clientBuilder.withOAuthMiddleware(oAuthMiddleware));
447    }
448
449    public ApiRootBuilder withOAuthMiddleware(final OAuthMiddleware oAuthMiddleware) {
450        return with(clientBuilder -> clientBuilder.withOAuthMiddleware(oAuthMiddleware));
451    }
452
453    public ApiRootBuilder withTokenSupplier(final TokenSupplier tokenSupplier) {
454        return with(clientBuilder -> clientBuilder.withTokenSupplier(tokenSupplier));
455    }
456
457    public ApiRootBuilder withTokenSupplier(final Supplier<TokenSupplier> tokenSupplier) {
458        return with(clientBuilder -> clientBuilder.withTokenSupplier(tokenSupplier));
459    }
460
461    public ApiRootBuilder withInternalLoggerMiddleware(final InternalLoggerMiddleware internalLoggerMiddleware) {
462        return with(clientBuilder -> clientBuilder.withInternalLoggerMiddleware(internalLoggerMiddleware));
463    }
464
465    public ApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactory internalLoggerFactory) {
466        return with(clientBuilder -> clientBuilder.withInternalLoggerFactory(internalLoggerFactory));
467    }
468
469    public ApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactory internalLoggerFactory,
470            final Level responseLogEvent, final Level deprecationLogEvent) {
471        return with(clientBuilder -> clientBuilder.withInternalLoggerFactory(internalLoggerFactory, responseLogEvent,
472            deprecationLogEvent));
473    }
474
475    public ApiRootBuilder withInternalLoggerFactory(final InternalLoggerFactory internalLoggerFactory,
476            final Level responseLogEvent, final Level deprecationLogEvent, final Level defaultExceptionLogEvent,
477            final Map<Class<? extends Throwable>, Level> exceptionLogEvents) {
478        return with(clientBuilder -> clientBuilder.withInternalLoggerFactory(internalLoggerFactory, responseLogEvent,
479            deprecationLogEvent, defaultExceptionLogEvent, exceptionLogEvents));
480    }
481
482    public ApiRootBuilder withApiBaseUrl(String apiBaseUrl) {
483        return with(clientBuilder -> clientBuilder.withApiBaseUrl(apiBaseUrl));
484    }
485
486    public ApiRootBuilder withApiBaseUrl(final URI apiBaseUrl) {
487        return with(clientBuilder -> clientBuilder.withApiBaseUrl(apiBaseUrl));
488    }
489
490    public ApiRootBuilder withUserAgentSupplier(final Supplier<String> userAgentSupplier) {
491        return with(clientBuilder -> clientBuilder.withUserAgentSupplier(userAgentSupplier));
492    }
493
494    public ApiRootBuilder addCorrelationIdProvider(final @Nullable CorrelationIdProvider correlationIdProvider) {
495        return addCorrelationIdProvider(correlationIdProvider, true);
496    }
497
498    private ApiRootBuilder addCorrelationIdProvider(final @Nullable CorrelationIdProvider correlationIdProvider,
499            final boolean replace) {
500        return with(clientBuilder -> clientBuilder.addCorrelationIdProvider(correlationIdProvider, replace));
501    }
502
503    public ApiRootBuilder withMiddleware(final Middleware middleware, final Middleware... middlewares) {
504        return with(clientBuilder -> clientBuilder.withMiddleware(middleware, middlewares));
505    }
506
507    public ApiRootBuilder addMiddleware(final Middleware middleware, final Middleware... middlewares) {
508        return with(clientBuilder -> clientBuilder.addMiddleware(middleware, middlewares));
509    }
510
511    public ApiRootBuilder withMiddlewares(final List<Middleware> middlewares) {
512        return with(clientBuilder -> clientBuilder.withMiddlewares(middlewares));
513    }
514
515    public ApiRootBuilder addMiddlewares(final List<Middleware> middlewares) {
516        return with(clientBuilder -> clientBuilder.addMiddlewares(middlewares));
517    }
518
519    public ApiRootBuilder with(UnaryOperator<ClientBuilder> builderUnaryOperator) {
520        builderUnaryOperator.apply(builder);
521
522        return this;
523    }
524
525    public ApiRoot build() {
526        return ApiRoot.fromClient(clientSupplier().get());
527    }
528
529    public ApiHttpClient buildClient() {
530        return clientSupplier().get();
531    }
532
533    public Supplier<ApiHttpClient> clientSupplier() {
534        return builder::build;
535    }
536
537    /**
538     * @deprecated use {@link #build(String)}  instead
539     * @param projectKey the project key to be used
540     * @return Builder
541     */
542    @Deprecated
543    public ByProjectKeyRequestBuilder buildForProject(final String projectKey) {
544        addCorrelationIdProvider(new ApiCorrelationIdProvider(projectKey), false);
545        return ApiRoot.fromClient(builder.build()).withProjectKey(projectKey);
546    }
547
548    public ProjectApiRoot buildProjectRoot() {
549        Objects.requireNonNull(projectKey, PROJECT_KEY_MUST_BE_SET);
550        addCorrelationIdProvider(new ApiCorrelationIdProvider(projectKey), false);
551        return ProjectApiRoot.fromClient(projectKey, builder.build());
552    }
553
554    /**
555     * @deprecated use {@link #build(String)}  instead
556     * @param projectKey the project key to be used
557     * @return Builder
558     */
559    @Deprecated
560    public ProjectApiRoot buildProjectRoot(final String projectKey) {
561        addCorrelationIdProvider(new ApiCorrelationIdProvider(projectKey), false);
562        return ProjectApiRoot.fromClient(projectKey, builder.build());
563    }
564
565    public ProjectApiRoot build(final String projectKey) {
566        addCorrelationIdProvider(new ApiCorrelationIdProvider(projectKey), false);
567        return ProjectApiRoot.fromClient(projectKey, builder.build());
568    }
569
570    public static ByProjectKeyRequestBuilder createForProject(final String projectKey,
571            final ApiHttpClient clientSupplier) {
572        return ApiRoot.fromClient(clientSupplier).withProjectKey(projectKey);
573    }
574}