Android Open Source - android-model-record Model Record






From Project

Back to project page android-model-record.

License

The source code is released under:

MIT License

If you think the Android project android-model-record listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.fanpics.opensource.android.modelrecord;
/*from  w w  w. ja v  a 2  s .c  o  m*/
import android.os.Handler;

import com.fanpics.opensource.android.modelrecord.callback.CreateCallback;
import com.fanpics.opensource.android.modelrecord.callback.DeleteCallback;
import com.fanpics.opensource.android.modelrecord.callback.LoadCallback;
import com.fanpics.opensource.android.modelrecord.callback.LoadListCallback;
import com.fanpics.opensource.android.modelrecord.callback.UpdateCallback;
import com.fanpics.opensource.android.modelrecord.configuration.BaseRecordConfiguration;
import com.fanpics.opensource.android.modelrecord.configuration.MultiRecordConfiguration;
import com.fanpics.opensource.android.modelrecord.configuration.SingleRecordConfiguration;
import com.fanpics.opensource.android.modelrecord.event.EventProcessor;
import com.fanpics.opensource.android.modelrecord.event.OttoProcessor;
import com.fanpics.opensource.android.modelrecord.event.SuccessEvent;
import com.squareup.otto.Bus;

import java.util.List;

public class ModelRecord<T> {
    protected EventProcessor eventProcessor;
    private HttpReport httpReport;
    protected Handler handler;

    /**
     *
     * @param bus Event bus to receive events
     */
    public ModelRecord(Bus bus) {
        this(bus, null);
    }

    /**
     *
     * @param bus Event bus to receive events
     * @param httpReport Class to receive metadata about http call failures and successes for
     *                   reporting purposes
     */
    public ModelRecord(Bus bus, HttpReport httpReport) {
        this(new OttoProcessor(bus), httpReport);
    }

    /**
     *
     * @param eventProcessor Event processor to receive events
     */
    public ModelRecord(EventProcessor eventProcessor) {
        this(eventProcessor, null);
    }

    /**
     *
     * @param eventProcessor Event processor to receive events
     * @param httpReport Class to receive metadata about http call failures and successes for
     *                   reporting purposes
     */
    public ModelRecord(EventProcessor eventProcessor, HttpReport httpReport) {
        this.eventProcessor = eventProcessor;
        this.httpReport = httpReport;
        this.handler = new Handler();
    }

    private void postOnMainThread(final Object event) {
        handler.post(new Runnable() {
            @Override
            public void run() {
                eventProcessor.process(event);
            }
        });
    }

    /**
     * Creates record in cache/on server
     *
     * @param model Object to be persisted
     */
    public void create(T model){
        SingleRecordConfiguration configuration = setupCreateConfiguration(new SingleRecordConfiguration<T>(), model);
        final CreateCallback createCallback = CreateCallback.createFromConfiguration(configuration, eventProcessor, httpReport);
        configuration.performAsynchronousNetworkCall(model, createCallback);
    }

    /**
     * Prepares configuration for object creation.
     *
     * This must be overridden if create is going to be used
     *
     * @param configuration Base configuration to build upon. It can be ignored and a new one created if needed.
     * @param model Object passed in from #create(model)
     * @return Configuration to set up and place request
     */
    protected SingleRecordConfiguration setupCreateConfiguration(SingleRecordConfiguration configuration, T model) {
        throw new RuntimeException("SetupCreateConfiguration() must be implemented before calling create");
    }

    /**
     * Updates record in cache/on server
     *
     * @param model Object to be updated
     */
    public void update(T model){
        SingleRecordConfiguration configuration = setupUpdateConfiguration(new SingleRecordConfiguration<T>(), model);
        final UpdateCallback updateCallback = UpdateCallback.createFromConfiguration(configuration, eventProcessor, httpReport);
        configuration.performAsynchronousNetworkCall(model, updateCallback);
    }

    /**
     * Prepares configuration for object update.
     *
     * This must be overridden if update is going to be used
     *
     * @param configuration Base configuration to build upon. It can be ignored and a new one created if needed.
     * @param model Object passed in from #update(Object)
     * @return Configuration to set up and place request
     */
    protected SingleRecordConfiguration setupUpdateConfiguration(SingleRecordConfiguration configuration, T model) {
        throw new RuntimeException("setupUpdateConfiguration() must be implemented before calling update");
    }

