// Path: framework/src/main/java/com/kifile/android/cornerstone/core/ConvertException.java
// public class ConvertException extends Exception {
// 
//     private Object o;
// 
//     public ConvertException() {
//     }
// 
//     public ConvertException(String detailMessage) {
//         super(detailMessage);
//     }
// 
//     public ConvertException(String detailMessage, Throwable throwable) {
//         super(detailMessage, throwable);
//     }
// 
//     public ConvertException(Throwable throwable) {
//         super(throwable);
//     }
// 
//     public void setError(Object error) {
//         o = error;
//     }
// 
//     public Object getError() {
//         return o;
//     }
// }
// 
// Path: framework/src/main/java/com/kifile/android/cornerstone/core/DataFetcher.java
// public interface DataFetcher<DATA> {
// 
//     /**
//      * Fetch data.
//      *
//      * @return If fetch successful, return the data.
//      * @throws FetchException   Throw FetchException when you cannot fetch a data.
//      * @throws ConvertException Throw ConvertException when you cannot convert the data to another type.
//      */
//     DATA fetch() throws FetchException, ConvertException;
// }
// 
// Path: framework/src/main/java/com/kifile/android/cornerstone/core/DataObserver.java
// public interface DataObserver<DATA> {
// 
//     /**
//      * Watch if the data of {@link DataProvider} is changed.
//      *
//      * @param data
//      */
//     void onDataChanged(DATA data);
// }
// 
// Path: framework/src/main/java/com/kifile/android/cornerstone/core/DataProvider.java
// public interface DataProvider<DATA> {
// 
//     void setFetcher(DataFetcher<DATA> fetcher);
// 
//     /**
//      * Add the observer into watch list, when data changed, notify it.
//      *
//      * @param observer
//      */
//     void registerDataObserver(DataObserver<DATA> observer);
// 
//     /**
//      * Remove observer from watch list.
//      *
//      * @param observer
//      */
//     void unregisterDataObserver(DataObserver<DATA> observer);
// 
//     /**
//      * Refresh data.
//      */
//     void refresh();
// 
//     /**
//      * Notify observers data changed.
//      */
//     void notifyDataChanged();
// 
//     DATA getData();
// 
//     /**
//      * @return If the data need update, return true.
//      */
//     boolean isDataNeedUpdate();
// 
//     /**
//      * Release the resources when destroy. If the worker thread is working, stop it.
//      */
//     void release();
// }


import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import com.kifile.android.cornerstone.core.ConvertException;
import com.kifile.android.cornerstone.core.DataFetcher;
import com.kifile.android.cornerstone.core.DataObserver;
import com.kifile.android.cornerstone.core.DataProvider;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
package com.kifile.android.cornerstone.impl.providers;




/**
 * The implement of {@link DataProvider}.
 *
 * @author kifile
 */
public abstract class AbstractDataProvider<DATA> implements DataProvider<DATA> {

    private static Executor EXECUTOR;

    private final List<DataObserver<DATA>> mObservers = new CopyOnWriteArrayList<>();

    private DATA mData;

    protected DataFetcher<DATA> mFetcher;

    protected boolean mIsAsync;

    // 由于数据加载需要通过异步线程调用，因此在此处创建一个静态的Handler，专门负责主线程通信。
    protected static Handler sHandler = new Handler();

    /**
     * When you extends AbstractDataProvider, don't make the constructor having any argument.
     * <p/>
     * Unless you want to control the provider by yourself like {@link CombinedDataProvider}
     * <p/>
     * This constructor will be called by {@link com.kifile.android.cornerstone.core.AbstractDataProviderManager}.
     */
    public AbstractDataProvider() {

    }

    public static void setDefaultExecutor(@NonNull Executor executor) {
        EXECUTOR = executor;
    }

    /**
     * Set if the fetch task run on a non-main thread.
     *
     * @param async
     */
    public void setAsync(boolean async) {
        mIsAsync = async;
    }

    @Override
    public void setFetcher(DataFetcher<DATA> fetcher) {
        mFetcher = fetcher;
    }

