All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.monarchapis.client.resource.AbstractResource Maven / Gradle / Ivy

Go to download

A Fluent API wrapper around Apache HTTP Client that handles both synchronous and asynchronous REST calls.

The newest version!
/*
 * Copyright (C) 2015 CapTech Ventures, Inc.
 * (http://www.captechconsulting.com) All Rights Reserved.
 *
 * Licensed 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.monarchapis.client.resource;

import java.lang.reflect.Type;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import com.monarchapis.client.rest.AsyncFuture;
import com.monarchapis.client.rest.BaseClient;
import com.monarchapis.client.rest.Callback;
import com.monarchapis.client.rest.RequestProcessor;
import com.monarchapis.client.rest.RestAsyncClient;
import com.monarchapis.client.rest.RestClient;
import com.monarchapis.client.rest.RestClientFactory;
import com.monarchapis.client.rest.RestException;
import com.monarchapis.client.rest.RestResponse;

public abstract class AbstractResource {
	private static ObjectMapper MAPPER = getObjectMapper();

	private String baseUrl;
	private List requestSigners;
	private RestClientFactory clientFactory;

	public AbstractResource(String baseUrl, RestClientFactory clientFactory) {
		this(baseUrl, clientFactory, null);
	}

	public AbstractResource(String baseUrl, RestClientFactory clientFactory, List requestSigners) {
		baseUrl = StringUtils.removeEnd(baseUrl, "/");

		if (StringUtils.isBlank(baseUrl)) {
			throw new IllegalArgumentException("baseUrl must not be blank or null");
		}

		if (clientFactory == null) {
			throw new IllegalArgumentException("clientFactory must not be null");
		}

		this.baseUrl = baseUrl;
		this.clientFactory = clientFactory;
		this.requestSigners = requestSigners;
	}

	public RestClient newClient(String method, String path) {
		return clientFactory.create(method, getBaseUrl() + path);
	}

	public RestAsyncClient newAsyncClient(String method, String path) {
		return clientFactory.createAsync(method, getBaseUrl() + path);
	}

	public String getBaseUrl() {
		return baseUrl;
	}

	public void setRequestSigner(List requestSigners) {
		this.requestSigners = requestSigners;
	}

	public List getRequestSigners() {
		return requestSigners;
	}

	protected static void require(String argument, String message) {
		if (StringUtils.isBlank(argument)) {
			throw new IllegalArgumentException(message);
		}
	}

	protected static void require(Object argument, String message) {
		if (argument == null) {
			throw new IllegalArgumentException(message);
		}
	}

	protected String convert(String value) {
		return value;
	}

	protected String convert(DateTime dateTime) {
		return dateTime != null ? dateTime.toString() : null;
	}

	protected String convert(Object value) {
		return value != null ? String.valueOf(value) : null;
	}

	protected String toJson(Object value) {
		try {
			return MAPPER.writeValueAsString(value);
		} catch (JsonProcessingException e) {
			throw new RestException(e);
		}
	}

	protected void signRequest(BaseClient client) {
		if (requestSigners != null) {
			for (RequestProcessor requestSigner : requestSigners) {
				requestSigner.processRequest(client);
			}
		}
	}

	protected  T parseAs(RestResponse response, Class clazz) {
		checkStatusCode(response);

		return parseAs(response.getResponseBody(), clazz);
	}

	protected  T parseAs(RestResponse response, TypeReference reference) {
		checkStatusCode(response);

		return parseAs(response.getResponseBody(), reference);
	}

	@SuppressWarnings("unchecked")
	protected static  T parseAs(String response, Class clazz) {
		try {
			if (clazz == Void.class) {
				return (T) Void.TYPE;
			}

			return MAPPER.readValue(response, clazz);
		} catch (Exception e) {
			throw new RestException(e);
		}
	}

	protected static  T parseAs(String response, final TypeReference reference) {
		try {
			return MAPPER.readValue(response, new com.fasterxml.jackson.core.type.TypeReference() {
				public Type getType() {
					return reference.getType();
				}
			});
		} catch (Exception e) {
			throw new RestException(e);
		}
	}

	protected void checkStatusCode(RestResponse response) {
		if (response.getStatusCode() >= 400) {
			throwErrorException(response);
		}
	}

	protected abstract void throwErrorException(RestResponse response);

	private static ObjectMapper getObjectMapper() {
		ObjectMapper mapper = new ObjectMapper();

		mapper.registerModule(new JodaModule());
		mapper.registerModule(new GuavaModule());

		mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

		return mapper;
	}

	protected  CallbackAdapter callbackAdapter(final AsyncFuture callback, Class clazz) {
		return new CallbackAdapter(callback, clazz);
	}

	protected  CallbackAdapter callbackAdapter(final AsyncFuture callback, TypeReference typeReference) {
		return new CallbackAdapter(callback, typeReference);
	}

	protected static class CallbackAdapter implements Callback {
		final private AsyncFuture callback;
		final private Class clazz;
		final private TypeReference typeReference;

		public CallbackAdapter(AsyncFuture callback, Class clazz) {
			this.callback = callback;
			this.clazz = clazz;
			this.typeReference = null;
		}

		public CallbackAdapter(AsyncFuture callback, TypeReference typeReference) {
			this.callback = callback;
			this.clazz = null;
			this.typeReference = typeReference;
		}

		@Override
		public void completed(RestResponse response) {
			try {
				T result;

				if (clazz != null) {
					result = parseAs(response.getResponseBody(), clazz);
				} else {
					result = parseAs(response.getResponseBody(), typeReference);
				}

				callback.completed(result);
			} catch (Exception ex) {
				callback.failed(ex);
			}
		}

		@Override
		public void failed(Exception ex) {
			callback.failed(ex);
		}

		@Override
		public void cancelled() {
			callback.cancel(true);
		}
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy