package com.ecollege.android.tasks;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import roboguice.util.Ln;
import android.content.Context;
import android.content.DialogInterface;
import com.ecollege.android.R;
import com.ecollege.android.activities.ECollegeActivity;
import com.ecollege.android.errors.ECollegePromptRetryException;
import com.ecollege.android.util.CacheConfiguration;
import com.ecollege.api.exceptions.TimeoutException;
import com.ecollege.api.services.BaseService;
public class ServiceCallTask<ServiceT extends BaseService> extends ECollegeAsyncTask<ServiceT> {
private static boolean VOLATILE_CACHE_ENABLED = false;
protected ServiceT service;
protected boolean useFileCache = true;
protected boolean cacheExecutedResult = true;
protected boolean useResultCache = true;
protected boolean cacheInFileCache = true;
protected TaskPostProcessor<ServiceT> postProcessor;
public ServiceCallTask(ECollegeActivity activity, ServiceT service) {
super(activity);
this.service=service;
}
public ServiceCallTask<ServiceT> bypassFileCache() {
useFileCache = false;
return this;
}
public ServiceCallTask<ServiceT> doNotResultCache() {
cacheExecutedResult = false;
return this;
}
public ServiceCallTask<ServiceT> bypassResultCache() {
useResultCache = false;
return this;
}
public ServiceCallTask<ServiceT> doNotFileCache() {
cacheInFileCache = false;
return this;
}
public ServiceCallTask<ServiceT> configureCaching(CacheConfiguration config) {
assert(config != null);
cacheInFileCache = config.cacheResultInFileCache;
useFileCache = !config.bypassFileCache;
cacheExecutedResult = config.cacheResultInResultCache;
useResultCache = !config.bypassResultCache;
return this;
}
public ServiceCallTask<ServiceT> setPostProcessor(TaskPostProcessor<ServiceT> postProcessor) {
this.postProcessor = postProcessor;
return this;
}
public ServiceT call() throws Exception {
if (useResultCache && VOLATILE_CACHE_ENABLED) {
ServiceT executedService = getServiceFromResultCache(service);
// We found an identical service that was already executed and cached,
// so just return that one
if (executedService != null) {
Ln.i(String.format("Returning cached result: %s for %s instead of performing service call", executedService.toString(), service.toString()));
service = executedService;
return executedService;
}
} else {
Ln.i(String.format("Bypassing result cache for %s", service));
}
app.getClient().executeService(service, app.getServiceCache(), useFileCache, cacheInFileCache);
if (postProcessor != null) {
service = postProcessor.onPostProcess(service);
}
if (cacheExecutedResult && service.isCacheable() && VOLATILE_CACHE_ENABLED) {
app.putObjectInVolatileCache(
service.getCacheKey(app.getSessionIdentifier()),
service);
}
return service;
}
@SuppressWarnings("unchecked")
protected ServiceT getServiceFromResultCache(ServiceT newService) {
ServiceT completedService = app.getObjectOfTypeFromVolatileCache(
newService.getCacheKey(app.getSessionIdentifier()),
(Class<ServiceT>)newService.getClass());
return completedService;
}
@Override
protected void onException(Exception sourceException) throws RuntimeException {
boolean errorHandled = false;
String resultExceptionMethod = "onServiceCallException";
ECollegeActivity currentActivity = getCurrentActivity();
try {
if (currentActivity != null) {
Method exceptionHandler = currentActivity.getClass().getMethod(resultExceptionMethod, service.getClass(), Exception.class);
errorHandled = (Boolean)exceptionHandler.invoke(currentActivity,service,sourceException);
} else {
Ln.e("ERROR! No current activity to attach exception to!");
}
} catch (SecurityException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
Ln.i("onException","No exception handler found in " + service.getClass().getSimpleName());
//no success handler found
} catch (IllegalArgumentException e) {
//problem calling method with arg
app.reportError(e);
} catch (IllegalAccessException e) {
//problem calling method with permissions
app.reportError(e);
} catch (InvocationTargetException e) {
app.reportError(e.getTargetException());
}
if (!errorHandled) {
if (sourceException instanceof TimeoutException) {
DialogInterface.OnClickListener retryHandler = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
ServiceCallTask.this.execute();
}
};
if (currentActivity != null) {
ECollegePromptRetryException retryE = new ECollegePromptRetryException((Context)currentActivity, retryHandler, R.string.e_network_timeout);
app.reportError(retryE);
}
} else {
super.onException(sourceException);
}
}
}
@Override
protected void onSuccess(ServiceT t) throws Exception {
// TODO Auto-generated method stub
super.onSuccess(t);
ECollegeActivity currentActivity = getCurrentActivity();
String resultSuccessMethod = "onServiceCallSuccess";
try {
if (currentActivity != null) {
Method successHandler = currentActivity.getClass().getMethod(resultSuccessMethod, service.getClass());
successHandler.invoke(currentActivity,t);
} else {
Ln.e("ERROR! No current activity to attach success to!");
}
} catch (NoSuchMethodException e) {
//no success handler found
} catch (SecurityException e) {
app.reportError(e);
} catch (IllegalArgumentException e) {
//problem calling method with arg
app.reportError(e);
} catch (IllegalAccessException e) {
//problem calling method with permissions
app.reportError(e);
} catch (InvocationTargetException e) {
app.reportError(e.getTargetException());
}
}
// public ServiceCallTask(Context context) {
// super(context);
// // TODO Auto-generated constructor stub
// }
//
// private ECollegeActivity getActivity(Context context) {
// return (ECollegeActivity) context;
// }
//
// @Override
// protected void handleError(Context context, Exception error) {
//// getActivity(context).hasRunningTask(false);
//// getActivity(context).reportError((RBException) error);
// }
//
// @Override
// protected ServiceT doCheckedInBackground(Context context,
// ServiceT... params) throws Exception {
// // TODO Auto-generated method stub
//
//
// ServiceT service = (ServiceT)params[0];
// ECollegeClient client = getActivity(context).getApp().getClient();
// client.executeService(service);
// return service;
// }
//
// @Override
// protected void after(Context context, ServiceT result) {
// // Show a progress indicator text in the application title bar
//
// String resultClassName = result.getClass().getSimpleName();
// String resultSuccessMethod = "on" + resultClassName + "Success";
//
// try {
// Method successHandler = context.getClass().getMethod(resultSuccessMethod, result.getClass());
// successHandler.invoke(context,result);
// } catch (SecurityException e) {
// e.printStackTrace();
// } catch (NoSuchMethodException e) {
// //no success handler found
// } catch (IllegalArgumentException e) {
// //problem calling method with arg
// e.printStackTrace();
// } catch (IllegalAccessException e) {
// //problem calling method with permissions
// e.printStackTrace();
// } catch (InvocationTargetException e) {
// e.printStackTrace();
// }
//
//
//// getActivity(context).setTitle(context.getText(R.string.app_name).toString());
//// getActivity(context).hasRunningTask(false);
//// afterTask(getActivity(context), result);
// }
}