package com.finchframework.finch.rest; import android.content.ContentProvider; import android.content.ContentValues; import android.database.sqlite.SQLiteDatabase; import android.net.Uri; import android.util.Log; import com.finchframework.finch.Finch; import org.apache.http.client.methods.HttpGet; import java.io.UnsupportedEncodingException; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; /** * Encapsulates functions for asynchronous RESTful requests so that subclass * content providers can use them for initiating request while still using * custom methods for interpreting REST based content such as, RSS, ATOM, * JSON, etc. */ public abstract class RESTfulContentProvider extends ContentProvider { protected FileHandlerFactory mFileHandlerFactory; private Map<String, UriRequestTask> mRequestsInProgress = new HashMap<String, UriRequestTask>(); public RESTfulContentProvider() { } public void setFileHandlerFactory(FileHandlerFactory fileHandlerFactory) { mFileHandlerFactory = fileHandlerFactory; } public abstract Uri insert(Uri uri, ContentValues cv, SQLiteDatabase db); private UriRequestTask getRequestTask(String queryText) { return mRequestsInProgress.get(queryText); } /** * Allows the subclass to define the database used by a response handler. * * @return database passed to response handler. */ public abstract SQLiteDatabase getDatabase(); public void requestComplete(String mQueryText) { synchronized (mRequestsInProgress) { mRequestsInProgress.remove(mQueryText); } } /** * Abstract method that allows a subclass to define the type of handler * that should be used to parse the response of a given request. * * @param requestTag unique tag identifying this request. * @return The response handler created by a subclass used to parse the * request response. */ protected abstract ResponseHandler newResponseHandler(String requestTag); UriRequestTask newQueryTask(String requestTag, String url) { UriRequestTask requestTask; final HttpGet get = new HttpGet(url); ResponseHandler handler = newResponseHandler(requestTag); requestTask = new UriRequestTask(requestTag, this, get, handler, getContext()); mRequestsInProgress.put(requestTag, requestTask); return requestTask; } /** * Creates a new worker thread to carry out a RESTful network invocation. * * @param queryTag unique tag that identifies this request. * @param queryUri the complete URI that should be access by this request. */ public void asyncQueryRequest(String queryTag, String queryUri) { synchronized (mRequestsInProgress) { UriRequestTask requestTask = getRequestTask(queryTag); if (requestTask == null) { requestTask = newQueryTask(queryTag, queryUri); Thread t = new Thread(requestTask); // allows other requests to run in parallel. t.start(); } } } /** * Spawns a thread to download bytes from a url and store them in a file, * such as for storing a thumbnail. * * @param id the database id used to reference the downloaded url. */ public void cacheUri2File(String id, String url) { // use media id as a unique request tag final HttpGet get = new HttpGet(url); UriRequestTask requestTask = new UriRequestTask( get, mFileHandlerFactory.newFileHandler(id), getContext()); Thread t = new Thread(requestTask); t.start(); } public void deleteFile(String id) { mFileHandlerFactory.delete(id); } public String getCacheName(String id) { return mFileHandlerFactory.getFileName(id); } public static String encode(String gDataQuery) { try { return URLEncoder.encode(gDataQuery, "UTF-8"); } catch (UnsupportedEncodingException e) { Log.d(Finch.LOG_TAG, "could not decode UTF-8," + " this should not happen"); } return null; } }