001    package org.maltparser.core.syntaxgraph;
002    
003    import java.util.Iterator;
004    import java.util.NoSuchElementException;
005    import java.util.Set;
006    import java.util.SortedMap;
007    import java.util.SortedSet;
008    import java.util.TreeMap;
009    import java.util.TreeSet;
010    
011    import org.maltparser.core.exception.MaltChainedException;
012    import org.maltparser.core.pool.ObjectPoolList;
013    import org.maltparser.core.symbol.SymbolTableHandler;
014    import org.maltparser.core.syntaxgraph.edge.Edge;
015    import org.maltparser.core.syntaxgraph.edge.GraphEdge;
016    import org.maltparser.core.syntaxgraph.node.ComparableNode;
017    import org.maltparser.core.syntaxgraph.node.DependencyNode;
018    import org.maltparser.core.syntaxgraph.node.Node;
019    import org.maltparser.core.syntaxgraph.node.NonTerminal;
020    import org.maltparser.core.syntaxgraph.node.NonTerminalNode;
021    import org.maltparser.core.syntaxgraph.node.PhraseStructureNode;
022    import org.maltparser.core.syntaxgraph.node.Root;
023    import org.maltparser.core.syntaxgraph.node.TokenNode;
024    /**
025    *
026    *
027    * @author Johan Hall
028    */
029    public class PhraseStructureGraph extends Sentence implements PhraseStructure { 
030            protected final ObjectPoolList<Edge> edgePool;
031            protected final SortedSet<Edge> graphEdges;
032            protected final SortedMap<Integer, NonTerminal> nonTerminalNodes;
033            protected final ObjectPoolList<NonTerminal> nonTerminalPool;
034            protected final Root root;
035            
036            public PhraseStructureGraph(SymbolTableHandler symbolTables) throws MaltChainedException {
037                    super(symbolTables);
038    
039                    root = new Root();
040                    root.setBelongsToGraph(this);
041                    
042                    graphEdges = new TreeSet<Edge>();
043                    edgePool = new ObjectPoolList<Edge>() {
044                            protected Edge create() { return new GraphEdge(); }
045                            public void resetObject(Edge o) throws MaltChainedException { o.clear(); }
046                    };
047                    
048                    nonTerminalNodes = new TreeMap<Integer,NonTerminal>();
049                    nonTerminalPool = new ObjectPoolList<NonTerminal>() {
050                            protected NonTerminal create() throws MaltChainedException { return new NonTerminal(); }
051                            public void resetObject(NonTerminal o) throws MaltChainedException { o.clear(); }
052                    };
053            }
054            
055            public PhraseStructureNode addTerminalNode() throws MaltChainedException {
056                    return addTokenNode();
057            }
058            
059            public PhraseStructureNode addTerminalNode(int index) throws MaltChainedException {
060                    return addTokenNode(index);
061            }
062            
063            public PhraseStructureNode getTerminalNode(int index) {
064                    return getTokenNode(index);
065            }
066            
067            public int nTerminalNode() {
068                    return nTokenNode();
069            }
070            
071            public PhraseStructureNode addNonTerminalNode(int index) throws MaltChainedException {
072                    NonTerminal node = nonTerminalPool.checkOut();
073                    node.setIndex(index);
074                    node.setBelongsToGraph(this);
075                    nonTerminalNodes.put(index,node);
076                    return node;
077            }
078            
079            public PhraseStructureNode addNonTerminalNode() throws MaltChainedException {
080                    int index = getHighestNonTerminalIndex();
081                    if (index > 0) {
082                            return addNonTerminalNode(index+1);
083                    }
084                    return addNonTerminalNode(1);
085            }
086            
087            public PhraseStructureNode getNonTerminalNode(int index) throws MaltChainedException {
088                    return nonTerminalNodes.get(index);
089            }
090            
091            public int getHighestNonTerminalIndex() {
092                    try {
093                            return nonTerminalNodes.lastKey();
094                    } catch (NoSuchElementException e) {
095                            return 0;
096                    }
097            }
098            
099            public Set<Integer> getNonTerminalIndices() {
100                    return new TreeSet<Integer>(nonTerminalNodes.keySet());
101            }
102            
103            public boolean hasNonTerminals() {
104                    return !nonTerminalNodes.isEmpty();
105            }
106            
107            public int nNonTerminals() {
108                    return nonTerminalNodes.size();
109            }
110            
111            public PhraseStructureNode getPhraseStructureRoot() {
112                    return root;
113            }
114            
115            public Edge addPhraseStructureEdge(PhraseStructureNode parent, PhraseStructureNode child) throws MaltChainedException {
116                    if (parent == null || child == null) {
117                            throw new MaltChainedException("Parent or child node is missing.");
118                    } else if (parent instanceof NonTerminalNode && !child.isRoot()) {
119                            Edge e = edgePool.checkOut();
120                            e.setBelongsToGraph(this);
121                            e.setEdge((Node)parent, (Node)child, Edge.PHRASE_STRUCTURE_EDGE);
122                            graphEdges.add(e);
123                            return e;
124                    } else {
125                            throw new MaltChainedException("Parent or child node is not of correct node type.");
126                    }
127            }
128            
129            public void removePhraseStructureEdge(PhraseStructureNode parent, PhraseStructureNode child) throws MaltChainedException {
130                    if (parent == null || child == null) {
131                            throw new MaltChainedException("Parent or child node is missing.");
132                    } else if (parent instanceof NonTerminalNode && !child.isRoot()) {
133                            for (Edge e : graphEdges) {
134                                    if (e.getSource() == parent && e.getTarget() == child) {
135                                            e.clear();
136                                            graphEdges.remove(e);
137                                            if (e instanceof GraphEdge) {
138                                                    edgePool.checkIn(e);
139                                            }
140                                    }
141                            }
142                    } else {
143                            throw new SyntaxGraphException("Head node is not a root node or a terminal node.");
144                    }
145            }
146            
147            public Edge addSecondaryEdge(ComparableNode source, ComparableNode target) throws MaltChainedException {
148                    if (source == null || target == null) {
149                            throw new SyntaxGraphException("Head or dependent node is missing.");
150                    } else if (!target.isRoot()) {
151                            Edge e = edgePool.checkOut();
152                            e.setBelongsToGraph(this);
153                            e.setEdge((Node)source, (Node)target, Edge.SECONDARY_EDGE);
154                            graphEdges.add(e);
155                            return e;
156                    }
157                    return null;
158            }
159            
160            public void removeSecondaryEdge(ComparableNode source, ComparableNode target) throws MaltChainedException {
161                    if (source == null || target == null) {
162                            throw new SyntaxGraphException("Head or dependent node is missing.");
163                    } else if (!target.isRoot()) {
164                            Iterator<Edge> ie = ((Node)target).getIncomingEdgeIterator();
165                            while (ie.hasNext()) {
166                                    Edge e = ie.next();
167                                    if (e.getSource() == source) {
168                                            ie.remove();
169                                            graphEdges.remove(e);
170                                            edgePool.checkIn(e);
171                                    }
172                            }
173                    }
174            }
175            
176            public int nEdges() {
177                    return graphEdges.size();
178            }
179            
180            public SortedSet<Edge> getEdges() {
181                    return graphEdges;
182            }
183            
184            public boolean isContinuous() {
185                    for (int index : nonTerminalNodes.keySet()) {
186                            NonTerminalNode node = nonTerminalNodes.get(index);
187                            if (!node.isContinuous()) {
188                                    return false;
189                            }
190                    }
191                    return true;
192            }
193            
194            public boolean isContinuousExcludeTerminalsAttachToRoot() {
195                    for (int index : nonTerminalNodes.keySet()) {
196                            NonTerminalNode node = nonTerminalNodes.get(index);
197                            if (!node.isContinuousExcludeTerminalsAttachToRoot()) {
198                                    return false;
199                            }
200                    }
201                    return true;
202            }
203            
204    //      public void makeContinuous() throws MaltChainedException {
205    //              if (root != null) {
206    //                      root.reArrangeChildrenAccordingToLeftAndRightProperDesendant();
207    //              }
208    //      }
209            
210            public void clear() throws MaltChainedException {
211                    edgePool.checkInAll();
212                    graphEdges.clear();
213                    root.clear();
214                    root.setBelongsToGraph(this);
215                    nonTerminalPool.checkInAll();
216                    nonTerminalNodes.clear();
217                    super.clear();
218            }
219            
220            public String toStringTerminalNode(TokenNode node) {
221                    final StringBuilder sb = new StringBuilder();
222                    final DependencyNode depnode = node;
223    
224                    sb.append(node.toString().trim());
225                    if (depnode.hasHead()) {
226                            sb.append('\t');
227                            try {
228                                    sb.append(depnode.getHead().getIndex());
229                                    sb.append('\t');
230                                    sb.append(depnode.getHeadEdge().toString());
231                            } catch (MaltChainedException e) {
232                                    System.out.println(e);
233                            }
234                    }
235                    sb.append('\n');
236    
237                    return sb.toString();
238            }
239            
240            public String toStringNonTerminalNode(NonTerminalNode node) {
241                    final StringBuilder sb = new StringBuilder();
242    
243                    sb.append(node.toString().trim());
244                    sb.append('\n');
245                    Iterator<Edge> ie = ((Node)node).getOutgoingEdgeIterator();
246                    while (ie.hasNext()) {
247                            Edge e = ie.next();
248                            if (e.getTarget() instanceof TokenNode) {
249                                    sb.append("   T");
250                                    sb.append(e.getTarget().getIndex());
251                            }
252                            if (e.getTarget() instanceof NonTerminalNode) {
253                                    sb.append("   N");
254                                    sb.append(e.getTarget().getIndex());
255                            }
256                            sb.append('\t');
257                            sb.append(e.toString());
258                            sb.append('\n');
259                    }
260                    return sb.toString();
261            }
262            
263            public String toString() {
264                    final StringBuilder sb = new StringBuilder();
265                    for (int index : terminalNodes.keySet()) {
266                            sb.append(toStringTerminalNode(terminalNodes.get(index)));
267                    }
268                    sb.append('\n');
269                    sb.append(toStringNonTerminalNode((NonTerminalNode)getPhraseStructureRoot()));
270                    for (int index : nonTerminalNodes.keySet()) {
271                            sb.append(toStringNonTerminalNode(nonTerminalNodes.get(index)));
272                    }
273                    
274                    return sb.toString();
275            }
276    }