/*
* Created on Jul 7, 2006 Copyright (C) 2001-5, Anthony Harrison anh23@pitt.edu
* (jactr.org) This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version. This library is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU Lesser General Public License for more details. You should have
* received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple
* Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.jactr.modules.pm.visual.buffer.six;
import java.util.Collection;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.buffer.IllegalActivationBufferStateException;
import org.jactr.core.buffer.delegate.ExpandChunkRequestDelegate;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunk.ISymbolicChunk;
import org.jactr.core.chunktype.IChunkType;
import org.jactr.core.logging.Logger;
import org.jactr.core.model.IModel;
import org.jactr.core.production.request.ChunkTypeRequest;
import org.jactr.core.runtime.ACTRRuntime;
import org.jactr.core.slot.BasicSlot;
import org.jactr.core.slot.IMutableSlot;
import org.jactr.core.slot.ISlot;
import org.jactr.modules.pm.buffer.IPerceptualBuffer;
import org.jactr.modules.pm.common.buffer.AbstractPMActivationBuffer6;
import org.jactr.modules.pm.common.memory.IPerceptualMemory;
import org.jactr.modules.pm.visual.IVisualModule;
import org.jactr.modules.pm.visual.buffer.IVisualActivationBuffer;
import org.jactr.modules.pm.visual.buffer.IVisualLocationBuffer;
import org.jactr.modules.pm.visual.buffer.processor.VisualSearchRequestDelegate;
/**
* since visual-location and visual buffers share the same state information
* (stored in the visual buffer) so care must be taken to use the visual buffers
* state information and not visual location's
*
* @author developer
*/
public class DefaultVisualLocationBuffer6 extends AbstractPMActivationBuffer6
implements IVisualLocationBuffer
{
/**
* logger definition
*/
static public final Log LOGGER = LogFactory
.getLog(DefaultVisualLocationBuffer6.class);
protected IChunk _currentVisualLocation;
protected IChunk _lastVisualLocation;
protected IChunkType _visualLocationChunkType;
protected IVisualActivationBuffer _visualActivationBuffer;
protected VisualSearchRequestDelegate _scanDelegate;
public DefaultVisualLocationBuffer6(IVisualActivationBuffer visualBuffer,
IVisualModule module)
{
super(IVisualModule.VISUAL_LOCATION_BUFFER, module);
_visualActivationBuffer = visualBuffer;
}
@Override
public void initialize()
{
try
{
_visualLocationChunkType = getModel().getDeclarativeModule()
.getChunkType(IVisualModule.VISUAL_LOCATION_CHUNK_TYPE).get();
}
catch (Exception e)
{
LOGGER.error("Could not get chunktype "
+ IVisualModule.VISUAL_LOCATION_CHUNK_TYPE, e);
}
super.initialize();
installDefaultChunkPatternProcessors();
}
@Override
protected Collection<IChunk> clearInternal()
{
Collection<IChunk> source = super.clearInternal();
_currentVisualLocation = null;
if (_scanDelegate.isBufferStuffPending())
_scanDelegate.cancelBufferStuff();
clearLastLocation();
return source;
}
/**
* since the visual location chunks are reused, we want to turn off the copy
* mechanism
*
* @see org.jactr.core.buffer.six.AbstractActivationBuffer6#copyChunkOnInsertion()
*/
@Override
protected boolean shouldCopyOnInsertion(IChunk sourceChunk)
{
return false;
}
/**
* returns the current visual location in the buffer or the last attended
* location
*
* @return
* @see org.jactr.modules.pm.visual.buffer.IVisualLocationBuffer#getCurrentVisualLocation()
*/
public IChunk getCurrentVisualLocation()
{
if (_currentVisualLocation != null) return _currentVisualLocation;
return _lastVisualLocation;
}
@Override
protected void setSourceChunkInternal(IChunk chunk)
{
if (chunk != null
&& !chunk.isA(((IVisualModule) getModule())
.getVisualLocationChunkType()))
throw new IllegalActivationBufferStateException(getName()
+ " may only contain visual-location chunks not : "
+ chunk.getSymbolicChunk().getChunkType());
super.setSourceChunkInternal(chunk);
_currentVisualLocation = getSourceChunk();
IModel model = getModel();
if (Logger.hasLoggers(model))
Logger.log(model, Logger.Stream.VISUAL, getName()
+ " current visual location " + _currentVisualLocation);
if (chunk != null && !chunk.equals(_lastVisualLocation))
clearLastLocation();
}
protected void clearLastLocation()
{
if (_lastVisualLocation != null)
synchronized (_lastVisualLocation)
{
if (LOGGER.isDebugEnabled())
LOGGER
.debug("clearing temporary slot values of prior visual-location "
+ _lastVisualLocation);
/*
* it was in the buffer, zero the slot values that aren't persistent
*/
ISymbolicChunk sc = _lastVisualLocation.getSymbolicChunk();
for (ISlot slot : sc.getSlots())
if (!slot.getName().equals(IVisualModule.SCREEN_X_SLOT)
&& !slot.getName().equals(IVisualModule.SCREEN_Y_SLOT)) try
{
IMutableSlot ms = (IMutableSlot) sc.getSlot(slot.getName());
ms.setValue(null);
}
catch (Exception e)
{
}
_lastVisualLocation.setMetaData(
IPerceptualMemory.SEARCH_RESULT_IDENTIFIER_KEY, null);
}
_lastVisualLocation = null;
}
@Override
protected boolean removeSourceChunkInternal(IChunk chunkToRemove)
{
if (super.removeSourceChunkInternal(chunkToRemove))
{
/*
* we store this so that the next time a visual-location is added, the
* temporary slot values are cleared. We want to clear them so that we
* don't carry around a bunch of detritus - but we can't do it here
* because the encoding functions in the visual module or other related
* modules ( i.e. configural or manipulative in ACT-R/S) will rely upon
* the objects slot in the visual-location, which will likely be removed
* from the vis-loc buffer before encoding
*/
_lastVisualLocation = chunkToRemove;
return true;
}
return false;
}
protected void installDefaultChunkPatternProcessors()
{
/*
* this will expand any inserted chunk requests to chunktype requests. this
* allows the modeler to do a +visual-location> =oldLoc which will then
* start a new search
*/
addRequestDelegate(new ExpandChunkRequestDelegate(false));
_scanDelegate = new VisualSearchRequestDelegate((IVisualModule) getModule());
addRequestDelegate(_scanDelegate);
}
@Override
protected boolean isValidChunkType(IChunkType chunkType)
{
return chunkType.isA(_visualLocationChunkType);
}
/**
* we stuff the buffer if this buffer is empty and free AND the visual buffer
* is free. If they are, we create a basic visual search request, set the
* state (ours, not the visual buffers) to unrequested, and pass the request
* on to the visual location chunk pattern processor
*
* @see org.jactr.modules.pm.visual.buffer.IVisualLocationBuffer#checkForBufferStuff()
*/
public void checkForBufferStuff()
{
/*
* can't stuff if full, requested or unrequested
*/
if (!isBufferEmpty()) return;
/*
* cant stuff during busy or error, only free
*/
if (!isStateFree()) return;
if (LOGGER.isDebugEnabled())
LOGGER.debug("Setting search pattern for buffer stuff");
/*
* there is some stuffing to do.. lets do a basic search for anything new,
* near the center of view note: this is not the same as lisp which looks
* for the newest left most (WTF?).
*/
IVisualModule module = (IVisualModule) getModule();
ChunkTypeRequest locationBufferStuffPattern = new ChunkTypeRequest(module
.getVisualLocationChunkType());
locationBufferStuffPattern.addSlot(new BasicSlot(
IVisualModule.ATTENDED_STATUS_SLOT, getModel().getDeclarativeModule()
.getNewChunk()));
// @bug this should be based on current
// locationBufferStuffPattern.addSlot(new BasicSlot(
// IVisualModule.NEAREST_SLOT, module.getVisualMemory()
// .getVisualLocationChunkAt(0, 0)));
locationBufferStuffPattern.addSlot(new BasicSlot(
IPerceptualBuffer.IS_BUFFER_STUFF_REQUEST, true));
IModel model = getModel();
if (Logger.hasLoggers(model))
Logger.log(model, Logger.Stream.VISUAL, "Attempting a stuff search with "
+ locationBufferStuffPattern);
request(locationBufferStuffPattern, ACTRRuntime.getRuntime().getClock(
getModel()).getTime());
}
/**
* so that we don't try to encode the visual locations which are taken care of
* by the visual map..
*
* @see org.jactr.core.buffer.AbstractActivationBuffer#handlesEncoding()
*/
@Override
public boolean handlesEncoding()
{
return true;
}
public boolean isBufferStuffPending()
{
return _scanDelegate.isBufferStuffPending();
}
public void cancelBufferStuff()
{
_scanDelegate.cancelBufferStuff();
}
}