    /**
     * Deletes record in cache/on server
     *
     * @param model Object to be deleted
     */
    public void delete(T model){
        SingleRecordConfiguration configuration = setupDeleteConfiguration(new SingleRecordConfiguration(), model);
        final DeleteCallback deleteCallback = DeleteCallback.createFromConfiguration(configuration, eventProcessor, httpReport, model);
        configuration.performAsynchronousNetworkCall(model, deleteCallback);
    }

    /**
     * Prepares configuration for object deletion.
     *
     * This must be overridden if delete is going to be used
     *
     * @param configuration Base configuration to build upon. It can be ignored and a new one created if needed.
     * @param model Object passed in from #delete(Object)
     * @return Configuration to set up and place request
     */
    protected SingleRecordConfiguration setupDeleteConfiguration(SingleRecordConfiguration configuration, T model) {
        throw new RuntimeException("setupDeleteConfiguration() must be implemented before calling delete");
    }

    /**
     * Calls #Load(Object) without a key
     */
    public void load() {
        load(null);
    }

    /**
     * Eager loads object from cache if present, then continues to load it from the network
     *
     * @param key Key to be sent in load call
     */
    public void load(Object key) {
        loadAsynchronously(key, new SingleRecordConfiguration<T>(SingleRecordConfiguration.Type.LOAD));
    }

    /**
     * Calls #refresh(Object) without a key
     */
    public void refresh() {
        refresh(null);
    }

    /**
     * Skips cache and loads object from the network
     *
     * @param key Key to be sent in load call
     */
    public void refresh(Object key) {
        loadAsynchronously(key, new SingleRecordConfiguration<T>(SingleRecordConfiguration.Type.REFRESH));
    }

    /**
     * Calls #getPreLoaded(Object) without a key
     */
    public void getPreLoaded() {
        getPreLoaded(null);
    }

    /**
     * Loads object from cache
     *
     * @param key Key to be sent in load call
     */
    public void getPreLoaded(Object key) {
        loadAsynchronously(key, new SingleRecordConfiguration<T>(SingleRecordConfiguration.Type.CACHE_ONLY));
    }

    protected void loadAsynchronously(final Object key, final SingleRecordConfiguration baseConfiguration){
        new Thread(new Runnable() {
            @Override
            public void run() {
                baseConfiguration.setRunAsynchronously();
                load(key, baseConfiguration);
            }
        }).start();
    }

    /**
     * Calls #loadSynchronously(Object) without a key
     *
     * @return Loaded object
     */
    public Object loadSynchronously() {
        return loadSynchronously(null);
    }

    /**
     * Loads synchronously from cache, and falls back to network on cache miss
     *
     * @param key Key to be sent in load call
     * @return Loaded object
     */
    public Object loadSynchronously(Object key) {
        final SingleRecordConfiguration baseConfiguration = new SingleRecordConfiguration<T>(SingleRecordConfiguration.Type.LOAD);
        baseConfiguration.setRunSynchronously();
        return load(key, baseConfiguration);
    }

    /**
     * Calls @refreshSynchronously without a key
     *
     * @return Loaded object
     */
    public Object refreshSynchronously() {
        return refreshSynchronously(null);
    }

    /**
     * Loads object synchronously from network
     *
     * @param key Key to be sent in load call
     * @return Loaded object
     */
    public Object refreshSynchronously(Object key) {
        final SingleRecordConfiguration configuration = new SingleRecordConfiguration(SingleRecordConfiguration.Type.REFRESH);
        configuration.setRunSynchronously();
        return load(key, configuration);
    }

    protected Object load(Object key, SingleRecordConfiguration baseConfiguration) {
        SingleRecordConfiguration configuration = setupLoadConfiguration(baseConfiguration, key);

        if (configuration.shouldLoadFromCache()) {
            final Object loadedObject = loadFromCache(key, configuration);
            if (loadedObject != null && configuration.shouldRunSynchronously()) {
                return loadedObject;
            }
        }

        if (configuration.shouldLoadFromNetwork()) {
            return loadOnNetwork(key, configuration);
        }

        return null;
    }

    private Object loadFromCache(Object key, SingleRecordConfiguration configuration) {
        final RecordCache cache = configuration.getCache();
        final Object object = cache.load(key);
        if (configuration.shouldRunAsynchronously()) {
            postLoadedObject(object, configuration);
        }

        return object;
    }

    @SuppressWarnings("unchecked")
    private Object loadOnNetwork(Object key, SingleRecordConfiguration configuration) {
        final LoadCallback loadCallback = LoadCallback.createFromConfiguration(configuration, eventProcessor, httpReport, key, handler);
        if (configuration.shouldRunSynchronously()){
            final Result result = configuration.performSynchronousNetworkCall(key);
            if(!result.shouldCache()) {
                loadCallback.disableCaching();
            }

            loadCallback.synchronousSuccess(result.getModel(), result.getResponse());
            return result.getModel();
        } else {
            configuration.performAsynchronousNetworkCall(key, loadCallback);
            return null;
        }
    }

