package org.jactr.core.buffer.delegate;
/*
* default logging
*/
import java.util.Collection;
import java.util.concurrent.Future;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.buffer.IActivationBuffer;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunk.ISymbolicChunk;
import org.jactr.core.chunk.IllegalChunkStateException;
import org.jactr.core.production.request.ChunkRequest;
import org.jactr.core.production.request.IRequest;
import org.jactr.core.slot.IMutableSlot;
import org.jactr.core.slot.ISlot;
/**
* takes a chunk pattern and if the chunk is already encoded, copies it, before
* inserting into the buffer via
* {@link IActivationBuffer#addSourceChunk(org.jactr.core.chunk.IChunk)}. If the
* chunk is encoded and there are slots to be modified, the chunk will
* automatically be copied.
*
* @author harrison
*/
public class AddChunkRequestDelegate extends AsynchronousRequestDelegate
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(AddChunkRequestDelegate.class);
private boolean _copyEncodedChunks = true;
/**
* default is to copy encoded chunks
*/
public AddChunkRequestDelegate()
{
this(true);
}
public AddChunkRequestDelegate(boolean copyEncodedChunks)
throws IllegalArgumentException
{
_copyEncodedChunks = copyEncodedChunks;
}
public boolean willAccept(IRequest request)
{
return request instanceof ChunkRequest;
}
@Override
protected boolean isValid(IRequest request, IActivationBuffer buffer)
throws IllegalArgumentException
{
if (!(request instanceof ChunkRequest))
throw new IllegalArgumentException("Request must be ChunkRequest");
ChunkRequest cRequest = (ChunkRequest) request;
IChunk chunk = cRequest.getChunk();
ISymbolicChunk sChunk = chunk.getSymbolicChunk();
Collection<? extends ISlot> slots = cRequest.getSlots();
for (ISlot slot : slots)
{
boolean valid = false;
try
{
valid = null != sChunk.getSlot(slot.getName());
}
catch (IllegalChunkStateException icse)
{
}
if (!valid)
throw new IllegalArgumentException("No slot named " + slot.getName()
+ " available in " + chunk);
}
return true;
}
@Override
protected Object startRequest(IRequest request, IActivationBuffer buffer, double requestTime)
{
ChunkRequest cRequest = (ChunkRequest) request;
IChunk originalChunk = cRequest.getChunk();
Future<IChunk> copiedChunk = null;
Collection<? extends ISlot> slots = cRequest.getSlots();
if (originalChunk.isEncoded() && (slots.size() != 0 || _copyEncodedChunks))
copiedChunk = buffer.getModel().getDeclarativeModule().copyChunk(
originalChunk);
if (copiedChunk != null) return copiedChunk;
return originalChunk;
}
@SuppressWarnings("unchecked")
@Override
protected void finishRequest(IRequest request, IActivationBuffer buffer,
Object startValue)
{
ChunkRequest cRequest = (ChunkRequest) request;
Collection<? extends ISlot> slots = cRequest.getSlots();
IChunk toAdd = null;
if (startValue instanceof IChunk)
toAdd = (IChunk) startValue;
else
try
{
toAdd = ((Future<IChunk>) startValue).get();
}
catch (Exception e)
{
LOGGER.error("Failed to get chunk from future reference. Request:"
+ request + " Buffer:" + buffer + " Start:" + startValue, e);
// bail out, shop probably do some model logging
return;
}
/*
* set the values...safely with the lock
*/
try
{
toAdd.getWriteLock().lock();
ISymbolicChunk sChunk = toAdd.getSymbolicChunk();
for (ISlot slot : slots)
((IMutableSlot) sChunk.getSlot(slot.getName())).setValue(slot
.getValue());
}
finally
{
toAdd.getWriteLock().unlock();
}
/*
* and add to the buffer..
*/
buffer.addSourceChunk(toAdd);
}
}