package org.marketcetera.module; import org.marketcetera.util.misc.ClassVersion; import java.util.List; import java.util.LinkedList; /* $License$ */ /** * A processor module that is capable of creating / canceling data flows. * * @author anshul@marketcetera.com */ @ClassVersion("$Id: FlowRequesterModule.java 16154 2012-07-14 16:34:05Z colin $") public class FlowRequesterModule extends ProcessorModule implements DataFlowRequester { public FlowRequesterModule(ModuleURN inModuleURN) { super(inModuleURN, false); } @Override protected void preStart() throws ModuleException { super.preStart(); createFlow(); if(mFailPreStart) { throw new ModuleException( TestMessages.TEST_START_STOP_FAILURE); } } @Override public void preStop() throws ModuleException { super.preStop(); if (!mSkipCancel) { cancelFlow(); } } @Override public void setFlowSupport(DataFlowSupport support) { mSupport = support; } /** * Overridden to test failures when invoking {@link DataFlowSupport} * APIs from within this method. */ @Override public void requestData(DataRequest inRequest, DataEmitterSupport inSupport) throws RequestDataException { try { if (mNestDataFlowInRequest) { doNestedRequestOrCancel(); } } catch (ModuleException e) { throw new RequestDataException(e); } super.requestData(inRequest, inSupport); } /** * Overridden to test failures when invoking {@link DataFlowSupport} * APIs from within this method. */ @Override public void cancel(DataFlowID inFlowID, RequestID inRequestID) { super.cancel(inFlowID, inRequestID); if(mNestDataFlowInCancel) { try { doNestedRequestOrCancel(); } catch (ModuleException e) { mNestedCancelFailure = e; } } } /** * If the API to create that appends sink by default should be invoked. * * @param inInvokeDefault if the createDataFlow() API that appends * the sink module by default should be invoked */ public void setInvokeDefault(boolean inInvokeDefault) { mInvokeDefault = inInvokeDefault; } /** * The value of the appendSink flag when invoking the API that * doesn't append the sink module by default. * * @param inAppendSink the appendSink flag. */ public void setAppendSink(boolean inAppendSink) { mAppendSink = inAppendSink; } /** * The data requests that should be used by this module when * creating data flows. * * @param inRequests the set of requests to use when creating * data flows. */ public void setRequests(DataRequest[] inRequests) { mRequests = inRequests; } /** * The data request that should be used by this module when * creating data flows. * * @param inRequests the set of request used to use when creating * data flow. */ public void addRequests(DataRequest[] inRequests) { mDataRequests.add(inRequests); } /** * The data flow ID. * * @param inFlowID the data flowID. */ public void setFlowID(DataFlowID inFlowID) { mFlowID = inFlowID; } /** * The data flow ID for the request supplied via * {@link #setRequests(DataRequest[])}. * * @return the data flow ID. */ public DataFlowID getFlowID() { return mFlowID; } /** * The data flow IDs corresponding to the requests added via * {@link #addRequests(DataRequest[])}. * * @return the flow IDs for the data requests created. */ public DataFlowID[] getFlowIDs() { return mFlowIDs.toArray(new DataFlowID[mFlowIDs.size()]); } /** * If the module should skip canceling the data flow when its stopped. * * @return if the module should skip canceling the data flow when * its stopped. */ public boolean isSkipCancel() { return mSkipCancel; } /** * If the module should skip canceling the data flow when its stopped. * * @param inSkipCancel if the module should skip canceling the data * flow when its stopped. */ public void setSkipCancel(boolean inSkipCancel) { mSkipCancel = inSkipCancel; } /** * If the module should throw an exception from the preStart method. * * @param inFailPreStart if the module should throw an exception from * the preStart method. */ public void setFailPreStart(boolean inFailPreStart) { mFailPreStart = inFailPreStart; } /** * If the module should attempt to create a data flow from within * the requestData() or cancel() method. * * @param inNestedCreateDataFlow if the module should attempt to * create a nested data flow. */ public void setNestedCreateDataFlow(boolean inNestedCreateDataFlow) { mNestedCreateDataFlow = inNestedCreateDataFlow; } /** * If the module should attempt to cancel a data flow from within * the requestData() or cancel() method. * * @param inNestedCancelDataFlow if the module should attempt to * cancel a data flow when canceling another data flow. */ public void setNestedCancelDataFlow(boolean inNestedCancelDataFlow) { mNestedCancelDataFlow = inNestedCancelDataFlow; } /** * if the module should invoke nested flow requests from within * requestData(). * * @param inNestDataFlowInRequest if the module should invoke nested * flow requests from within requestData(). */ public void setNestDataFlowInRequest(boolean inNestDataFlowInRequest) { mNestDataFlowInRequest = inNestDataFlowInRequest; } /** * if the module should invoke nested flow requests from within cancel(). * * @param inNestDataFlowInCancel if the module should invoke nested * flow requests from within cancel(). */ public void setNestDataFlowInCancel(boolean inNestDataFlowInCancel) { mNestDataFlowInCancel = inNestDataFlowInCancel; } /** * Gets the failure observed when invoking data flow APIs from within * cancel(). * * @return the failure observed when invoking data flow APIs from within * cancel(). */ public ModuleException getNestedCancelFailure() { return mNestedCancelFailure; } /** * Clears the failure observed when invoking data flow APIs from within. * cancel(). */ public void resetNestedCancelFailure() { mNestedCancelFailure = null; } void createFlow() throws ModuleException { if(mRequests != null) { if(mInvokeDefault) { setFlowID(mSupport.createDataFlow(mRequests)); } else { setFlowID(mSupport.createDataFlow(mRequests, mAppendSink)); } } if(mDataRequests != null) { mFlowIDs.clear(); for(DataRequest[] request: mDataRequests) { if(mInvokeDefault) { mFlowIDs.add(mSupport.createDataFlow(request)); } else { mFlowIDs.add(mSupport.createDataFlow(request, mAppendSink)); } } } } void cancelFlow() throws ModuleException { if(mFlowID != null) { mSupport.cancel(mFlowID); setFlowID(null); } if(!mFlowIDs.isEmpty()) { for(DataFlowID id: mFlowIDs) { mSupport.cancel(id); } mFlowIDs.clear(); } } private void doNestedRequestOrCancel() throws ModuleException { if (mNestedCreateDataFlow) { if (mInvokeDefault) { mSupport.createDataFlow(null); } else { mSupport.createDataFlow(null, true); } } if (mNestedCancelDataFlow) { mSupport.cancel(null); } } private DataFlowID mFlowID; private List<DataFlowID> mFlowIDs = new LinkedList<DataFlowID>(); private boolean mInvokeDefault; private boolean mAppendSink; private boolean mSkipCancel = false; private boolean mFailPreStart = false; private DataRequest[] mRequests; private List<DataRequest[]> mDataRequests = new LinkedList<DataRequest[]>(); private DataFlowSupport mSupport; private boolean mNestedCreateDataFlow; private boolean mNestedCancelDataFlow; private boolean mNestDataFlowInRequest; private boolean mNestDataFlowInCancel; private ModuleException mNestedCancelFailure; }