package org.jactr.core.module.procedural.map.instance;
/*
* default logging
*/
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import javolution.util.FastList;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.buffer.IActivationBuffer;
import org.jactr.core.buffer.event.ActivationBufferEvent;
import org.jactr.core.buffer.event.ActivationBufferListenerAdaptor;
import org.jactr.core.buffer.event.IActivationBufferListener;
import org.jactr.core.buffer.six.IStatusBuffer;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunk.event.ChunkEvent;
import org.jactr.core.chunk.event.ChunkListenerAdaptor;
import org.jactr.core.chunk.event.IChunkListener;
import org.jactr.core.concurrent.ExecutorServices;
import org.jactr.core.module.procedural.map.template.GeneralInstantiationMapTemplate;
import org.jactr.core.production.IProduction;
import org.jactr.core.production.condition.ICondition;
import org.jactr.core.slot.ISlot;
import org.jactr.core.slot.ISlotContainer;
public class GeneralInstantiationMap extends AbstractInstantiationMap<Object>
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(GeneralInstantiationMap.class);
/**
* will be {@link IChunkListener} if root is chunk, or
* {@link IActivationBufferListener} if it is a buffer (for status)
*/
private Object _listener;
/**
* productions that make reference to status slots that aren't immediately
* obvious (IStatusBuffer.getSlots() doesn't contain the names) - this is fine
* as some status buffers might be scoped (i.e. motor)
*/
final private Set<IProduction> _unknownStatusSlotProductions;
final private Map<String, Set<IProduction>> _productions;
public GeneralInstantiationMap(Object root, GeneralInstantiationMapTemplate template,
IInstaniationMap parent)
{
super(root, template, parent);
_unknownStatusSlotProductions = new TreeSet<IProduction>();
_productions = template.getRETEMapping();
}
private Set<IProduction> getProductions(String slotName,
boolean createIfMissing)
{
slotName = slotName.toLowerCase();
synchronized (_productions)
{
Set<IProduction> prods = _productions.get(slotName);
if (prods == null && createIfMissing)
{
prods = new TreeSet<IProduction>();
_productions.put(slotName, prods);
}
return prods;
}
}
private void remove(String slotName)
{
slotName = slotName.toLowerCase();
synchronized (_productions)
{
_productions.remove(slotName);
}
}
public boolean add(IProduction production, ICondition condition)
{
if (!(condition instanceof ISlotContainer)) return false;
FastList<ISlot> container = FastList.newInstance();
boolean added = false;
for (ISlot slot : ((ISlotContainer) condition).getSlots(container))
{
String name = slot.getName().toLowerCase();
Set<IProduction> productions = getProductions(name, true);
productions.add(production);
added = true;
}
FastList.recycle(container);
return added;
}
public void remove(IProduction production, ICondition condition)
{
if (!(condition instanceof ISlotContainer)) return;
FastList<ISlot> container = FastList.newInstance();
for (ISlot slot : ((ISlotContainer) condition).getSlots(container))
{
String name = slot.getName().toLowerCase();
Set<IProduction> productions = getProductions(name, false);
if (productions != null)
{
productions.remove(production);
if (productions.size() == 0) remove(name);
}
}
FastList.recycle(container);
}
public boolean add(IProduction production)
{
throw new UnsupportedOperationException(
"use add(IProduction, ICondition) instead");
}
public void remove(IProduction production)
{
throw new UnsupportedOperationException(
"use remove(IProduction, ICondition) instead");
}
public int getSize()
{
synchronized (_productions)
{
return _productions.size();
}
}
@Override
public void activate()
{
super.activate();
Object root = getRoot();
if (root instanceof IChunk)
{
IChunkListener listener = new ChunkListenerAdaptor(){
@Override
public void slotChanged(ChunkEvent event)
{
String slotName = event.getSlotName().toLowerCase();
Set<IProduction> productions = getProductions(slotName, false);
if(productions!=null)
dirty(productions);
}
};
_listener = listener;
((IChunk)root).addListener(listener, ExecutorServices.INLINE_EXECUTOR);
}
else if (root instanceof IStatusBuffer)
{
IActivationBufferListener listener = new ActivationBufferListenerAdaptor(){
@Override
public void statusSlotChanged(ActivationBufferEvent abe)
{
String slotName = abe.getSlotName().toLowerCase();
Set<IProduction> productions = getProductions(slotName, false);
if(productions!=null)
dirty(productions);
}
};
_listener = listener;
((IActivationBuffer)root).addListener(listener, ExecutorServices.INLINE_EXECUTOR);
}
else if (LOGGER.isWarnEnabled())
LOGGER.warn("No clue how to activate instance for " + root);
}
@Override
public void deactivate()
{
super.deactivate();
Object root = getRoot();
if (root instanceof IChunk)
((IChunk)root).removeListener((IChunkListener)_listener);
else if (root instanceof IStatusBuffer)
((IActivationBuffer)root).removeListener((IActivationBufferListener)_listener);
else if (LOGGER.isWarnEnabled())
LOGGER.warn("No clue how to deactivate instance for " + root);
}
public Set<IProduction> getFailedProductions()
{
// TODO Auto-generated method stub
return null;
}
public Set<IProduction> getTestableProductions()
{
// TODO Auto-generated method stub
return null;
}
}