    /**
     * Prepares configuration for object loading.
     *
     * This must be overridden if any singular object load actions are going to be used
     *
     * @param configuration Base configuration to build upon. It can be ignored and a new one created if needed.
     * @param key Key passed in from load command
     * @return Configuration to set up and place request
     */
    protected SingleRecordConfiguration setupLoadConfiguration(SingleRecordConfiguration configuration, Object key) {
        throw new RuntimeException("setupLoadConfiguration() must be implemented before calling any load methods");
    }

    /**
     * Calls #loadList(Object) without a key
     */
    public void loadList() {
        loadList(null);
    }

    /**
     * Eager loads list from cache if present, then continues to load it from the network
     *
     * @param key Key to be sent in load call
     */
    public void loadList(Object key) {
        loadListAsynchronously(key, new MultiRecordConfiguration<T>(SingleRecordConfiguration.Type.LOAD));
    }

    /**
     * Calls #refreshList(Object) without a key
     */
    public void refreshList() {
        refreshList(null);
    }

    /**
     * Skips cache and loads list from the network
     *
     * @param key Key to be sent in load call
     */
    public void refreshList(Object key) {
        loadListAsynchronously(key, new MultiRecordConfiguration<T>(SingleRecordConfiguration.Type.REFRESH));
    }

    /**
     * Calls #getPreLoadedList(Object) without a key
     */
    public void getPreLoadedList() {
        getPreLoadedList(null);
    }

    /**
     * Loads list from cache
     *
     * @param key Key to be sent in load call
     */
    public void getPreLoadedList(Object key) {
        loadListAsynchronously(key, new MultiRecordConfiguration<T>(SingleRecordConfiguration.Type.CACHE_ONLY));
    }

    protected void loadListAsynchronously(final Object key, final MultiRecordConfiguration configuration){
        new Thread(new Runnable() {
            @Override
            public void run() {
                loadList(key, configuration);
            }
        }).start();
    }

    /**
     * Calls @loadListSynchronously without a key
     *
     * @return Loaded list
     */
    public List loadListSynchronously() {
        return loadListSynchronously(null);
    }

    /**
     * Loads list synchronously from cache, and falls back to network on cache miss
     *
     * @param key Key to be sent in load call
     * @return Loaded object
     */
    public List loadListSynchronously(Object key) {
        final MultiRecordConfiguration configuration = new MultiRecordConfiguration<T>(MultiRecordConfiguration.Type.LOAD);
        configuration.setRunSynchronously();
        return loadList(key, configuration);
    }

    /**
     * Calls @refreshListSynchronously without a key
     *
     * @return Loaded list
     */
    public List refreshListSynchronously() {
        return refreshListSynchronously(null);
    }

    /**
     * Loads list synchronously from network
     *
     * @param key Key to be sent in load call
     * @return Loaded object
     */
    public List refreshListSynchronously(Object key) {
        final MultiRecordConfiguration configuration = new MultiRecordConfiguration<T>(MultiRecordConfiguration.Type.REFRESH);
        configuration.setRunSynchronously();
        return loadList(key, configuration);
    }

    protected List loadList(Object key, MultiRecordConfiguration baseConfiguration) {
        MultiRecordConfiguration configuration = setupLoadListConfiguration(baseConfiguration, key);
        if(configuration.shouldLoadFromCache()) {
            final List loadedObject = loadListFromCache(key, configuration);
            if (loadedObject != null && configuration.shouldRunSynchronously()) {
                return loadedObject;
            }
        }

        if(configuration.shouldLoadFromNetwork()) {
            return loadListOnNetwork(key, configuration);
        }

        return null;
    }

    private List loadListFromCache(Object key, MultiRecordConfiguration configuration) {
        final RecordCache cache = configuration.getCache();
        final List object = cache.loadList(key);
        if (configuration.shouldRunAsynchronously()) {
            postLoadedObject(object, configuration);
        }

        return object;
    }

