package org.jactr.modules.pm.visual.memory.impl.map;
/*
* default logging
*/
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import javolution.util.FastSet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.commonreality.identifier.IIdentifier;
import org.commonreality.modalities.visual.Color;
import org.commonreality.modalities.visual.IVisualPropertyHandler;
import org.commonreality.object.IAfferentObject;
import org.commonreality.object.UnknownPropertyNameException;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.model.IModel;
import org.jactr.core.production.request.ChunkTypeRequest;
import org.jactr.core.slot.BasicSlot;
import org.jactr.core.slot.IConditionalSlot;
import org.jactr.modules.pm.visual.IVisualModule;
public class ColorFeatureMap extends AbstractVisualFeatureMap<Color[]>
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(ColorFeatureMap.class);
private Map<Color, Set<IIdentifier>> _valueMap;
private Map<IIdentifier, Color[]> _currentValues;
private ColorChunkCache _cache;
public ColorFeatureMap(IModel model)
{
super(IVisualModule.COLOR_SLOT, IVisualPropertyHandler.COLOR);
_valueMap = new HashMap<Color, Set<IIdentifier>>();
_currentValues = new HashMap<IIdentifier, Color[]>();
_cache = new ColorChunkCache(model);
}
public ColorChunkCache getColorChunkCache()
{
return _cache;
}
@Override
protected void addInformation(IIdentifier identifier, Color[] data)
{
for (Color color : data)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug(identifier + " has color " + color);
Set<IIdentifier> identifiers = _valueMap.get(color);
if (identifiers == null)
{
identifiers = FastSet.newInstance();
_valueMap.put(color, identifiers);
}
identifiers.add(identifier);
}
_currentValues.put(identifier, data);
}
@Override
protected void clearInternal()
{
_valueMap.clear();
_currentValues.clear();
}
@Override
protected Color[] getCurrentValue(IIdentifier identifier)
{
return _currentValues.get(identifier);
}
@Override
protected Color[] extractInformation(IAfferentObject afferentObject)
{
try
{
return getHandler().getColors(afferentObject);
}
catch (UnknownPropertyNameException unknown)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug(
"Could not find coloring info for "
+ afferentObject.getIdentifier(), unknown);
return new Color[0];
}
}
@Override
protected void getCandidates(ChunkTypeRequest request,
Set<IIdentifier> results)
{
boolean firstInsertion = true;
String slotName = getRelevantSlotName();
FastSet<IIdentifier> tmp = FastSet.newInstance();
for (IConditionalSlot slot : request.getConditionalSlots())
if (slot.getName().equalsIgnoreCase(slotName))
{
Object slotValue = slot.getValue();
Color value = null;
if (slotValue instanceof IChunk || slotValue == null)
value = _cache.getColor((IChunk) slotValue);
else if (LOGGER.isWarnEnabled())
LOGGER.warn(String
.format("color feature map requires null or color chunk values"));
tmp.clear();
switch (slot.getCondition())
{
case IConditionalSlot.NOT_EQUALS:
not(value, tmp);
break;
case IConditionalSlot.EQUALS:
equals(value, tmp);
break;
default:
LOGGER.warn("only not and equals are available for color");
break;
}
if (firstInsertion)
{
firstInsertion = false;
results.addAll(tmp);
}
else
results.retainAll(tmp);
}
FastSet.recycle(tmp);
}
protected void not(Color color, Set<IIdentifier> container)
{
for (Map.Entry<Color, Set<IIdentifier>> entry : _valueMap.entrySet())
if (color == null && entry.getKey() != null
|| !color.equals(entry.getKey())) container.addAll(entry.getValue());
}
protected void equals(Color color, Set<IIdentifier> container)
{
Set<IIdentifier> tmp = _valueMap.get(color);
if (tmp != null) container.addAll(tmp);
}
@Override
protected Color[] removeInformation(IIdentifier identifier)
{
Color[] colors = _currentValues.remove(identifier);
if (colors != null) for (Color color : colors)
{
Set<IIdentifier> identifiers = _valueMap.get(color);
if (identifiers != null)
{
identifiers.remove(identifier);
if (identifiers.size() == 0)
{
_valueMap.remove(color);
FastSet.recycle((FastSet) identifiers);
}
}
}
return colors;
}
@Override
public void fillSlotValues(ChunkTypeRequest mutableRequest,
IIdentifier identifier, IChunk encodedChunk,
ChunkTypeRequest originalSearchRequest)
{
/*
* we require the original search pattern since there can be many colors..
*/
Color[] colors = _currentValues.get(identifier);
if (colors != null)
for (Color color : colors)
if (colorMatchesPattern(color, originalSearchRequest))
{
IChunk colorChunk = _cache.getColorChunk(color);
if (LOGGER.isDebugEnabled())
LOGGER.debug("setting color to " + colorChunk + " describing "
+ color);
// assign the value and return
mutableRequest.addSlot(new BasicSlot(IVisualModule.COLOR_SLOT,
colorChunk));
return;
}
if (LOGGER.isDebugEnabled()) LOGGER.debug("no color to set");
}
protected boolean colorMatchesPattern(Color color, ChunkTypeRequest request)
{
for (IConditionalSlot slot : request.getConditionalSlots())
if (slot.getName().equalsIgnoreCase(IVisualModule.COLOR_SLOT))
{
Object slotValue = slot.getValue();
if (slotValue instanceof IChunk || slotValue == null)
{
Color value = _cache.getColor((IChunk) slotValue);
switch (slot.getCondition())
{
case IConditionalSlot.NOT_EQUALS:
if (color.equals(value)) return false;
break;
case IConditionalSlot.EQUALS:
if (!color.equals(value)) return false;
default:
LOGGER.warn("only not and equals are available for color");
break;
}
}
}
return true;
}
public void normalizeRequest(ChunkTypeRequest request)
{
// TODO Auto-generated method stub
}
}