package org.maltparser.core.syntaxgraph;
import java.util.*;
import org.maltparser.core.exception.MaltChainedException;
import org.maltparser.core.pool.ObjectPoolList;
import org.maltparser.core.symbol.SymbolTableHandler;
import org.maltparser.core.syntaxgraph.edge.Edge;
import org.maltparser.core.syntaxgraph.edge.GraphEdge;
import org.maltparser.core.syntaxgraph.node.*;
/**
*
*
* @author Johan Hall
*/
public class PhraseStructureGraph extends Sentence implements PhraseStructure {
protected final ObjectPoolList<Edge> edgePool;
protected final SortedSet<Edge> graphEdges;
protected final SortedMap<Integer, NonTerminal> nonTerminalNodes;
protected final ObjectPoolList<NonTerminal> nonTerminalPool;
protected final Root root;
public PhraseStructureGraph(SymbolTableHandler symbolTables) throws MaltChainedException {
super(symbolTables);
root = new Root();
root.setBelongsToGraph(this);
graphEdges = new TreeSet<Edge>();
edgePool = new ObjectPoolList<Edge>() {
protected Edge create() {
return new GraphEdge();
}
public void resetObject(Edge o) throws MaltChainedException {
o.clear();
}
};
nonTerminalNodes = new TreeMap<Integer, NonTerminal>();
nonTerminalPool = new ObjectPoolList<NonTerminal>() {
protected NonTerminal create() throws MaltChainedException {
return new NonTerminal();
}
public void resetObject(NonTerminal o) throws MaltChainedException {
o.clear();
}
};
}
public PhraseStructureNode addTerminalNode() throws MaltChainedException {
return addTokenNode();
}
public PhraseStructureNode addTerminalNode(int index) throws MaltChainedException {
return addTokenNode(index);
}
public PhraseStructureNode getTerminalNode(int index) {
return getTokenNode(index);
}
public int nTerminalNode() {
return nTokenNode();
}
public PhraseStructureNode addNonTerminalNode(int index) throws MaltChainedException {
NonTerminal node = nonTerminalPool.checkOut();
node.setIndex(index);
node.setBelongsToGraph(this);
nonTerminalNodes.put(index, node);
return node;
}
public PhraseStructureNode addNonTerminalNode() throws MaltChainedException {
int index = getHighestNonTerminalIndex();
if (index > 0) {
return addNonTerminalNode(index + 1);
}
return addNonTerminalNode(1);
}
public PhraseStructureNode getNonTerminalNode(int index) throws MaltChainedException {
return nonTerminalNodes.get(index);
}
public int getHighestNonTerminalIndex() {
try {
return nonTerminalNodes.lastKey();
} catch (NoSuchElementException e) {
return 0;
}
}
public Set<Integer> getNonTerminalIndices() {
return new TreeSet<Integer>(nonTerminalNodes.keySet());
}
public boolean hasNonTerminals() {
return !nonTerminalNodes.isEmpty();
}
public int nNonTerminals() {
return nonTerminalNodes.size();
}
public PhraseStructureNode getPhraseStructureRoot() {
return root;
}
public Edge addPhraseStructureEdge(PhraseStructureNode parent, PhraseStructureNode child) throws MaltChainedException {
if (parent == null || child == null) {
throw new MaltChainedException("Parent or child node is missing.");
} else if (parent instanceof NonTerminalNode && !child.isRoot()) {
Edge e = edgePool.checkOut();
e.setBelongsToGraph(this);
e.setEdge((Node) parent, (Node) child, Edge.PHRASE_STRUCTURE_EDGE);
graphEdges.add(e);
return e;
} else {
throw new MaltChainedException("Parent or child node is not of correct node type.");
}
}
public void removePhraseStructureEdge(PhraseStructureNode parent, PhraseStructureNode child) throws MaltChainedException {
if (parent == null || child == null) {
throw new MaltChainedException("Parent or child node is missing.");
} else if (parent instanceof NonTerminalNode && !child.isRoot()) {
for (Edge e : graphEdges) {
if (e.getSource() == parent && e.getTarget() == child) {
e.clear();
graphEdges.remove(e);
if (e instanceof GraphEdge) {
edgePool.checkIn(e);
}
}
}
} else {
throw new SyntaxGraphException("Head node is not a root node or a terminal node.");
}
}
public Edge addSecondaryEdge(ComparableNode source, ComparableNode target) throws MaltChainedException {
if (source == null || target == null) {
throw new SyntaxGraphException("Head or dependent node is missing.");
} else if (!target.isRoot()) {
Edge e = edgePool.checkOut();
e.setBelongsToGraph(this);
e.setEdge((Node) source, (Node) target, Edge.SECONDARY_EDGE);
graphEdges.add(e);
return e;
}
return null;
}
public void removeSecondaryEdge(ComparableNode source, ComparableNode target) throws MaltChainedException {
if (source == null || target == null) {
throw new SyntaxGraphException("Head or dependent node is missing.");
} else if (!target.isRoot()) {
Iterator<Edge> ie = ((Node) target).getIncomingEdgeIterator();
while (ie.hasNext()) {
Edge e = ie.next();
if (e.getSource() == source) {
ie.remove();
graphEdges.remove(e);
edgePool.checkIn(e);
}
}
}
}
public int nEdges() {
return graphEdges.size();
}
public SortedSet<Edge> getEdges() {
return graphEdges;
}
public boolean isContinuous() {
for (int index : nonTerminalNodes.keySet()) {
NonTerminalNode node = nonTerminalNodes.get(index);
if (!node.isContinuous()) {
return false;
}
}
return true;
}
public boolean isContinuousExcludeTerminalsAttachToRoot() {
for (int index : nonTerminalNodes.keySet()) {
NonTerminalNode node = nonTerminalNodes.get(index);
if (!node.isContinuousExcludeTerminalsAttachToRoot()) {
return false;
}
}
return true;
}
// public void makeContinuous() throws MaltChainedException {
// if (root != null) {
// root.reArrangeChildrenAccordingToLeftAndRightProperDesendant();
// }
// }
@Override
public void clear() throws MaltChainedException {
edgePool.checkInAll();
graphEdges.clear();
root.clear();
root.setBelongsToGraph(this);
nonTerminalPool.checkInAll();
nonTerminalNodes.clear();
super.clear();
}
public String toStringTerminalNode(TokenNode node) {
final StringBuilder sb = new StringBuilder();
final DependencyNode depnode = node;
sb.append(node.toString().trim());
if (depnode.hasHead()) {
sb.append('\t');
try {
sb.append(depnode.getHead().getIndex());
sb.append('\t');
sb.append(depnode.getHeadEdge().toString());
} catch (MaltChainedException e) {
System.err.println(e);
}
}
sb.append('\n');
return sb.toString();
}
public String toStringNonTerminalNode(NonTerminalNode node) {
final StringBuilder sb = new StringBuilder();
sb.append(node.toString().trim());
sb.append('\n');
Iterator<Edge> ie = ((Node) node).getOutgoingEdgeIterator();
while (ie.hasNext()) {
Edge e = ie.next();
if (e.getTarget() instanceof TokenNode) {
sb.append(" T");
sb.append(e.getTarget().getIndex());
}
if (e.getTarget() instanceof NonTerminalNode) {
sb.append(" N");
sb.append(e.getTarget().getIndex());
}
sb.append('\t');
sb.append(e.toString());
sb.append('\n');
}
return sb.toString();
}
@Override
public String toString() {
final StringBuilder sb = new StringBuilder();
for (int index : terminalNodes.keySet()) {
sb.append(toStringTerminalNode(terminalNodes.get(index)));
}
sb.append('\n');
sb.append(toStringNonTerminalNode((NonTerminalNode) getPhraseStructureRoot()));
for (int index : nonTerminalNodes.keySet()) {
sb.append(toStringNonTerminalNode(nonTerminalNodes.get(index)));
}
return sb.toString();
}
}