package org.jactr.core.module.asynch.delegate; /* * default logging */ import java.util.concurrent.Callable; import java.util.concurrent.Future; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.module.AbstractModule; import org.jactr.core.module.asynch.IAsynchronousModule; import org.jactr.core.production.condition.ChunkPattern; import org.jactr.core.production.request.IRequest; import org.jactr.core.queue.timedevents.BlockingTimedEvent; /** * abstract asynch delegate. This will manage the {@link BlockingTimedEvent} * such that the synchronization will occurr minimumProcessingTime after the * start of the request. * * @author harrison * @param <M> * @param <R> */ public abstract class BasicAsynchronousModuleDelegate<M extends IAsynchronousModule, R> implements IAsynchronousModuleDelegate<M, R> { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(BasicAsynchronousModuleDelegate.class); private M _module; private R _errorResult; public BasicAsynchronousModuleDelegate(M module, R cantProcessResult) { _module = module; _errorResult = cantProcessResult; } public M getModule() { return _module; } public Future<R> process(final IRequest request, final double requestTime, final Object... parameters) { boolean canProcess = shouldProcess(request, parameters); if (canProcess) { Future<R> rtn = AbstractModule.delayedFuture(new Callable<R>() { public R call() throws Exception { R result = _errorResult; try { result = processInternal(request, requestTime, parameters); } catch (Exception e) { /** * Error : error */ LOGGER.error("Failed to process pattern request ", e); } processInternalCompleted(request, result, parameters); return result; } }, getModule().getExecutor()); return rtn; } else { /* * nothing can be done, return right now */ processInternalCompleted(request, _errorResult, parameters); return AbstractModule.immediateReturn(_errorResult); } } /** * called on the asynch thread after processInternal has completed. primarily * used to output some logging info.. * * @param request * @param result * @param startTime * @param harvestAt */ protected void processInternalCompleted(IRequest request, R result, Object...parameters) { } /** * Called on the initiating thread (i.e. model thread), this checks the module * and the buffers to be sure that the processing can proceed. If true, it * will queue {@link #processInternal(ChunkPattern)} on the asynchronous * executor. * * @param request * @return */ abstract protected boolean shouldProcess(IRequest request, Object... parameters); /** * called on the asynchronous thread, this does the actual processing, * returning some result. This method should handle all its own exceptions. * * @param request * @return */ abstract protected R processInternal(IRequest request, double requestTime, Object... parameters); }