package org.jactr.tools.analysis.production;
/*
* default logging
*/
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.Tree;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.buffer.BufferUtilities;
import org.jactr.io.antlr3.builder.JACTRBuilder;
import org.jactr.io.antlr3.misc.ASTSupport;
import org.jactr.io.antlr3.parser.xml.JACTRParser.declarativeMemory_return;
import org.jactr.tools.analysis.production.endstates.BufferEndState;
import org.jactr.tools.analysis.production.endstates.BufferEndStates;
import org.jactr.tools.analysis.production.endstates.IBufferEndStateComputer;
import org.jactr.tools.analysis.production.endstates.impl.BufferStateUtilities;
import org.jactr.tools.analysis.production.relationships.IRelationship;
import org.jactr.tools.analysis.production.relationships.IRelationshipComputer;
import org.jactr.tools.analysis.production.relationships.ProductionRelationships;
public class SequenceAnalyzer
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(SequenceAnalyzer.class);
/**
* tracks chunktypes (key) and all their children
*/
protected Map<String, Set<String>> _chunkTypeChildren;
protected Map<String, CommonTree> _chunkTypes;
protected Map<CommonTree, ProductionRelationships> _relationships;
protected Collection<IBufferEndStateComputer> _endStateComputers;
protected Collection<IRelationshipComputer> _relationshipComputers;
public SequenceAnalyzer()
{
_chunkTypeChildren = new TreeMap<String, Set<String>>();
_chunkTypes = new TreeMap<String, CommonTree>();
_relationships = new HashMap<CommonTree, ProductionRelationships>();
_endStateComputers = new ArrayList<IBufferEndStateComputer>();
_relationshipComputers = new ArrayList<IRelationshipComputer>();
}
public void reset()
{
_chunkTypeChildren.clear();
_relationships.clear();
}
public void add(IBufferEndStateComputer computer)
{
_endStateComputers.add(computer);
}
public void add(IRelationshipComputer computer)
{
_relationshipComputers.add(computer);
}
public ProductionRelationships getRelationships(CommonTree production)
{
return _relationships.get(production);
}
public Map<CommonTree, ProductionRelationships> getAllRelationships()
{
return new HashMap<CommonTree, ProductionRelationships>(_relationships);
}
/**
* we track all the chunktypes and their children so that we can check
* chunktype conditions
*
* @param chunkType
*/
public void addChunkType(CommonTree chunkType)
{
String chunkTypeName = ASTSupport.getName(chunkType).toLowerCase();
_chunkTypes.put(chunkTypeName, chunkType);
CommonTree parent = ASTSupport.getFirstDescendantWithType(chunkType,
JACTRBuilder.PARENT);
if (parent == null)
{
if (!_chunkTypeChildren.containsKey(chunkTypeName))
_chunkTypeChildren.put(chunkTypeName, new TreeSet<String>());
}
else
{
String parentName = parent.getText().toLowerCase();
if (!_chunkTypeChildren.containsKey(parentName))
_chunkTypeChildren.put(parentName, new TreeSet<String>());
_chunkTypeChildren.get(parentName).add(chunkTypeName);
}
}
public void addProduction(CommonTree production)
{
String productionName = ASTSupport.getName(production).toLowerCase();
BufferEndStates endStates = computeBufferEndStates(production);
ProductionRelationships relations = new ProductionRelationships(
productionName, endStates);
_relationships.put(production, relations);
for (Map.Entry<CommonTree, ProductionRelationships> entry : _relationships
.entrySet())
{
CommonTree other = entry.getKey();
ProductionRelationships otherRels = entry.getValue();
/*
* we compute the relationships in both directions, adding the
* relationships to each (but only once if we are comparing to ourselves)
*/
for (IRelationship relation : computeRelationship(production, other))
{
relations.addRelationship(relation);
// no need to add twice, we'll do it again below
if (production != other) otherRels.addRelationship(relation);
}
/*
* and the other direction
*/
for (IRelationship relation : computeRelationship(other, production))
{
relations.addRelationship(relation);
// no need to add twice, we already added above
if (production != other) otherRels.addRelationship(relation);
}
}
}
protected BufferEndStates computeBufferEndStates(CommonTree production)
{
String productionName = ASTSupport.getName(production);
Set<String> bufferConditionNames = new TreeSet<String>();
for (String bufferName : ASTSupport.getMapOfTrees(production,
JACTRBuilder.QUERY_CONDITION).keySet())
bufferConditionNames.add(bufferName);
for (String bufferName : ASTSupport.getMapOfTrees(production,
JACTRBuilder.MATCH_CONDITION).keySet())
bufferConditionNames.add(bufferName);
BufferEndStates endStates = new BufferEndStates(production);
/*
* we compute the buffer end states for each of the buffers checked in the
* lhs
*/
for (String bufferName : bufferConditionNames)
for (IBufferEndStateComputer computer : _endStateComputers)
for (BufferEndState endState : computer.computePossibleEndStatesFor(
endStates, bufferName, this))
{
if (LOGGER.isDebugEnabled())
LOGGER.debug(productionName + " end state for " + bufferName
+ " = " + endState);
endStates.addEndState(endState);
}
return endStates;
}
protected Collection<IRelationship> computeRelationship(CommonTree head,
CommonTree tail)
{
Collection<IRelationship> rtn = new ArrayList<IRelationship>();
for (IRelationshipComputer computer : _relationshipComputers)
{
IRelationship relationship = computer.computeRelationship(_relationships
.get(head).getEndStates(), _relationships.get(tail).getEndStates());
if (LOGGER.isDebugEnabled())
LOGGER.debug(ASTSupport.getName(head) + " " + relationship.getScore()
+ " " + ASTSupport.getName(tail));
rtn.add(relationship);
}
return rtn;
}
public Collection<CommonTree> getChunkTypeSlots(String chunkTypeName)
{
Map<String, CommonTree> slots = new TreeMap<String, CommonTree>();
while (chunkTypeName != null)
{
CommonTree chunkType = _chunkTypes.get(chunkTypeName.toLowerCase());
if (chunkType == null)
{
chunkTypeName = null;
continue;
}
/*
* snag the named slots contained in the first slots container in the
* chunk type. We cant just use getMapOfTrees(chunkType, SLOT) as that
* will traverse all the chunks too
*/
Map<String, CommonTree> cSlots = ASTSupport.getMapOfTrees(ASTSupport
.getFirstDescendantWithType(chunkType, JACTRBuilder.SLOTS),
JACTRBuilder.SLOT);
for (String slotName : cSlots.keySet())
if (!slots.containsKey(slotName))
{
CommonTree slot = cSlots.get(slotName);
String content = BufferStateUtilities.getContent(slot);
if (!content.equalsIgnoreCase("nil")
&& !content.equalsIgnoreCase("null"))
{
if (LOGGER.isDebugEnabled())
LOGGER.debug("chunk type " + chunkTypeName + " contributed "
+ slot.toStringTree());
slots.put(slotName, slot);
}
}
/*
* the second child, if it is a PARENT is the name of the parent
*/
Tree node = chunkType.getChild(1);
if (node.getType() == JACTRBuilder.PARENT)
chunkTypeName = node.getText();
else
chunkTypeName = null; // terminate
}
return slots.values();
}
}