package ecologylab.bigsemantics.collecting;
import java.util.HashMap;
import java.util.Map;
import ecologylab.bigsemantics.actions.SemanticActionHandler;
import ecologylab.bigsemantics.metadata.Metadata;
import ecologylab.bigsemantics.metametadata.LinkWith;
import ecologylab.bigsemantics.metametadata.MetaMetadata;
import ecologylab.bigsemantics.metametadata.MetaMetadataCompositeField;
import ecologylab.bigsemantics.metametadata.MetaMetadataRepository;
/**
* Monitoring parsed metadata & composite fields for potential metadata links.
*
* @author quyin
*
*/
public class LinkedMetadataMonitor
{
/**
* map a monitored class name to a collection of monitor records, each of which corresponds to a
* metadata object.
*/
private Map<String, Map<Metadata, LinkWith>> monitorRecords = new HashMap<String, Map<Metadata, LinkWith>>();
/**
* Register a meta-metadata wrapper name for monitoring.
*
* @param name
* The monitored meta-metadata wrapper name.
*/
public void registerName(String name)
{
if (!monitorRecords.containsKey(name))
monitorRecords.put(name, new HashMap<Metadata, LinkWith>());
}
/**
* Add a monitor for a metadata object which has <link_with> defined in its meta-metadata.
*
* @param object
* The metadata object who wants to monitor a potential link.
*/
public void addMonitors(Metadata object)
{
if (object.getMetaMetadata() instanceof MetaMetadata)
{
MetaMetadata mmd = (MetaMetadata) object.getMetaMetadata();
Map<String, LinkWith> linkWiths = mmd.getLinkWiths();
if (linkWiths != null)
{
for (String name : linkWiths.keySet())
{
LinkWith lw = linkWiths.get(name);
Map<Metadata, LinkWith> collection = monitorRecords.get(lw.getName());
// collection can't be null
synchronized (collection)
{
collection.put(object, lw);
}
}
}
}
}
/**
* Remove a monitor for a metadata object.
*
* @param object
* The metadata object who wanted to monitor a link but don't now.
*/
public void removeMonitors(Metadata object)
{
if (object.getMetaMetadata() instanceof MetaMetadata)
{
MetaMetadata mmd = (MetaMetadata) object.getMetaMetadata();
Map<String, LinkWith> linkWiths = mmd.getLinkWiths();
if (linkWiths != null)
{
for (String name : linkWiths.keySet())
{
LinkWith lw = linkWiths.get(name);
Map<Metadata, LinkWith> collection = monitorRecords.get(lw.getName());
// collection can't be null
synchronized (collection)
{
collection.remove(object);
}
}
}
}
}
/**
* When a new metadata object is parsed, try to link it with some monitoring metadata objects that
* are waiting here.
*
* @param repository
* @param parsedMetadata
* @return If the linking happens.
*/
public boolean tryLink(MetaMetadataRepository repository, Metadata parsedMetadata)
{
if (parsedMetadata == null)
{
return false;
}
MetaMetadataCompositeField composite = parsedMetadata.getMetaMetadata();
if (composite == null)
{
return false;
}
MetaMetadata mmd;
String mmdName;
if (composite instanceof MetaMetadata)
{
mmd = (MetaMetadata) composite;
mmdName = mmd.getName();
}
else
{
mmdName = composite.getTypeName();
mmd = repository.getMMByName(mmdName);
}
if (mmd == null)
{
// maybe it's defined inline -- we need a solution for this kind of inline definition thing!
// currently you can't do metadata linking on inline-defined meta_metadata classes
return false;
}
while (!monitorRecords.containsKey(mmdName))
{
if (mmdName == null || "metadata".equals(mmdName))
return false;
mmdName = mmd.getSuperMmdTypeName();
mmd = repository.getMMByName(mmdName);
}
Map<Metadata, LinkWith> records = monitorRecords.get(mmdName);
for (Metadata object : records.keySet())
{
LinkWith lw = records.get(object);
if (lw.tryLink(parsedMetadata, object))
{
SemanticActionHandler handler = object.pendingSemanticActionHandler;
handler.takeSemanticActions();
return true;
}
}
return false;
}
}