package org.jactr.core.production.action;
/*
* default logging
*/
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.chunk.IChunk;
import org.jactr.core.model.IModel;
import org.jactr.core.production.CannotInstantiateException;
import org.jactr.core.production.IInstantiation;
import org.jactr.core.production.VariableBindings;
import org.jactr.core.queue.timedevents.AbstractTimedEvent;
import org.jactr.core.queue.timedevents.IBufferBasedTimedEvent;
import org.jactr.core.slot.DefaultMutableSlot;
import org.jactr.core.slot.IMutableSlot;
import org.jactr.core.slot.ISlot;
import org.jactr.core.slot.ISlotContainer;
import org.jactr.core.utils.StringUtilities;
/**
* a zero-time buffer content set operator
*
* @author harrison
*/
public class SetAction extends DefaultAction implements ISlotContainer,
IBufferAction
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(SetAction.class);
private String _bufferName;
final private Collection<IMutableSlot> _slots;
private IChunk _boundChunk;
private Object _referant;
@SuppressWarnings("unchecked")
public SetAction(String bufferName, Object referant)
{
this(bufferName, referant, Collections.EMPTY_LIST);
}
public SetAction(String bufferName, Object referant,
Collection<? extends ISlot> slots)
{
setReferant(referant);
setBufferName(bufferName);
_slots = new ArrayList<IMutableSlot>();
for (ISlot slot : slots)
addSlot(slot);
}
@Override
public void dispose()
{
super.dispose();
_slots.clear();
}
public void addSlot(ISlot slot)
{
_slots.add(new DefaultMutableSlot(slot));
}
public Collection<? extends ISlot> getSlots()
{
return getSlots(null);
}
public Collection<ISlot> getSlots(Collection<ISlot> container)
{
if (container == null) container = new ArrayList<ISlot>();
container.addAll(_slots);
return container;
}
public void removeSlot(ISlot slot)
{
_slots.remove(slot);
}
public String getBufferName()
{
return _bufferName;
}
public void setBufferName(String bufferName)
{
_bufferName = bufferName.toLowerCase();
}
public Object getReferant()
{
return _referant;
}
public void setReferant(Object ref)
{
_referant = ref;
}
public IAction bind(VariableBindings variableBindings)
throws CannotInstantiateException
{
SetAction act = new SetAction(getBufferName(), _referant, _slots);
act.bindSlotValues(variableBindings, act._slots);
act.bindChunk(variableBindings);
return act;
}
protected void bindChunk(VariableBindings bindings)
throws CannotInstantiateException
{
Object ref = getReferant();
if (ref instanceof String && ((String) ref).startsWith("="))
{
/*
* the punk is a variable name..
*/
Object resolved = resolve((String) ref, bindings);
if (resolved == null)
throw new CannotInstantiateException("Could not resolve variable name "
+ ref + " possible:" + bindings);
if (LOGGER.isDebugEnabled())
LOGGER.debug("Resolved " + ref + " to " + resolved + "("
+ resolved.getClass().getName() + ") " + bindings);
setReferant(resolved);
ref = resolved;
}
if (ref instanceof IChunk) _boundChunk = (IChunk) ref;
if (_boundChunk == null)
throw new CannotInstantiateException("Could not get chunk bound to ="
+ ref);
}
@Override
public double fire(IInstantiation instantiation, double firingTime)
{
IModel model = instantiation.getModel();
double fireAt = firingTime
+ model.getProceduralModule().getDefaultProductionFiringTime();
IActivationBuffer buffer = model.getActivationBuffer(getBufferName());
SetActionTimedEvent modify = new SetActionTimedEvent(firingTime, fireAt,
buffer, _boundChunk, getSlots());
model.getTimedEventQueue().enqueue(modify);
return 0;
}
public class SetActionTimedEvent extends AbstractTimedEvent implements
IBufferBasedTimedEvent
{
IChunk _chunkToModify;
final Collection<? extends ISlot> _slotsToChange;
final IActivationBuffer _buffer;
final String _label;
public SetActionTimedEvent(double now, double whenToFire,
IActivationBuffer buffer, IChunk chunkToModify,
Collection<? extends ISlot> slots)
{
setTimes(now, whenToFire);
_buffer = buffer;
_chunkToModify = chunkToModify;
_slotsToChange = new ArrayList<ISlot>(slots);
_label = String.format("Set(%s into %s @ %.2f)", _chunkToModify
.getSymbolicChunk().getName(), _buffer, whenToFire);
}
@Override
public String toString()
{
return _label;
}
@SuppressWarnings("synthetic-access")
@Override
public void fire(double now)
{
super.fire(now);
/*
* add the chunk to the buffer, and update the slot values
*/
_chunkToModify = _buffer.addSourceChunk(_chunkToModify);
updateSlots(_chunkToModify, _slotsToChange);
if (LOGGER.isDebugEnabled())
LOGGER.debug("Result " + StringUtilities.toString(_chunkToModify));
}
/**
* @see org.jactr.core.queue.timedevents.IBufferBasedTimedEvent#getBuffer()
*/
public IActivationBuffer getBuffer()
{
return _buffer;
}
public IChunk getBoundChunk()
{
return _chunkToModify;
}
}
}