package org.jactr.modules.pm.aural.memory.impl;
/*
* default logging
*/
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.commonreality.identifier.IIdentifier;
import org.commonreality.modalities.aural.DefaultAuralPropertyHandler;
import org.commonreality.modalities.aural.IAuralPropertyHandler;
import org.commonreality.object.IAfferentObject;
import org.commonreality.object.delta.IObjectDelta;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunk.event.ChunkEvent;
import org.jactr.core.chunk.event.IChunkListener;
import org.jactr.core.chunktype.IChunkType;
import org.jactr.core.module.declarative.IDeclarativeModule;
import org.jactr.core.slot.ISlot;
import org.jactr.modules.pm.aural.IAuralModule;
import org.jactr.modules.pm.common.afferent.DefaultAfferentObjectListener;
import org.jactr.modules.pm.common.afferent.IAfferentObjectListener;
import org.jactr.modules.pm.common.memory.IPerceptualEncoder;
import org.jactr.modules.pm.common.memory.impl.IIndexManager;
/**
* @author harrison
*/
public class AuralEventIndexManager implements IIndexManager
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(AuralEventIndexManager.class);
final private IAuralModule _module;
/*
* listener allows us to create and remove audio-event chunks as they are
* needed.
*/
final private IAfferentObjectListener _afferentListener;
final private Map<IIdentifier, IChunk> _existingIndexChunks;
final private IAuralPropertyHandler _auralPropertyHandler = new DefaultAuralPropertyHandler();
final private Lock _lock = new ReentrantLock();
final private IChunkListener _encodingListener;
public AuralEventIndexManager(IAuralModule module)
{
_module = module;
_existingIndexChunks = new HashMap<IIdentifier, IChunk>();
_afferentListener = new IAfferentObjectListener() {
public void afferentObjectAdded(IAfferentObject object)
{
addIndex(object);
}
public void afferentObjectRemoved(IAfferentObject object)
{
removeIndex(object);
}
public void afferentObjectUpdated(IAfferentObject object,
IObjectDelta delta)
{
}
public boolean isInterestedIn(IAfferentObject object)
{
return _auralPropertyHandler.hasModality(object);
}
};
_encodingListener = new IChunkListener() {
public void chunkAccessed(ChunkEvent event)
{
}
public void chunkEncoded(ChunkEvent event)
{
IChunk indexChunk = event.getSource();
indexChunk.removeListener(_encodingListener);
removeIndex(getIdentifier(indexChunk));
}
public void mergingInto(ChunkEvent event)
{
IChunk indexChunk = event.getSource();
indexChunk.removeListener(_encodingListener);
removeIndex(getIdentifier(indexChunk));
}
public void mergingWith(ChunkEvent event)
{
IChunk indexChunk = event.getChunk();
indexChunk.removeListener(_encodingListener);
removeIndex(getIdentifier(indexChunk));
}
public void similarityChanged(ChunkEvent event)
{
}
public void slotChanged(ChunkEvent event)
{
}
};
}
protected void attach(DefaultAfferentObjectListener afferentListener)
{
afferentListener.add(_afferentListener);
}
protected void detach(DefaultAfferentObjectListener afferentListener)
{
afferentListener.remove(_afferentListener);
}
protected IChunk addIndex(IAfferentObject object)
{
/*
* create the chunk first..
*/
IChunkType audioEventType = _module.getAudioEventChunkType();
IDeclarativeModule decM = audioEventType.getModel().getDeclarativeModule();
IIdentifier identifier = object.getIdentifier();
IChunk event = null;
try
{
event = decM.createChunk(audioEventType,
String.format("ae-%s", identifier.getName())).get();
}
catch (Exception e)
{
LOGGER.error(String.format("Failed to create aural index chunk for %s",
identifier), e);
return null;
}
if (LOGGER.isDebugEnabled())
LOGGER.debug(String.format("created audio-event for %s", identifier));
try
{
_lock.lock();
event.setMetaData(IPerceptualEncoder.COMMONREALITY_IDENTIFIER_META_KEY,
identifier);
_existingIndexChunks.put(identifier, event);
return event;
}
finally
{
_lock.unlock();
}
}
private IIdentifier getIdentifier(IChunk indexChunk)
{
return (IIdentifier) indexChunk
.getMetaData(IPerceptualEncoder.COMMONREALITY_IDENTIFIER_META_KEY);
}
protected void removeIndex(IAfferentObject object)
{
removeIndex(object.getIdentifier());
}
protected void removeIndex(IIdentifier identifier)
{
if (identifier == null) return;
IChunk index = null;
if (LOGGER.isDebugEnabled())
LOGGER.debug(String.format("removing audio-event %s", identifier));
try
{
_lock.lock();
index = _existingIndexChunks.remove(identifier);
}
finally
{
_lock.unlock();
}
/*
* it was never used, so dispose
*/
if (index != null && !index.isEncoded() && !index.hasBeenDisposed())
index.getModel().getDeclarativeModule().dispose(index);
}
public IChunk getIndexChunk(IChunk encodedChunk)
{
try
{
ISlot event = encodedChunk.getSymbolicChunk().getSlot(
IAuralModule.EVENT_SLOT);
return (IChunk) event.getValue();
}
catch (Exception e)
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("No valid audio-event for " + encodedChunk);
return null;
}
}
public IChunk getAuralEvent(IAfferentObject auralEvent)
{
try
{
_lock.lock();
IChunk event = _existingIndexChunks.get(auralEvent.getIdentifier());
if (event == null && _auralPropertyHandler.hasModality(auralEvent))
{
if (LOGGER.isDebugEnabled())
LOGGER.debug(String.format(
"System missed the encoding of aural event %s, coding now",
auralEvent.getIdentifier()));
event = addIndex(auralEvent);
}
return event;
}
finally
{
_lock.unlock();
}
}
}