package org.jactr.modules.threaded.goal.buffer; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.buffer.IActivationBuffer; import org.jactr.core.buffer.delegate.AddChunkRequestDelegate; import org.jactr.core.buffer.delegate.AddChunkTypeRequestDelegate; import org.jactr.core.buffer.delegate.AsynchronousRequestDelegate; import org.jactr.core.buffer.delegate.IDelegatedRequestableBuffer; import org.jactr.core.buffer.delegate.IRequestDelegate; import org.jactr.core.buffer.event.ActivationBufferEvent; import org.jactr.core.buffer.six.AbstractCapacityBuffer6; import org.jactr.core.chunk.IChunk; import org.jactr.core.chunktype.IChunkType; import org.jactr.core.logging.Logger; import org.jactr.core.model.IModel; import org.jactr.core.module.IModule; import org.jactr.core.production.request.IRequest; import org.jactr.core.utils.parameter.ParameterHandler; public class DefaultCapacityGoalBuffer6 extends AbstractCapacityBuffer6 implements IDelegatedRequestableBuffer { /** * Logger definition */ static private transient Log LOGGER = LogFactory .getLog(DefaultCapacityGoalBuffer6.class); static final public String CHUNK_CAPACITY_PARAM = "ChunkCapacity"; int _hardChunkCapacity = 1; private Collection<IRequestDelegate> _delegates; public DefaultCapacityGoalBuffer6(String name, IModule module) { super(name, module); setG(20); setActivation(1); setEjectionPolicy(EjectionPolicy.MostRecentlyMatched); _delegates = new ArrayList<IRequestDelegate>(); /* * by default we accept +goal> =chunk and +goal> isa chunk as add operations * immediately */ AsynchronousRequestDelegate ard = new AddChunkRequestDelegate() { protected double computeCompletionTime(double startTime, IRequest request, IActivationBuffer buffer) { // ensures that adds occur with modify & remove, otherwise, // they'd be off by defAct time return startTime; } }; ard.setAsynchronous(true); ard.setUseBlockingTimedEvents(false); addRequestDelegate(ard); ard = new AddChunkTypeRequestDelegate() { protected double computeCompletionTime(double startTime, IRequest request, IActivationBuffer buffer) { // ensures that adds occur with modify & remove return startTime; } }; ard.setAsynchronous(true); ard.setUseBlockingTimedEvents(false); addRequestDelegate(ard); } @Override protected void chunkInserted(IChunk insertedChunk) { super.chunkInserted(insertedChunk); IModel model = getModel(); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.GOAL, "Added " + insertedChunk + " " + getSourceChunks()); } @Override protected void chunkRemoved(IChunk removedChunk) { super.chunkRemoved(removedChunk); IModel model = getModel(); if (Logger.hasLoggers(model)) Logger.log(model, Logger.Stream.GOAL, "Removed " + removedChunk + " " + getSourceChunks()); } /** * has capacity been reached? * * @return */ protected boolean isCapacityReached() { try { getLock().readLock().lock(); return getTimesAndChunks().size() >= _hardChunkCapacity; } finally { getLock().readLock().unlock(); } } /** * goal buffers always accept any chunk */ @Override protected boolean isValidChunkType(IChunkType chunkType) { return true; } @Override public Collection<String> getPossibleParameters() { Collection<String> rtn = new ArrayList<String>(super .getPossibleParameters()); rtn.add(CHUNK_CAPACITY_PARAM); return rtn; } @Override public Collection<String> getSetableParameters() { Collection<String> rtn = new ArrayList<String>(super.getSetableParameters()); rtn.add(CHUNK_CAPACITY_PARAM); return rtn; } @Override public String getParameter(String key) { if (CHUNK_CAPACITY_PARAM.equalsIgnoreCase(key)) return "" + _hardChunkCapacity; return super.getParameter(key); } @Override public void setParameter(String key, String value) { if (CHUNK_CAPACITY_PARAM.equalsIgnoreCase(key)) { setHardChunkCapacity(((Number) ParameterHandler.numberInstance().coerce( value)).intValue()); } else super.setParameter(key, value); } public void setHardChunkCapacity(int numberOfChunks) { if (LOGGER.isDebugEnabled()) LOGGER.debug("Setting capacity to " + numberOfChunks); int old = _hardChunkCapacity; try { getLock().writeLock().lock(); _hardChunkCapacity = numberOfChunks; } finally { getLock().writeLock().unlock(); } if (getEventDispatcher().hasListeners()) getEventDispatcher().fire( new ActivationBufferEvent(this, ActivationBufferEvent.Type.PARAMETER_CHANGED, CHUNK_CAPACITY_PARAM, old, numberOfChunks)); } @Override protected boolean requestInternal(IRequest request, double requestTime) throws IllegalArgumentException { for (IRequestDelegate delegate : _delegates) if (delegate.willAccept(request) && delegate.request(request, this, requestTime)) return true; return false; } public boolean willAccept(IRequest request) { for (IRequestDelegate delegate : _delegates) if (delegate.willAccept(request)) return true; return false; } public void addRequestDelegate(IRequestDelegate processor) { _delegates.add(processor); } public Collection<IRequestDelegate> getRequestDelegates() { return Collections.unmodifiableCollection(_delegates); } public void removeRequestDelegate(IRequestDelegate processor) { _delegates.remove(processor); } }