    @SuppressWarnings("unchecked")
    private List loadListOnNetwork(Object key, MultiRecordConfiguration configuration) {
        final LoadListCallback loadListCallback = LoadListCallback.createFromConfiguration(configuration, eventProcessor, httpReport, handler);
        if (configuration.shouldRunSynchronously()){
            final Result<List> result = configuration.performSynchronousNetworkCall(key);
            if(!result.shouldCache()) {
                loadListCallback.disableCaching();
            }

            loadListCallback.synchronousSuccess(result.getModel(), result.getResponse());
            return result.getModel();
        } else {
            configuration.performAsynchronousNetworkCall(key, loadListCallback);
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    private void postLoadedObject(Object object, BaseRecordConfiguration configuration) {
        if (object != null) {
            final SuccessEvent event = configuration.getSuccessEvent();
            event.setHasFinished(!configuration.shouldLoadFromNetwork());
            event.setResult(object);
            postOnMainThread(event);
        } else if (!configuration.shouldLoadFromNetwork()) {
            final Object event = configuration.getFailureEvent();
            postOnMainThread(event);
        }
    }

    /**
     * Prepares configuration for list loading.
     *
     * This must be overridden if any list load actions are going to be used
     *
     * @param configuration Base configuration to build upon. It can be ignored and a new one created if needed.
     * @param key Key passed in from load list command
     * @return Configuration to set up and place request
     */
    protected MultiRecordConfiguration setupLoadListConfiguration(MultiRecordConfiguration configuration, Object key) {
        throw new RuntimeException("setupLoadListConfiguration() must be implemented before calling any loadList methods");
    }
}




Java Source Code List

com.fanpics.opensource.android.modelrecord.HttpReport.java
com.fanpics.opensource.android.modelrecord.ModelRecordTest.java
com.fanpics.opensource.android.modelrecord.ModelRecord.java
com.fanpics.opensource.android.modelrecord.RecordCache.java
com.fanpics.opensource.android.modelrecord.ResponseParser.java
com.fanpics.opensource.android.modelrecord.Result.java
com.fanpics.opensource.android.modelrecord.callback.BaseRecordCallback.java
com.fanpics.opensource.android.modelrecord.callback.CreateCallback.java
com.fanpics.opensource.android.modelrecord.callback.DeleteCallbackTest.java
com.fanpics.opensource.android.modelrecord.callback.DeleteCallback.java
com.fanpics.opensource.android.modelrecord.callback.FailureCallback.java
com.fanpics.opensource.android.modelrecord.callback.LoadCallback.java
com.fanpics.opensource.android.modelrecord.callback.LoadListCallback.java
com.fanpics.opensource.android.modelrecord.callback.RecordCallbackTest.java
com.fanpics.opensource.android.modelrecord.callback.RecordCallback.java
com.fanpics.opensource.android.modelrecord.callback.SuccessCallback.java
com.fanpics.opensource.android.modelrecord.callback.UpdateCallback.java
com.fanpics.opensource.android.modelrecord.configuration.BaseRecordConfigurationTest.java
com.fanpics.opensource.android.modelrecord.configuration.BaseRecordConfiguration.java
com.fanpics.opensource.android.modelrecord.configuration.MultiRecordConfigurationTest.java
com.fanpics.opensource.android.modelrecord.configuration.MultiRecordConfiguration.java
com.fanpics.opensource.android.modelrecord.configuration.SingleRecordConfigurationTest.java
com.fanpics.opensource.android.modelrecord.configuration.SingleRecordConfiguration.java
com.fanpics.opensource.android.modelrecord.event.EventProcessor.java
com.fanpics.opensource.android.modelrecord.event.FailureEvent.java
com.fanpics.opensource.android.modelrecord.event.OttoProcessorTest.java
com.fanpics.opensource.android.modelrecord.event.OttoProcessor.java
com.fanpics.opensource.android.modelrecord.event.SuccessEventTest.java
com.fanpics.opensource.android.modelrecord.event.SuccessEvent.java
com.fanpics.opensource.android.modelrecord.sample.data.cache.ImgurDataCache.java
com.fanpics.opensource.android.modelrecord.sample.data.model.ImgurData.java
com.fanpics.opensource.android.modelrecord.sample.data.model.ImgurItem.java
com.fanpics.opensource.android.modelrecord.sample.data.model.record.ImgurDataRecord.java
com.fanpics.opensource.android.modelrecord.sample.data.network.ImgurItemService.java
com.fanpics.opensource.android.modelrecord.sample.event.ImgurDataLoadFailedEvent.java
com.fanpics.opensource.android.modelrecord.sample.event.ImgurDataLoadSucceededEvent.java
com.fanpics.opensource.android.modelrecord.sample.ui.activity.MainActivity.java
com.fanpics.opensource.android.modelrecord.sample.ui.adapter.ImgurAdapter.java