package com.robinpowered.sdk; import com.google.gson.FieldNamingPolicy; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.robinpowered.sdk.credential.Credential; import com.robinpowered.sdk.exception.RobinExceptionHandler; import com.robinpowered.sdk.model.Account; import com.robinpowered.sdk.model.Identifier; import com.robinpowered.sdk.model.Invitable; import com.robinpowered.sdk.model.Urn; import com.robinpowered.sdk.model.adapter.AccountReferenceAdapter; import com.robinpowered.sdk.model.adapter.IdentifierAdapter; import com.robinpowered.sdk.model.adapter.InvitableAdapter; import com.robinpowered.sdk.model.adapter.JodaDateTimeAdapter; import com.robinpowered.sdk.model.adapter.RobinTypeAdapterFactory; import com.robinpowered.sdk.model.adapter.UrnAdapter; import com.squareup.okhttp.HttpUrl; import org.joda.time.DateTime; import retrofit.RequestInterceptor; import retrofit.RestAdapter; import retrofit.client.Client; import retrofit.converter.Converter; import retrofit.converter.GsonConverter; /** * Factory class to create and return services created by {@link retrofit.RestAdapter}. */ public class RobinServiceFactory { /** * Constants */ public static final String BASE_URL = "https://api.robinpowered.com/v1.0"; /** * Properties */ HttpUrl endpoint; public RobinServiceFactory() { this(HttpUrl.parse(BASE_URL)); } public RobinServiceFactory(HttpUrl endpoint) { this.endpoint = endpoint; } /** * Private helpers */ /** * Returns a {@link Converter} configured to deserialize Robin entities. * * @return A converter. */ protected Converter getResponseDataConverter() { Gson gson = new GsonBuilder() // Set our naming policy to transform underscores <-> camelCase .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) .registerTypeAdapter(DateTime.class, new JodaDateTimeAdapter()) .registerTypeAdapter(Invitable.class, new InvitableAdapter()) .registerTypeAdapter(Identifier.class, new IdentifierAdapter()) .registerTypeAdapterFactory(new RobinTypeAdapterFactory()) .registerTypeAdapter(Urn.class, new UrnAdapter()) .registerTypeHierarchyAdapter(Account.Reference.class, new AccountReferenceAdapter()) .serializeNulls() .create(); return new GsonConverter(gson); } /** * Returns a {@link retrofit.RestAdapter.Builder} pre-configured with a {@link GsonConverter} * and a {@link RobinExceptionHandler}. * * @return The builder. */ protected RestAdapter.Builder getRestAdapterBuilder() { RestAdapter.Builder builder = new RestAdapter.Builder(); builder.setConverter(getResponseDataConverter()); builder.setErrorHandler(new RobinExceptionHandler()); return builder; } /** * Public Factories */ /** * Factory method to create and return a Robin API Service. * * @param serviceType The service class type to create. * @return The Robin service. */ public <ServiceType> ServiceType create(Class<ServiceType> serviceType) { return create(serviceType, null); } /** * Factory method to create and return a Robin API Service with the provided auth credential. * * @param serviceType The service class type to create. * @param credential A credential used to authorize and authenticate with the service. * @return The Robin service. */ public <ServiceType> ServiceType create(Class<ServiceType> serviceType, final Credential credential) { return create(serviceType, credential, null); } /** * Factory method to create and return a Robin API Service with the provided auth credential * and http client. * * @param serviceType The service class type to create. * @param credential A credential used to authorize and authenticate with the service. * @param httpClient The http client to use for network requests. * @return The Robin service. */ public <ServiceType> ServiceType create(Class<ServiceType> serviceType, final Credential credential, final Client httpClient) { return create(serviceType, credential, httpClient, endpoint); } /** * Factory method to create and return a Robin API Service with the provided auth credential * and http client. * * @param serviceType The service class type to create. * @param credential A credential used to authorize and authenticate with the service. * @param httpClient The http client to use for network requests. * @return The Robin service. */ public <ServiceType> ServiceType create(Class<ServiceType> serviceType, final Credential credential, final Client httpClient, final HttpUrl endpoint) { RestAdapter.Builder restAdapterBuilder = getRestAdapterBuilder(); if (httpClient != null) { restAdapterBuilder.setClient(httpClient); } restAdapterBuilder.setEndpoint(endpoint.toString()); restAdapterBuilder.setRequestInterceptor( new RequestInterceptor() { @Override public void intercept(RequestFacade request) { if (null != credential) { // The existing Authorization header will not be replaced if it // already exists. request.addHeader("Authorization", credential.getBuiltValue()); } } } ); return restAdapterBuilder.build().create(serviceType); } }