package org.jactr.modules.pm.vocal.delegate; /* * default logging */ import java.util.HashSet; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.commonreality.agents.IAgent; import org.commonreality.efferent.IEfferentCommand; import org.commonreality.identifier.IIdentifier; import org.jactr.core.chunk.IChunk; import org.jactr.core.model.IModel; import org.jactr.core.module.asynch.delegate.AbstractAsynchronousModuleDelegate; import org.jactr.core.production.condition.ChunkPattern; import org.jactr.core.production.request.ChunkTypeRequest; import org.jactr.core.production.request.IRequest; import org.jactr.core.queue.ITimedEvent; import org.jactr.core.queue.timedevents.AbstractTimedEvent; import org.jactr.core.queue.timedevents.BlockingTimedEvent; import org.jactr.core.runtime.ACTRRuntime; import org.jactr.modules.pm.vocal.AbstractVocalModule; @Deprecated public abstract class AbstractVocalDelegate extends AbstractAsynchronousModuleDelegate<AbstractVocalModule, IChunk> { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(AbstractVocalDelegate.class); private Set<IEfferentCommand.ActualState> _driftStates; private Set<IEfferentCommand.ActualState> _earlyTerminationStates; private ITimedEvent _currentTimedEvent; private BlockingTimedEvent _currentBlockingTimedEvent; private IIdentifier _currentCommandIdentifier; public AbstractVocalDelegate(AbstractVocalModule module, double minimumProcessingTime, IChunk cantProcessResult) { super(module, minimumProcessingTime, cantProcessResult); _driftStates = new HashSet<IEfferentCommand.ActualState>(); _earlyTerminationStates = new HashSet<IEfferentCommand.ActualState>(); } protected void setDriftStates(IEfferentCommand.ActualState... states) { for (IEfferentCommand.ActualState state : states) _driftStates.add(state); } protected void setEarlyTerminationStates( IEfferentCommand.ActualState... states) { for (IEfferentCommand.ActualState state : states) _earlyTerminationStates.add(state); } protected void blockingTimedEventCreated(BlockingTimedEvent bte) { _currentBlockingTimedEvent = bte; } public boolean commandStateChanged(IIdentifier commandIdentifier, IEfferentCommand.ActualState state, boolean callingFromFinalize) { if (_currentCommandIdentifier == null || !_currentCommandIdentifier.equals(commandIdentifier)) { if (LOGGER.isDebugEnabled()) LOGGER.debug(getClass().getSimpleName() + " : " + commandIdentifier + " does not match current command identifier " + _currentCommandIdentifier + ", ignoring"); return false; } if (_currentBlockingTimedEvent == null) { if (LOGGER.isWarnEnabled()) LOGGER .warn(getClass().getSimpleName() + " : " + "No blocking timed event for " + commandIdentifier + "? Ignoring"); return false; } if (_currentTimedEvent == null) { if (LOGGER.isWarnEnabled()) LOGGER.warn(getClass().getSimpleName() + " : " + "No timed event for " + commandIdentifier + "? Ignoring"); return false; } boolean isDrift = _driftStates.contains(state); if (!_earlyTerminationStates.contains(state) && !isDrift) { if (LOGGER.isDebugEnabled()) LOGGER.debug(getClass().getSimpleName() + " : " + state + " is neither early termination nor drift state, ignoring"); return false; } if (LOGGER.isDebugEnabled()) LOGGER.debug("State is " + state + " isDrift=" + isDrift); /* * if we are calling from the finalization method, we are only * concerned if this is a drift state, otherwise we return */ if(!isDrift && callingFromFinalize) return false; /* * we need to push the timed event back by creating a new one */ VocalTimedEvent vte = (VocalTimedEvent) _currentTimedEvent; double now = ACTRRuntime.getRuntime().getClock(getModule().getModel()) .getTime(); synchronized (vte) { if (LOGGER.isDebugEnabled()) LOGGER.debug("TimedEvent is supposed to fire at "+vte.getEndTime()); if ((!vte.hasFired() && !vte.hasAborted()) || callingFromFinalize) { if (isDrift) { enqueue(vte.driftTo(vte.getEndTime() + getMinimumProcessingTime())); if (LOGGER.isDebugEnabled()) LOGGER.debug(getClass().getSimpleName() + " : Drifting vocal timed event back to " + _currentTimedEvent.getEndTime()); } else { enqueue(vte.driftTo(now)); if (LOGGER.isDebugEnabled()) LOGGER.debug(getClass().getSimpleName() + " : Accelerating vocal timed event to " + _currentTimedEvent.getEndTime()); } if (!vte.hasAborted() && !vte.hasFired()) vte.abort(); return true; } else if (!callingFromFinalize && LOGGER.isDebugEnabled()) LOGGER.debug(getClass().getSimpleName() + " : current vocal timed event has already fired"); } return false; } final protected void finalizeProcessing(IRequest request, IChunk result, Object... parameters) { AbstractVocalModule module = getModule(); IModel model = module.getModel(); IAgent agent = ACTRRuntime.getRuntime().getConnector().getAgent(model); IEfferentCommand vocalizationCommand = agent.getEfferentCommandManager() .get(getCommandIdentifier()); if (vocalizationCommand != null) { /* * it is possible that we will not have heard back from CR on the command * by the time the timed event fires. so, we should check again to see if * we need to drift. if so, return. and let the drifted timed event fire * us later */ if (commandStateChanged(getCommandIdentifier(), vocalizationCommand .getActualState(), true)) return; } if (LOGGER.isDebugEnabled()) LOGGER.debug(getClass().getSimpleName() + " Finalizing"); finalizeProcessingInternal((ChunkTypeRequest)request, result, parameters); _currentBlockingTimedEvent = null; _currentCommandIdentifier = null; _currentTimedEvent = null; } abstract protected void finalizeProcessingInternal(ChunkTypeRequest pattern, IChunk result, Object... parameters); final protected void enqueue(ITimedEvent timedEvent) { setCurrentTimedEvent(timedEvent); getModule().getVocalBuffer().enqueueTimedEvent(timedEvent); } private void setCurrentTimedEvent(ITimedEvent timedEvent) { _currentTimedEvent = timedEvent; } protected void setCommandIdentifier(IIdentifier identifier) { _currentCommandIdentifier = identifier; } protected IIdentifier getCommandIdentifier() { return _currentCommandIdentifier; } final protected ITimedEvent createHarvestTimedEvent(double start, double end, IRequest request, IChunk result, Object... parameters) { return new VocalTimedEvent(start, end, (ChunkTypeRequest) request, result, parameters); } private class VocalTimedEvent extends AbstractTimedEvent { private IChunk _result; private Object[] _parameters; private ChunkTypeRequest _pattern; public VocalTimedEvent(double start, double end, ChunkTypeRequest pattern, IChunk result, Object... parameters) { super(start, end); _result = result; _pattern = pattern; _parameters = parameters; } public VocalTimedEvent driftTo(double newEndTime) { return new VocalTimedEvent(getStartTime(), newEndTime, _pattern, _result, _parameters); } public void fire(double currentTime) { super.fire(currentTime); finalizeProcessing(_pattern, _result, _parameters); } } }