package com.flexmls.flexmls_api.services; import java.lang.reflect.ParameterizedType; import java.util.HashMap; import java.util.List; import java.util.Map; import com.flexmls.flexmls_api.ApiParameter; import com.flexmls.flexmls_api.Client; import com.flexmls.flexmls_api.FlexmlsApiClientException; import com.flexmls.flexmls_api.models.Base; /** * Base service class that abstracts the HTTP rest requests using some handy methods. * @param <T> Resource entity that this service end point provides. */ public abstract class BaseService<T extends Base> { protected static final Map<ApiParameter, String> EMPTY = new HashMap<ApiParameter, String>(); private Class<T> klass; private Client c = null; public BaseService(Client c) { super(); this.c = c; } public Client getClient() { return c; } public T get(String id) throws FlexmlsApiClientException { return get(id, EMPTY); } public T get(String id, Map<ApiParameter, String> options) throws FlexmlsApiClientException { return c.get(getPath(id), options).getResults(model()).get(0); } public List<T> find() throws FlexmlsApiClientException { return find(EMPTY); } public List<T> find(Map<ApiParameter, String> options) throws FlexmlsApiClientException { return c.get(getPath(), options).getResults(model()); } public abstract String getPath(); protected String getPath(String resourceId) { return new StringBuffer(getPath()).append("/").append(resourceId) .toString(); } /** * This is a kludgy workaround to get the generic class sent in for the resource. * It may not work in all instances, in which case the actual \<Model\>.class value * should be explicitly returned. * * It is not perfect, but it is WAY better than having to pass it in to all service * implementations. */ @SuppressWarnings("unchecked") protected Class<T> model() { if(klass != null){ return klass; } ParameterizedType superclass = (ParameterizedType) getClass() .getGenericSuperclass(); klass = (Class<T>) superclass.getActualTypeArguments()[0]; if(klass == null) { throw new IllegalArgumentException("Unable to determine the service model class, it will need to be explicitly passed."); } return klass; } }