    @Override
// Path: framework/src/main/java/com/kifile/android/cornerstone/core/ConvertException.java
// public class ConvertException extends Exception {
// 
//     private Object o;
// 
//     public ConvertException() {
//     }
// 
//     public ConvertException(String detailMessage) {
//         super(detailMessage);
//     }
// 
//     public ConvertException(String detailMessage, Throwable throwable) {
//         super(detailMessage, throwable);
//     }
// 
//     public ConvertException(Throwable throwable) {
//         super(throwable);
//     }
// 
//     public void setError(Object error) {
//         o = error;
//     }
// 
//     public Object getError() {
//         return o;
//     }
// }
// 
// Path: framework/src/main/java/com/kifile/android/cornerstone/core/DataFetcher.java
// public interface DataFetcher<DATA> {
// 
//     /**
//      * Fetch data.
//      *
//      * @return If fetch successful, return the data.
//      * @throws FetchException   Throw FetchException when you cannot fetch a data.
//      * @throws ConvertException Throw ConvertException when you cannot convert the data to another type.
//      */
//     DATA fetch() throws FetchException, ConvertException;
// }
// 
// Path: framework/src/main/java/com/kifile/android/cornerstone/core/DataObserver.java
// public interface DataObserver<DATA> {
// 
//     /**
//      * Watch if the data of {@link DataProvider} is changed.
//      *
//      * @param data
//      */
//     void onDataChanged(DATA data);
// }
// 
// Path: framework/src/main/java/com/kifile/android/cornerstone/core/DataProvider.java
// public interface DataProvider<DATA> {
// 
//     void setFetcher(DataFetcher<DATA> fetcher);
// 
//     /**
//      * Add the observer into watch list, when data changed, notify it.
//      *
//      * @param observer
//      */
//     void registerDataObserver(DataObserver<DATA> observer);
// 
//     /**
//      * Remove observer from watch list.
//      *
//      * @param observer
//      */
//     void unregisterDataObserver(DataObserver<DATA> observer);
// 
//     /**
//      * Refresh data.
//      */
//     void refresh();
// 
//     /**
//      * Notify observers data changed.
//      */
//     void notifyDataChanged();
// 
//     DATA getData();
// 
//     /**
//      * @return If the data need update, return true.
//      */
//     boolean isDataNeedUpdate();
// 
//     /**
//      * Release the resources when destroy. If the worker thread is working, stop it.
//      */
//     void release();
// }


// Path: framework/src/main/java/com/kifile/android/cornerstone/impl/providers/AbstractDataProvider.java
import android.os.Handler;
import android.os.Looper;
import android.support.annotation.NonNull;
import com.kifile.android.cornerstone.core.ConvertException;
import com.kifile.android.cornerstone.core.DataFetcher;
import com.kifile.android.cornerstone.core.DataObserver;
import com.kifile.android.cornerstone.core.DataProvider;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

package com.kifile.android.cornerstone.impl.providers;




/**
 * The implement of {@link DataProvider}.
 *
 * @author kifile
 */
public abstract class AbstractDataProvider<DATA> implements DataProvider<DATA> {

    private static Executor EXECUTOR;

    private final List<DataObserver<DATA>> mObservers = new CopyOnWriteArrayList<>();

    private DATA mData;

    protected DataFetcher<DATA> mFetcher;

    protected boolean mIsAsync;

    // 由于数据加载需要通过异步线程调用，因此在此处创建一个静态的Handler，专门负责主线程通信。
    protected static Handler sHandler = new Handler();

    /**
     * When you extends AbstractDataProvider, don't make the constructor having any argument.
     * <p/>
     * Unless you want to control the provider by yourself like {@link CombinedDataProvider}
     * <p/>
     * This constructor will be called by {@link com.kifile.android.cornerstone.core.AbstractDataProviderManager}.
     */
    public AbstractDataProvider() {

    }

    public static void setDefaultExecutor(@NonNull Executor executor) {
        EXECUTOR = executor;
    }

    /**
     * Set if the fetch task run on a non-main thread.
     *
     * @param async
     */
    public void setAsync(boolean async) {
        mIsAsync = async;
    }

    @Override
    public void setFetcher(DataFetcher<DATA> fetcher) {
        mFetcher = fetcher;
    }

    @Override
    public void registerDataObserver(final DataObserver<DATA> observer) {