package com.algolia.search; import com.algolia.search.models.common.CompressionType; import com.algolia.search.util.AlgoliaUtils; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.ForkJoinPool; import javax.annotation.Nonnull; /** Algolia's clients common configuration */ @SuppressWarnings("WeakerAccess") public abstract class ConfigBase { private static final String JAVA_VERSION = System.getProperty("java.version"); private final String applicationID; private final String apiKey; private final Map<String, String> defaultHeaders; private final int batchSize; private final boolean useSystemProxy; private final Integer readTimeOut; private final Integer writeTimeOut; private final Integer connectTimeOut; private final List<StatefulHost> hosts; private final ExecutorService executor; private final CompressionType compressionType; /** Config base builder to ensure the immutability of the configuration. */ public abstract static class Builder<T extends Builder<T>> { private final String applicationID; private final String apiKey; private final Map<String, String> defaultHeaders; private int batchSize; private boolean useSystemProxy; private Integer readTimeOut; private Integer writeTimeOut; private Integer connectTimeOut; private List<StatefulHost> hosts; private ExecutorService executor; protected CompressionType compressionType; /** * Builds a base configuration * * @param applicationID The Algolia Application ID * @param apiKey The API Key: could be Admin API Key or Search API Key * @throws NullPointerException If the ApplicationID or the APIKey or the hosts are null * @throws IllegalArgumentException If the ApplicationID or the APIKey are empty */ public Builder( @Nonnull String applicationID, @Nonnull String apiKey, @Nonnull List<StatefulHost> defaultHosts, @Nonnull CompressionType compressionType) { this.applicationID = applicationID; this.apiKey = apiKey; this.useSystemProxy = false; this.batchSize = 1000; this.hosts = defaultHosts; this.connectTimeOut = Defaults.CONNECT_TIMEOUT_MS; this.compressionType = compressionType; this.defaultHeaders = new HashMap<>(); this.defaultHeaders.put(Defaults.ALGOLIA_APPLICATION_HEADER, applicationID); this.defaultHeaders.put(Defaults.ALGOLIA_KEY_HEADER, apiKey); String clientVersion = this.getClass().getPackage().getImplementationVersion(); this.defaultHeaders.put( Defaults.USER_AGENT_HEADER, String.format("Algolia for Java (%s); JVM (%s)", clientVersion, JAVA_VERSION)); this.defaultHeaders.put(Defaults.ACCEPT_HEADER, Defaults.APPLICATION_JSON); this.defaultHeaders.put(Defaults.ACCEPT_ENCODING_HEADER, Defaults.CONTENT_ENCODING_GZIP); this.executor = ForkJoinPool.commonPool(); } /** To prevent unchecked cast warning. */ public abstract T getThis(); /** * Makes the underlying Apache HTTP Client to use JVM/System settings for the proxy. * * @deprecated Please use a custom HttpAsyncClientBuilder when instantiating the * ApacheHttpRequester instead. */ public T setUseSystemProxy(boolean useSystemProxy) { this.useSystemProxy = useSystemProxy; return getThis(); } /** Overrides the default batch size for save methods. Default = 1000 objects per chunk. */ public T setBatchSize(int batchSize) { this.batchSize = batchSize; return getThis(); } /** Overrides the default read timeout. Default = 1000ms In milliseconds */ public T setReadTimeOut(Integer readTimeOut) { this.readTimeOut = readTimeOut; return getThis(); } /** Overrides the default write timeout. Default = 30000ms In milliseconds */ public T setWriteTimeOut(Integer writeTimeOut) { this.writeTimeOut = writeTimeOut; return getThis(); } /** Overrides the default connect timeout. Default = 2000ms In milliseconds */ public T setConnectTimeOut(Integer connectTimeOut) { this.connectTimeOut = connectTimeOut; return getThis(); } /** Sets a list of specific host to target. Default hosts will be overridden. */ public T setHosts(@Nonnull List<StatefulHost> customHosts) { this.hosts = customHosts; return getThis(); } /** Sets a custom executor service. Default ForkJoinPool will be overridden. */ public T setExecutorService(ExecutorService executorService) { this.executor = executorService; return getThis(); } /** * Associates the specified value with the specified key in this map. If the map previously * contained a mapping for the key, the old value is replaced. */ public T addExtraHeaders(@Nonnull String headerKey, @Nonnull String headerValue) { this.defaultHeaders.put(headerKey, headerValue); return getThis(); } /** * Copies all of the mappings from the specified map to this map. These mappings will replace * any mappings that this map had for any of the keys currently in the specified map. */ public T addExtraHeaders(Map<String, String> headers) { this.defaultHeaders.putAll(headers); return getThis(); } } protected ConfigBase(Builder<?> builder) { Objects.requireNonNull(builder.applicationID, "An ApplicationID is required."); Objects.requireNonNull(builder.apiKey, "An API key is required."); Objects.requireNonNull(builder.hosts, "Default hosts are required."); if (AlgoliaUtils.isEmptyWhiteSpace(builder.applicationID)) { throw new IllegalArgumentException("The ApplicationID can't be empty."); } if (AlgoliaUtils.isEmptyWhiteSpace(builder.apiKey)) { throw new IllegalArgumentException("The APIKey can't be empty."); } this.apiKey = builder.apiKey; this.applicationID = builder.applicationID; this.defaultHeaders = builder.defaultHeaders; this.useSystemProxy = builder.useSystemProxy; this.batchSize = builder.batchSize; this.compressionType = builder.compressionType; this.readTimeOut = builder.readTimeOut; this.writeTimeOut = builder.writeTimeOut; this.connectTimeOut = builder.connectTimeOut; this.hosts = builder.hosts; this.executor = builder.executor; } public String getApplicationID() { return applicationID; } public String getApiKey() { return apiKey; } public Map<String, String> getDefaultHeaders() { return defaultHeaders; } /** * Retrieve the settings which instructs the underlying Apache HTTP Client to use JVM/System * settings for the proxy. * * @deprecated Please use a custom HttpAsyncClientBuilder when instantiating the * ApacheHttpRequester instead. */ public boolean getUseSystemProxy() { return useSystemProxy; } public int getBatchSize() { return batchSize; } public CompressionType getCompressionType() { return compressionType; } public Integer getReadTimeOut() { return readTimeOut; } public Integer getWriteTimeOut() { return writeTimeOut; } public Integer getConnectTimeOut() { return connectTimeOut; } public List<StatefulHost> getHosts() { return hosts; } public ExecutorService getExecutor() { return executor; } }