package by.istin.android.xcore; import android.app.Activity; import android.content.Context; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import by.istin.android.xcore.callable.ISuccess; import by.istin.android.xcore.model.CursorModel; import by.istin.android.xcore.provider.ModelContract; import by.istin.android.xcore.service.DataSourceService; import by.istin.android.xcore.service.StatusResultReceiver; import by.istin.android.xcore.source.DataSourceRequest; import by.istin.android.xcore.utils.AppUtils; import by.istin.android.xcore.utils.CursorUtils; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by IstiN on 14.8.13. */ public class Core implements XCoreHelper.IAppServiceKey { public static final String APP_SERVICE_KEY = "xcore:common:core"; public static abstract class SimpleDataSourceServiceListener { public void onStart(Bundle resultData) { } public abstract void onDone(Bundle resultData); public void onError(Exception exception) { } public void onCached(Bundle resultData) { } } public static interface IExecuteOperation<Result> { DataSourceRequest getDataSourceRequest(); String getProcessorKey(); String getDataSourceKey(); Uri getResultQueryUri(); String[] getSelectionArgs(); Activity getActivity(); ISuccess<Result> getSuccess(); CursorModel.CursorModelCreator getCursorModelCreator(); SimpleDataSourceServiceListener getDataSourceListener(); } public static class ExecuteOperationBuilder<Result> { private DataSourceRequest mDataSourceRequest; private String mProcessorKey; private String mDataSourceKey; private Uri mResultQueryUri; private Activity mActivity; private ISuccess<Result> mSuccess; private String[] mSelectionArgs; private CursorModel.CursorModelCreator mCursorModelCreator; private Core.SimpleDataSourceServiceListener mDataSourceServiceListener; public ExecuteOperationBuilder setDataSourceRequest(DataSourceRequest pDataSourceRequest) { this.mDataSourceRequest = pDataSourceRequest; return this; } public ExecuteOperationBuilder setProcessorKey(String pProcessorKey) { this.mProcessorKey = pProcessorKey; return this; } public ExecuteOperationBuilder setDataSourceKey(String pDataSourceKey) { this.mDataSourceKey = pDataSourceKey; return this; } public ExecuteOperationBuilder setResultQueryUri(Uri pResultQueryUri) { this.mResultQueryUri = pResultQueryUri; return this; } public ExecuteOperationBuilder setActivity(Activity pActivity) { this.mActivity = pActivity; return this; } public ExecuteOperationBuilder setSuccess(ISuccess<Result> pSuccess) { this.mSuccess = pSuccess; return this; } public ExecuteOperationBuilder setSelectionArgs(String[] selectionArgs) { this.mSelectionArgs = selectionArgs; return this; } public IExecuteOperation<Result> build() { return new IExecuteOperation<Result>() { @Override public DataSourceRequest getDataSourceRequest() { return mDataSourceRequest; } @Override public String getProcessorKey() { return mProcessorKey; } @Override public String getDataSourceKey() { return mDataSourceKey; } @Override public Uri getResultQueryUri() { return mResultQueryUri; } @Override public String[] getSelectionArgs() { return mSelectionArgs; } @Override public Activity getActivity() { return mActivity; } @Override public ISuccess<Result> getSuccess() { return mSuccess; } @Override public CursorModel.CursorModelCreator getCursorModelCreator() { return mCursorModelCreator; } @Override public SimpleDataSourceServiceListener getDataSourceListener() { return mDataSourceServiceListener; } }; } public ExecuteOperationBuilder setResultSqlQuery(String resultSqlQuery) { setResultQueryUri(ModelContract.getSQLQueryUri(resultSqlQuery, null)); return this; } public ExecuteOperationBuilder setResultSqlQuery(String resultSqlQuery, String[] args) { setResultSqlQuery(resultSqlQuery); setSelectionArgs(args); return this; } public ExecuteOperationBuilder setCursorModelCreator(CursorModel.CursorModelCreator cursorModelCreator) { this.mCursorModelCreator = cursorModelCreator; return this; } public ExecuteOperationBuilder setDataSourceServiceListener(SimpleDataSourceServiceListener dataSourceServiceListener) { this.mDataSourceServiceListener = dataSourceServiceListener; return this; } } private final Context mContext; private final ExecutorService mExecutor = Executors.newFixedThreadPool(3); private final Handler mHandler = new Handler(Looper.getMainLooper()); public Core(Context context) { mContext = context; } public static Core get(Context context) { return (Core) AppUtils.get(context, APP_SERVICE_KEY); } public void executeSync(final IExecuteOperation<?> executeOperation) throws Exception { final SimpleDataSourceServiceListener dataSourceListener = executeOperation.getDataSourceListener(); Bundle bundle = new Bundle(); sendOnStartEvent(bundle, dataSourceListener); DataSourceRequest dataSourceRequest = executeOperation.getDataSourceRequest(); try { Object result = DataSourceService.execute(ContextHolder.get(), dataSourceRequest.isCacheable(), executeOperation.getProcessorKey(), executeOperation.getDataSourceKey(), dataSourceRequest, bundle); if (dataSourceListener != null) { dataSourceListener.onDone(bundle); } sendResult(bundle, result, executeOperation, false); } catch (Exception e) { sendOnErrorEvent(e, dataSourceListener); throw e; } } public void execute(final IExecuteOperation<?> executeOperation) { String processorKey = executeOperation.getProcessorKey(); final DataSourceRequest dataSourceRequest = executeOperation.getDataSourceRequest(); final SimpleDataSourceServiceListener dataSourceListener = executeOperation.getDataSourceListener(); DataSourceService.execute(mContext, dataSourceRequest, processorKey, executeOperation.getDataSourceKey(), new StatusResultReceiver(mHandler) { @Override public void onStart(Bundle resultData) { sendOnStartEvent(resultData, dataSourceListener); } @Override public void onDone(final Bundle resultData) { final Uri uri = executeOperation.getResultQueryUri(); if (uri == null) { if (dataSourceListener != null) { dataSourceListener.onDone(resultData); } sendResult(resultData, resultData.get(StatusResultReceiver.RESULT_KEY), executeOperation, true); return; } mExecutor.execute(new Runnable() { @Override public void run() { final Cursor cursor = mContext.getContentResolver().query(uri, null, null, executeOperation.getSelectionArgs(), null); if (cursor != null) { cursor.getCount(); } if (!sendResult(resultData, cursor, executeOperation, true)) { CursorUtils.close(cursor); } } }); } @Override protected void onCached(Bundle resultData) { super.onCached(resultData); if (dataSourceListener != null) { dataSourceListener.onCached(resultData); } onDone(resultData); } @Override public void onError(Exception exception) { sendOnErrorEvent(exception, dataSourceListener); } }); } private void sendOnErrorEvent(Exception exception, SimpleDataSourceServiceListener dataSourceListener) { exception.printStackTrace(); if (dataSourceListener != null) { dataSourceListener.onError(exception); } } private void sendOnStartEvent(Bundle resultData, SimpleDataSourceServiceListener dataSourceListener) { if (dataSourceListener != null) { dataSourceListener.onStart(resultData); } } private boolean sendResult(final Bundle resultData, final Object result, final IExecuteOperation<?> executeOperation, boolean inHandler) { final ISuccess success = executeOperation.getSuccess(); if (success != null) { Runnable runnable = new Runnable() { @Override public void run() { Core.this.sendResult(executeOperation, result, success, resultData); } }; if (inHandler) { mHandler.post(runnable); } else { Core.this.sendResult(executeOperation, result, success, resultData); } return true; } else { return false; } } private void sendResult(IExecuteOperation<?> executeOperation, Object result, ISuccess success, Bundle resultData) { CursorModel.CursorModelCreator cursorModelCreator = executeOperation.getCursorModelCreator(); if (cursorModelCreator != null && result instanceof Cursor) { success.success(cursorModelCreator.create((Cursor) result)); } else { success.success(result); } SimpleDataSourceServiceListener dataSourceListener = executeOperation.getDataSourceListener(); if (dataSourceListener != null) { dataSourceListener.onDone(resultData); } } @Override public String getAppServiceKey() { return APP_SERVICE_KEY; } }