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 }