/*
* Copyright 2015 LINE Corporation
*
* LINE Corporation licenses this file to you under the Apache License,
* version 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
package com.linecorp.armeria.client;
import static java.util.Objects.requireNonNull;
import java.net.URI;
/**
* Creates a new client that connects to the specified {@link URI} using the builder pattern. Use the factory
* methods in {@link Clients} if you do not have many options to override.
*
* <h3>How are decorators and HTTP headers configured?</h3>
*
* <p>Unlike other options, when a user calls {@link #option(ClientOption, Object)} or {@code options()} with
* a {@link ClientOption#DECORATION} or a {@link ClientOption#HTTP_HEADERS}, this builder will not simply
* replace the old option but <em>merge</em> the specified option into the previous option value. For example:
* <pre>{@code
* ClientOptionsBuilder b = new ClientOptionsBuilder();
* b.option(ClientOption.HTTP_HEADERS, headersA);
* b.option(ClientOption.HTTP_HEADERS, headersB);
* b.option(ClientOption.DECORATION, decorationA);
* b.option(ClientOption.DECORATION, decorationB);
*
* ClientOptions opts = b.build();
* HttpHeaders httpHeaders = opts.httpHeaders();
* ClientDecoration decorations = opts.decoration();
* }</pre>
* {@code httpHeaders} will contain all HTTP headers of {@code headersA} and {@code headersB}.
* If {@code headersA} and {@code headersB} have the headers with the same name, the duplicate header in
* {@code headerB} will replace the one with the same name in {@code headerA}.
* Similarly, {@code decorations} will contain all decorators of {@code decorationA} and {@code decorationB},
* but there will be no replacement but only addition.
*/
public final class ClientBuilder extends AbstractClientOptionsBuilder<ClientBuilder> {
private final URI uri;
private ClientFactory factory = ClientFactory.DEFAULT;
/**
* Creates a new {@link ClientBuilder} that builds the client that connects to the specified {@code uri}.
*/
public ClientBuilder(String uri) {
this(URI.create(requireNonNull(uri, "uri")));
}
/**
* Creates a new {@link ClientBuilder} that builds the client that connects to the specified {@link URI}.
*/
public ClientBuilder(URI uri) {
this.uri = requireNonNull(uri, "uri");
}
/**
* Sets the {@link ClientFactory} of the client. The default is {@link ClientFactory#DEFAULT}.
*/
public ClientBuilder factory(ClientFactory factory) {
this.factory = requireNonNull(factory, "factory");
return this;
}
/**
* Creates a new client which implements the specified {@code clientType}.
*
* @throws IllegalArgumentException if the scheme of the {@code uri} specified in
* {@link #ClientBuilder(String)} or the specified {@code clientType} is
* unsupported for the scheme
*/
@SuppressWarnings("unchecked")
public <T> T build(Class<T> clientType) {
requireNonNull(clientType, "clientType");
return factory.newClient(uri, clientType, buildOptions());
}
}