package org.jactr.modules.pm.visual.delegate;
/*
* default logging
*/
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.commonreality.identifier.IIdentifier;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.logging.Logger;
import org.jactr.core.model.IModel;
import org.jactr.core.module.asynch.delegate.BasicAsynchronousModuleDelegate;
import org.jactr.core.production.request.IRequest;
import org.jactr.modules.pm.common.memory.PerceptualSearchResult;
import org.jactr.modules.pm.visual.AbstractVisualModule;
import org.jactr.modules.pm.visual.IVisualModule;
import org.jactr.modules.pm.visual.event.VisualModuleEvent;
import org.jactr.modules.pm.visual.memory.IVisualMemory;
import org.jactr.modules.pm.visual.memory.impl.encoder.AbstractVisualEncoder;
public class VisualEncodingDelegate extends
BasicAsynchronousModuleDelegate<AbstractVisualModule, IChunk>
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(VisualEncodingDelegate.class);
public VisualEncodingDelegate(AbstractVisualModule module)
{
super(module, module.getErrorChunk());
}
/**
* returns the contents of the perceptual search
*
* @param searchResult
* @param visualModule
* @param streamName
* @return
*/
public IChunk getSearchResult(PerceptualSearchResult searchResult,
IVisualModule visualModule, String streamName)
{
IModel model = visualModule.getModel();
IChunk errorChunk = model.getDeclarativeModule().getErrorChunk();
IChunk visualLocation = searchResult.getLocation();
IChunk visualObject = searchResult.getPercept();
if (visualObject == null || visualObject.hasBeenDisposed())
{
// object has moved too far..
if (LOGGER.isDebugEnabled() || Logger.hasLoggers(model))
{
String msg = "Result of search found at " + visualLocation
+ " has changed too much since search occured, returning error";
if (LOGGER.isDebugEnabled()) LOGGER.debug(msg);
if (Logger.hasLoggers(model) && streamName != null)
Logger.log(model, streamName, msg);
}
return errorChunk;
}
/*
* this shouldnt occur. the id should be set as long as the visual object
* has not been disposed or encoded (removed from the visual buffer)
*/
IIdentifier afferentId = searchResult.getPerceptIdentifier();
if (afferentId == null)
{
if (LOGGER.isDebugEnabled() || Logger.hasLoggers(model))
{
String msg = "Result of search found at " + visualLocation
+ " has no identifier associated with it, returning error";
if (LOGGER.isWarnEnabled()) LOGGER.warn(msg);
if (Logger.hasLoggers(model) && streamName != null)
Logger.log(model, streamName, msg);
}
return errorChunk;
}
/*
* if stick and the last search is the same as this result, we don't check
* movement tolerance
*/
IVisualMemory visualMemory = visualModule.getVisualMemory();
if (!(visualMemory.isStickyAttentionEnabled() && visualMemory
.getLastSearchResult() == searchResult))
{
/*
* has it exceeded movement tolerance?
*/
IChunk currentLocation = AbstractVisualEncoder.getVisualLocation(
visualObject, visualModule.getVisualMemory());
if (currentLocation == null
|| AbstractVisualEncoder.exceedsMovementTolerance(visualLocation,
currentLocation, visualModule.getVisualMemory()))
{
if (LOGGER.isDebugEnabled() || Logger.hasLoggers(model))
{
String msg = visualObject + " found at " + visualLocation
+ " is now at " + currentLocation
+ ", which exceeds movement tolerances, returning error";
if (LOGGER.isDebugEnabled()) LOGGER.debug(msg);
if (Logger.hasLoggers(model) && streamName != null)
Logger.log(model, streamName, msg);
}
return errorChunk;
}
}
return visualObject;
}
@Override
protected IChunk processInternal(IRequest request, double requestTime,
Object... parameters)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("Requesting attending " + request + " @ " + requestTime
+ " with " + getModule().getVisualMemory().getPendingUpdates()
+ " pending updates");
PerceptualSearchResult searchResult = (PerceptualSearchResult) parameters[0];
return getSearchResult(searchResult, getModule(), Logger.Stream.VISUAL
.toString());
}
@Override
protected void processInternalCompleted(IRequest request, IChunk visualChunk,
Object... parameters)
{
AbstractVisualModule module = getModule();
if (module.hasListeners())
module.dispatch(new VisualModuleEvent(module,
VisualModuleEvent.Type.ENCODED, visualChunk));
}
@Override
protected boolean shouldProcess(IRequest request, Object... parameters)
{
AbstractVisualModule module = getModule();
IModel model = module.getModel();
PerceptualSearchResult searchResult = (PerceptualSearchResult) parameters[0];
/*
* make sure vis loc is valid
*/
if (searchResult == null)
{
String message = "Cannot encode without first having performed a search";
if (LOGGER.isWarnEnabled()) LOGGER.warn(message);
if (Logger.hasLoggers(model))
Logger.log(model, Logger.Stream.VISUAL, message);
return false;
}
/*
* make sure vis loc is valid
*/
if (!searchResult.getLocation().isA(module.getVisualLocationChunkType()))
{
String message = "An invalid move-attention was used, screen-position does not contain a visual-location chunk ("
+ searchResult.getLocation() + ")";
if (LOGGER.isWarnEnabled()) LOGGER.warn(message);
if (Logger.hasLoggers(model))
Logger.log(model, Logger.Stream.VISUAL, message);
return false;
}
return true;
}
}