package org.marketcetera.module; import org.marketcetera.util.misc.ClassVersion; import java.util.*; /* $License$ */ /** * This class is used to track data flows, the modules * that initiate them and the modules that participate * in them. * <p> * This class is thread-safe. All of its methods employ locking * to ensure that the concurrent modifications to the instance's state * do not corrupt it. * * @author anshul@marketcetera.com * @version $Id: DataFlowTracker.java 16154 2012-07-14 16:34:05Z colin $ * @since 1.0.0 */ @ClassVersion("$Id: DataFlowTracker.java 16154 2012-07-14 16:34:05Z colin $") //$NON-NLS-1$ class DataFlowTracker { /** * Adds a data flow. * * @param inFlow the data flow to be added. */ synchronized void addFlow(DataFlow inFlow) { ModuleURN requester = inFlow.getRequesterURN(); mFlows.put(inFlow.getFlowID(), inFlow); if(requester != null) { add(mInitiated, requester, inFlow.getFlowID()); } for(ModuleURN p: inFlow.getParticipants()) { add(mParticipating, p, inFlow.getFlowID()); } } /** * Fetches the data flow, given the flow ID. * * @param inFlowID the data flow ID * * @return the data flow for the specified flow ID, null if not found. */ synchronized DataFlow get(DataFlowID inFlowID) { return mFlows.get(inFlowID); } /** * Removes the data flow, given the flow ID. * * @param inFlowID the data flow ID * * @return the data flow for the specified flowID, null if not found. */ synchronized DataFlow remove(DataFlowID inFlowID) { DataFlow dataFlow = mFlows.remove(inFlowID); if (dataFlow != null) { ModuleURN requester = dataFlow.getRequesterURN(); if(requester != null) { remove(mInitiated, requester, inFlowID); } for(ModuleURN p: dataFlow.getParticipants()) { remove(mParticipating, p, inFlowID); } } return dataFlow; } /** * Gets the data flows initiated by the specified module. * * @param inModuleURN the module URN. * * @return the set of data flow IDs that the module initiated, null * if this module has not initiated any data flows or any of its * initiated flows are not active. */ synchronized Set<DataFlowID> getInitiatedFlows(ModuleURN inModuleURN) { Set<DataFlowID> idSet = mInitiated.get(inModuleURN); return idSet == null ? null : new HashSet<DataFlowID>(idSet); } /** * Gets the data flows that the specified module is participating in. * * @param inModuleURN the module URN * * @return the set of data flow IDs that the module is * participating in. null, if this module is currently not * participating in data flows. */ synchronized Set<DataFlowID> getFlowsParticipating(ModuleURN inModuleURN) { Set<DataFlowID> idSet = mParticipating.get( inModuleURN); return idSet == null ? null : new HashSet<DataFlowID>(idSet); } /** * Returns the data flows that the specified module is participating in * that it did not initiate. * * @param inModuleURN the module URN * * @return the set of data flowIDs that the module is participating in that * it did not initiate. */ synchronized Set<DataFlowID> getFlowsParticipatingNotInitiated( ModuleURN inModuleURN) { Set<DataFlowID> idSet = mParticipating.get( inModuleURN); Set<DataFlowID> initSet = mInitiated.get(inModuleURN); if(idSet != null) { idSet = new HashSet<DataFlowID>(idSet); if(initSet != null) { idSet.removeAll(initSet); } } return idSet; } /** * Fetch all the IDs of all the active data flows. * * @param inIncludeModuleCreated if data flows created by modules * should be included. * * @return the IDs of all the active data flows. */ synchronized List<DataFlowID> getDataFlows(boolean inIncludeModuleCreated) { List<DataFlowID> ids; if(inIncludeModuleCreated) { ids = new ArrayList<DataFlowID>(mFlows.keySet()); } else { ids = new ArrayList<DataFlowID>(); for(DataFlow flow: mFlows.values()) { if(!flow.isModuleCreated()) { ids.add(flow.getFlowID()); } } } return ids; } /** * Adds the data flow ID to the set of flows in the specified table for * the specified module. * * @param inTable the table of data flows for module instances. * @param inURN the URN of the module whose data flows set needs * to be updated. * @param inFlowID the data flow ID. */ private static void add(Map<ModuleURN,Set<DataFlowID>> inTable, ModuleURN inURN, DataFlowID inFlowID) { Set<DataFlowID> value = inTable.get(inURN); if(value == null) { value = new HashSet<DataFlowID>(); inTable.put(inURN,value); } value.add(inFlowID); } /** * Removes the data flow ID from the set of flows in the specified table * for the specified module. * * @param inTable the table of data flows for module instances. * @param inURN the URN of the module whose data flows set needs * to be updated. * @param inFlowID the data flow ID. */ private static void remove(Map<ModuleURN, Set<DataFlowID>> inTable, ModuleURN inURN, DataFlowID inFlowID) { Set<DataFlowID> value = inTable.get(inURN); if(value != null) { value.remove(inFlowID); if(value.isEmpty()) { inTable.remove(inURN); } } } private final Map<DataFlowID, DataFlow> mFlows = new HashMap<DataFlowID, DataFlow>(); private final Map<ModuleURN, Set<DataFlowID>> mInitiated = new HashMap<ModuleURN, Set<DataFlowID>>(); private final Map<ModuleURN, Set<DataFlowID>> mParticipating = new HashMap<ModuleURN, Set<DataFlowID>>(); }