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

com.leonarduk.clearcheckbook.calls.AbstractCall Maven / Gradle / Ivy

Go to download

A Java library to access the HTTP developer API for Clearcheckbook.com, the money management website.

There is a newer version: 1.4
Show newest version
/**
 * AbstractCall
 *
 * @author ${author}
 * @since 10-Jul-2016
 */
package com.leonarduk.clearcheckbook.calls;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.type.TypeReference;

import com.leonarduk.clearcheckbook.ClearCheckBookConnection;
import com.leonarduk.clearcheckbook.ClearcheckbookException;
import com.leonarduk.clearcheckbook.dto.AbstractDataType;
import com.leonarduk.clearcheckbook.dto.ParsedNameValuePair;

/**
 * Abstract template class to hold the main processing shared by the API calls. Methods are
 * protected scope to be overriden by a public scope version in concrete child class.
 *
 * @author Stephen Leonard
 * @param 
 *            the generic type
 * @since 29 Jan 2014
 */
abstract public class AbstractCall> {

	/** The Constant _logger. */
	private static final Logger _logger = Logger.getLogger(AbstractCall.class);

	/** The connection. */
	private final ClearCheckBookConnection connection;

	/** The data type class. */
	private final Class dataTypeClass;

	/**
	 * Instantiates a new abstract call.
	 *
	 * @param connection
	 *            the connection
	 * @param dataTypeClass
	 *            the data type class
	 */
	protected AbstractCall(final ClearCheckBookConnection connection,
	        final Class dataTypeClass) {
		this.connection = connection;
		this.dataTypeClass = dataTypeClass;
	}

	/**
	 * Helper wrapper function to iterate over a list of items to insert/edit/delete calling the
	 * relevant method on each.
	 *
	 * @param dataTypeList
	 *            the data type list
	 * @return the list
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected List bulkProcess(final List dataTypeList) throws ClearcheckbookException {
		final List returnStatusList = new LinkedList<>();
		for (final T t : dataTypeList) {
			returnStatusList.add(this.process(t));
		}
		return returnStatusList;
	}

	/**
	 * Helper class to create instance of this.dataTypeClass
	 *
	 * @param map
	 *            the map
	 * @param classType
	 *            the class type
	 * @return {@link T extends AbstractDataType}
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	private T createDataTypeInstance(final HashMap map, final Class classType)
	        throws ClearcheckbookException {
		try {
			@SuppressWarnings("unchecked")
			final T dataType = (T) classType.getDeclaredConstructor(Map.class).newInstance(map);
			return dataType;
		}
		catch (InstantiationException | IllegalAccessException | IllegalArgumentException
		        | InvocationTargetException | NoSuchMethodException | SecurityException e) {
			throw new ClearcheckbookException(
			        "Failed to find constructor for " + classType.getName(), e);
		}

	}

	/**
	 * Delete.
	 *
	 * @param id
	 *            the id
	 * @return boolean - true means delete was successful
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected boolean delete(final ParsedNameValuePair id) throws ClearcheckbookException {
		AbstractCall._logger.debug("delete: " + id.getValue());
		String returnString;
		try {
			returnString = this.getConnection().deletePage(this.getUrlSuffix(), id);
			final boolean ok = Boolean.valueOf(returnString);
			AbstractCall._logger.info("insert : deleted " + ok);
			return ok;
		}
		catch (final IOException e) {
			throw new ClearcheckbookException(
			        "Failed to delete " + this.getUrlSuffix() + " id: " + id.getValue(), e);
		}
	}

	/**
	 * Edits the.
	 *
	 * @param input
	 *            the input
	 * @return boolean - true means edit was successful
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected boolean edit(final T input) throws ClearcheckbookException {
		AbstractCall._logger.debug("edit: " + input);
		final AbstractDataType dataType = input;
		String returnString;
		try {
			returnString = this.getConnection().putPage(this.getUrlSuffix(),
			        dataType.getEditParameters());
			AbstractCall._logger.debug("returned: " + returnString);
			final boolean ok = Boolean.valueOf(returnString);
			AbstractCall._logger.info("edit : edited " + ok);
			return ok;
		}
		catch (final IOException e) {
			throw new ClearcheckbookException("Failed to create " + this.getUrlSuffix(), e);
		}
	}

	/**
	 * Gets the.
	 *
	 * @return {@link T extends AbstractDataType}
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected T get() throws ClearcheckbookException {
		try {
			final String jsonString = this.getConnection().getPage(this.getUrlSuffix());
			return this.getCore(jsonString);
		}
		catch (final IOException e) {
			throw new ClearcheckbookException("Failed to get " + this.getUrlSuffix(), e);
		}
	}

	/**
	 * Calls the "get" method from the API that brings back the item by id.
	 *
	 * @param id
	 *            the id
	 * @return {@link T extends AbstractDataType}
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected T get(final ParsedNameValuePair id) throws ClearcheckbookException {
		try {
			final String jsonString = this.getConnection().getPage(this.getUrlSuffix(), id);

			final T dataType = this.getCore(jsonString);
			if (null == dataType.getIdParameter().getValue()) {
				throw new ClearcheckbookException(
				        "Could not get " + this.getUrlSuffix() + " for id " + id.getValue());
			}
			return dataType;
		}
		catch (IOException | ClearcheckbookException e) {
			throw new ClearcheckbookException(
			        "Failed to get " + this.getUrlSuffix() + " id: " + id.getValue(), e);
		}
	}

	/**
	 * Calls the "get" method from the API that brings back all the values.
	 *
	 * @return the all
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected List getAll() throws ClearcheckbookException {
		return this.getAll((ParsedNameValuePair) null);
	}

	/**
	 * Calls the "get" method from the API that brings back all the values.
	 *
	 * @param parameters
	 *            the parameters
	 * @return the all
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected List getAll(final ParsedNameValuePair... parameters)
	        throws ClearcheckbookException {
		final List returnedList = new ArrayList<>();
		String jsonString = "FAILED";
		try {
			jsonString = this.getConnection().getPage(this.getPluralUrl(), parameters);
			AbstractCall._logger.debug("get: " + jsonString);

			// No values returned
			if (jsonString.equals("")) {
				return returnedList;
			}
			final ObjectMapper mapper = new ObjectMapper();

			// convert JSON string to Map
			final List> list = mapper.readValue(jsonString,
			        new TypeReference>>() {
			        });

			for (final HashMap map : list) {
				final T dataType = this.createDataTypeInstance(map, this.dataTypeClass);
				returnedList.add(dataType);
			}
			AbstractCall._logger
			        .debug("get: " + jsonString + " -> " + list + " -> " + returnedList);
		}
		catch (final JsonMappingException e) {
			AbstractCall._logger.warn("No values returned", e);
			return returnedList;
		}
		catch (final IOException e) {
			AbstractCall._logger.error("getAll : Failed to bring back values [" + jsonString + "]",
			        e);
			throw new ClearcheckbookException("getAll : Failed to bring back values", e);
		}
		return returnedList;
	}

	/**
	 * Gets the connection.
	 *
	 * @return the connection
	 */
	public ClearCheckBookConnection getConnection() {
		return this.connection;
	}

	/**
	 * Gets the core.
	 *
	 * @param jsonString
	 *            the json string
	 * @return {@link T extends AbstractDataType}
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 * @throws JsonParseException
	 *             the json parse exception
	 * @throws JsonMappingException
	 *             the json mapping exception
	 * @throws IOException
	 *             Signals that an I/O exception has occurred.
	 */
	private T getCore(final String jsonString)
	        throws ClearcheckbookException, JsonParseException, JsonMappingException, IOException {
		if (jsonString.equals("null") || jsonString.trim().equals("")) {
			throw new ClearcheckbookException("Failed to get " + this.getUrlSuffix());
		}
		AbstractCall._logger.debug("getCore: " + jsonString);
		final ObjectMapper mapper = new ObjectMapper();

		// convert JSON string to Map
		final HashMap map = mapper.readValue(jsonString,
		        new TypeReference>() {
		        });
		final T dataType = this.createDataTypeInstance(map, this.dataTypeClass);
		return dataType;
	}

	/**
	 * Gets the plural url.
	 *
	 * @return the plural url
	 */
	protected String getPluralUrl() {
		return this.getUrlSuffix() + "s";
	}

	/**
	 * Gets the url suffix.
	 *
	 * @return the url suffix
	 */
	abstract protected String getUrlSuffix();

	/**
	 * Insert.
	 *
	 * @param input
	 *            the input
	 * @return String if successful, returns the id, else throws exception
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected String insert(final T input) throws ClearcheckbookException {
		AbstractCall._logger.debug("insert: " + input);
		final AbstractDataType dataType = input;
		String returnString;
		try {
			returnString = this.getConnection().postPage(this.getUrlSuffix(),
			        dataType.getInsertParameters());

			final Long id = Long.valueOf(returnString);
			AbstractCall._logger.info("insert : created " + id);
			return id.toString();
		}
		catch (final NumberFormatException e) {
			throw new ClearcheckbookException("Failed to create " + this.getUrlSuffix(), e);
		}
		catch (final IOException e) {
			throw new ClearcheckbookException("Failed to create " + this.getUrlSuffix(), e);
		}
	}

	/**
	 * Process.
	 *
	 * @param dataType
	 *            the data type
	 * @return the string
	 * @throws ClearcheckbookException
	 *             the clearcheckbook exception
	 */
	protected String process(final T dataType) throws ClearcheckbookException {
		AbstractCall._logger.debug("process " + dataType);
		String id = dataType.getIdParameter().getValue();

		// Inserts
		if ("".equals(id) || (dataType.getId() == 0)) {
			AbstractCall._logger.info("insert: " + dataType);
			id = this.insert(dataType);
			return "Inserted " + id;
		}
		// deletes
		else if (dataType.getId() < 0) {
			AbstractCall._logger.info("delete: " + dataType);
			final boolean status = this
			        .delete(AbstractDataType.getIdParameter(-1 * dataType.getId()));
			if (status) {
				return "Deleted " + id;
			}
			else {
				return "Failed to delete " + id;
			}
		}
		else {
			AbstractCall._logger.info("edit: " + dataType);
			final boolean status = this.edit(dataType);
			if (status) {
				return "Edited " + id;
			}
			else {
				return "Failed to edit " + id;
			}
		}
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy