001    package org.maltparser.core.syntaxgraph.node;
002    
003    
004    import java.util.NoSuchElementException;
005    import java.util.Set;
006    import java.util.SortedSet;
007    import java.util.TreeSet;
008    
009    import org.maltparser.core.exception.MaltChainedException;
010    import org.maltparser.core.helper.SystemLogger;
011    import org.maltparser.core.symbol.SymbolTable;
012    import org.maltparser.core.syntaxgraph.LabelSet;
013    import org.maltparser.core.syntaxgraph.SyntaxGraphException;
014    import org.maltparser.core.syntaxgraph.TokenStructure;
015    import org.maltparser.core.syntaxgraph.edge.Edge;
016    import org.maltparser.core.syntaxgraph.headrules.Direction;
017    import org.maltparser.core.syntaxgraph.headrules.HeadRules;
018    
019    
020    public class Root extends GraphNode implements DependencyNode, PhraseStructureNode, NonTerminalNode {
021            protected final SortedSet<DependencyNode> leftDependents;
022            protected final SortedSet<DependencyNode> rightDependents;
023            protected final SortedSet<PhraseStructureNode> children;
024    
025            /**
026             * a reference to a node where the node is part of a component. If the node is unconnected it will reference to it self. 
027             */
028            protected DependencyNode component;
029            protected int rank;
030            public Root() throws MaltChainedException {
031                    super();
032                    leftDependents = new TreeSet<DependencyNode>();
033                    rightDependents = new TreeSet<DependencyNode>();
034                    children = new TreeSet<PhraseStructureNode>();
035                    clear();
036            }
037            
038            public void addIncomingEdge(Edge in) throws MaltChainedException { 
039                    throw new SyntaxGraphException("It is not allowed for a root node to have an incoming edge");
040            }
041            
042            public void removeIncomingEdge(Edge in) { }
043    
044            public void addOutgoingEdge(Edge out) throws MaltChainedException {
045                    super.addOutgoingEdge(out);
046                    if (out.getTarget() != null) {
047                            if (out.getType() == Edge.DEPENDENCY_EDGE && out.getTarget() instanceof DependencyNode) {
048                                    Node dependent = out.getTarget();
049                                    if (compareTo(dependent) > 0) {
050                                            leftDependents.add((DependencyNode)dependent);
051                                    } else if (compareTo(dependent) < 0) {
052                                            rightDependents.add((DependencyNode)dependent);
053                                    }
054                            } else if (out.getType() == Edge.PHRASE_STRUCTURE_EDGE && out.getTarget() instanceof PhraseStructureNode) {
055                                    children.add((PhraseStructureNode)out.getTarget());
056                            }
057                    }
058            }
059            
060            public void removeOutgoingEdge(Edge out) throws MaltChainedException {
061                    super.removeOutgoingEdge(out);
062                    if (out.getTarget() != null) {
063                            if (out.getType() == Edge.DEPENDENCY_EDGE && out.getTarget() instanceof DependencyNode) {
064                                    Node dependent = out.getTarget();
065                                    if (compareTo(dependent) > 0) {
066                                            leftDependents.remove((DependencyNode)dependent);
067                                    } else if (compareTo(dependent) < 0) {
068                                            rightDependents.remove((DependencyNode)dependent);
069                                    }
070                            } else if (out.getType() == Edge.PHRASE_STRUCTURE_EDGE && out.getTarget() instanceof PhraseStructureNode) {
071                                    children.remove((PhraseStructureNode)out.getTarget());
072                            }
073                    }
074            }
075            
076            public DependencyNode getAncestor() throws MaltChainedException {
077                    return this;
078            }
079            
080            public DependencyNode getProperAncestor() throws MaltChainedException {
081                    return null;
082            }
083            
084            public int getRank() {
085                    return rank;
086            }
087            
088            public void setRank(int r) {
089                    this.rank = r;
090            }
091            
092            public DependencyNode findComponent() {
093                    return findComponent(this);
094            }
095            
096            private DependencyNode findComponent(DependencyNode x) {
097                    if (x != x.getComponent()) {
098                            x.setComponent(findComponent(x.getComponent()));
099                    }
100                    return x.getComponent();
101            }
102            
103            public DependencyNode getComponent() {
104                    return component;
105            }
106            
107            public void setComponent(DependencyNode x) {
108                    this.component = x;
109            }
110            
111            
112            public boolean isContinuous() {
113                    return true;
114            }
115            
116            public boolean isContinuousExcludeTerminalsAttachToRoot() {
117                    return true;
118            }
119            
120            public PhraseStructureNode getParent() {
121                    return null;
122            }
123            
124            public Edge getParentEdge() throws MaltChainedException {
125                    return null;
126            }
127            
128            public String getParentEdgeLabelSymbol(SymbolTable table) throws MaltChainedException {
129                    return null;
130            }
131            
132            public int getParentEdgeLabelCode(SymbolTable table) throws MaltChainedException {
133                    return -1;
134            }
135            
136            public boolean hasParentEdgeLabel(SymbolTable table) throws MaltChainedException {
137                    return false;
138            }
139            
140            public SortedSet<PhraseStructureNode> getChildren() {
141                    return new TreeSet<PhraseStructureNode>(children);
142            }
143    
144            public PhraseStructureNode getChild(int index) {
145                    if (index >= 0 && index < children.size()) {
146                            return children.toArray(new PhraseStructureNode[children.size()])[index];
147                    }
148                    return null;
149            }
150            
151            public PhraseStructureNode getLeftChild() {
152                    for (PhraseStructureNode node : children) {
153                            return node;
154                    }
155                    return null;
156            }
157            
158            public PhraseStructureNode getRightChild() {
159                    int n = children.size();
160                    int i = 1;
161                    for (PhraseStructureNode node : children) {
162                            if (i == n) {
163                                    return node;
164                            }
165                    }
166                    return null;
167            }
168            
169            public int nChildren() {
170                    return children.size();
171            }
172            
173            public boolean hasNonTerminalChildren() {
174                    for (PhraseStructureNode node : children) {
175                            if (node instanceof NonTerminal) {
176                                    return true;
177                            }
178                    }
179                    return false;
180            }
181            
182            public boolean hasTerminalChildren() {
183                    for (PhraseStructureNode node : children) {
184                            if (node instanceof Token) {
185                                    return true;
186                            }
187                    }
188                    return false;
189            }
190            
191            public int getHeight() {
192                    int max = -1;
193                    for (PhraseStructureNode node : children) {
194                            if (node instanceof Token) {
195                                    if (max < 0) {
196                                            max = 0;
197                                    }
198                            } else {
199                                    int nodeheight = ((NonTerminalNode)node).getHeight();
200                                    if (max < nodeheight) {
201                                            max = nodeheight;
202                                    }
203                            }
204                    }
205                    return max + 1;
206            }
207            
208            public TokenNode getLexicalHead(HeadRules headRules) throws MaltChainedException {
209                    return identifyHead(headRules);
210            }
211    
212            public PhraseStructureNode getHeadChild(HeadRules headRules) throws MaltChainedException {
213                    return identifyHeadChild(headRules);
214            }
215            
216            public TokenNode getLexicalHead() throws MaltChainedException {
217                    return identifyHead(null);
218            }
219    
220            public PhraseStructureNode getHeadChild() throws MaltChainedException {
221                    return identifyHeadChild(null);
222            }
223            
224            private PhraseStructureNode identifyHeadChild(HeadRules headRules) throws MaltChainedException {
225                    PhraseStructureNode headChild = (headRules == null)?null:headRules.getHeadChild(this);
226                    if (headChild == null) {
227                            Direction direction = (headRules == null)?Direction.LEFT:headRules.getDefaultDirection(this);
228                            if (direction == Direction.LEFT) {
229                                    if ((headChild = leftmostTerminalChild()) == null) {
230                                            headChild = leftmostNonTerminalChild();
231                                    }
232                            } else {
233                                    if ((headChild = rightmostTerminalChild()) == null) {
234                                            headChild = rightmostNonTerminalChild();
235                                    }
236                            }
237                    }
238                    return headChild;
239            }
240            
241            public TokenNode identifyHead(HeadRules headRules) throws MaltChainedException {
242                    PhraseStructureNode headChild = identifyHeadChild(headRules);
243                    TokenNode lexicalHead = null;
244                    if (headChild instanceof NonTerminalNode) {
245                            lexicalHead = ((NonTerminalNode)headChild).identifyHead(headRules);
246                    } else if (headChild instanceof TokenNode) {
247                            lexicalHead = (TokenNode)headChild;
248                    }
249                    for (PhraseStructureNode node : children) {
250                            if (node != headChild && node instanceof NonTerminalNode) {
251                                    ((NonTerminalNode)node).identifyHead(headRules);
252                            }
253                    }
254    
255                    return lexicalHead;
256            }
257            
258            private PhraseStructureNode leftmostTerminalChild() {
259                    for (PhraseStructureNode node : children) {
260                            if (node instanceof TokenNode) {
261                                    return node;
262                            }
263                    }
264                    return null;
265            }
266            
267            private PhraseStructureNode leftmostNonTerminalChild() {
268                    for (PhraseStructureNode node : children) {
269                            if (node instanceof NonTerminalNode) {
270                                    return node;
271                            }
272                    }
273                    return null;
274            }
275            
276            private PhraseStructureNode rightmostTerminalChild() {
277                    try {
278                            if (children.last() instanceof TokenNode) {
279                                    return children.last();
280                            }
281                    } catch (NoSuchElementException e) { }
282                    
283                    PhraseStructureNode candidate = null;
284                    for (PhraseStructureNode node : children) {
285                            if (node instanceof TokenNode) {
286                                    candidate = node;
287                            }
288                    }
289                    return candidate;
290            }
291            
292            private PhraseStructureNode rightmostNonTerminalChild() {
293                    try {
294                            if (children.last() instanceof NonTerminalNode) {
295                                    return children.last();
296                            }
297                    } catch (NoSuchElementException e) { }
298                    
299                    PhraseStructureNode candidate = null;
300                    for (PhraseStructureNode node : children) {
301                            if (node instanceof NonTerminalNode) {
302                                    candidate = node;
303                            }
304                    }
305                    return candidate;
306            }
307            
308            public boolean hasAtMostOneHead() {
309                    return true;
310            }
311            
312            public boolean hasAncestorInside(int left, int right) throws MaltChainedException {
313                    return false;
314            }
315            
316            public boolean hasHead() {
317                    return false;
318            }
319            
320            
321            public DependencyNode getHead() throws MaltChainedException {
322                    return null;
323            }
324            
325            public Edge getHeadEdge() throws MaltChainedException {
326                    return null;
327            }
328            
329            public void addHeadEdgeLabel(SymbolTable table, String symbol) throws MaltChainedException { }
330            
331            public void addHeadEdgeLabel(SymbolTable table, int code) throws MaltChainedException { }
332            
333            public void addHeadEdgeLabel(LabelSet labelSet) throws MaltChainedException { }
334            
335            public int getHeadEdgeLabelCode(SymbolTable table) throws MaltChainedException {
336                    return 0;
337            }
338    
339            public LabelSet getHeadEdgeLabelSet() throws MaltChainedException {
340                    return null;
341            }
342    
343    
344            public String getHeadEdgeLabelSymbol(SymbolTable table) throws MaltChainedException {
345                    return null;
346            }
347    
348            public Set<SymbolTable> getHeadEdgeLabelTypes() throws MaltChainedException {
349                    return null;
350            }
351    
352            public boolean hasHeadEdgeLabel(SymbolTable table) throws MaltChainedException {
353                    return false;
354            }
355    
356            public boolean isHeadEdgeLabeled() throws MaltChainedException {
357                    return false;
358            }
359    
360            public int nHeadEdgeLabels() throws MaltChainedException {
361                    return 0;
362            }
363    
364            public Set<Edge> getHeadEdges() throws MaltChainedException {
365                    return null;
366            }
367    
368            public Set<DependencyNode> getHeads() throws MaltChainedException {
369                    return null;
370            }
371    
372            public boolean hasDependent() {
373                    return hasLeftDependent() || hasRightDependent();
374            }
375            
376            /**
377             * Returns <code>true</code> if the node has one or more left dependents, otherwise <code>false</code>.
378             * 
379             * @return <code>true</code> if the node has one or more left dependents, otherwise <code>false</code>.
380             */
381            public boolean hasLeftDependent() {
382                    return !leftDependents.isEmpty();
383            }
384            
385            /**
386             * Returns the left dependent at the position <code>index</code>, where <code>index==0</code> equals the left most dependent.
387             * 
388             * @param index the index
389             * @return the left dependent at the position <code>index</code>, where <code>index==0</code> equals the left most dependent
390             */
391            public DependencyNode getLeftDependent(int index) {
392                    if (0 <= index && index < leftDependents.size()) {
393                            int i = 0;
394                            DependencyNode candidate = null;
395                            
396                            for (DependencyNode node : leftDependents) {
397                                    candidate = node;
398                                    if (i == index) {
399                                            return candidate;
400                                    }
401                                    i++;
402                            }
403                    }
404                    return null;
405            }
406            
407            /**
408             * Return the number of left dependents
409             * 
410             * @return the number of left dependents
411             */
412            public int getLeftDependentCount() {
413                    return leftDependents.size();
414            }
415            
416            public SortedSet<DependencyNode> getLeftDependents() {
417                    return leftDependents;
418            }
419            
420            /**
421             * Returns the left sibling if it exists, otherwise <code>null</code>
422             * 
423             * @return the left sibling if it exists, otherwise <code>null</code>
424             */
425            public DependencyNode getLeftSibling() throws MaltChainedException {
426                    return null;
427            }
428            
429            /**
430             * Returns the left sibling at the same side of head as the node it self. If not found <code>null</code is returned
431             * 
432             * @return the left sibling at the same side of head as the node it self. If not found <code>null</code is returned
433             */
434            public DependencyNode getSameSideLeftSibling() throws MaltChainedException {
435                    return null;
436            }
437            
438            /**
439             * Returns the closest left dependent to the node it self, if not found <code>null</code> is returned.
440             * 
441             * @return the closest left dependent to the node it self, if not found <code>null</code> is returned.
442             */
443            public DependencyNode getClosestLeftDependent() {
444                    try {
445                            return leftDependents.last();
446                    } catch (NoSuchElementException e) {
447                            return null;
448                    }
449            }
450            
451            public DependencyNode getLeftmostDependent() {
452                    for (DependencyNode dep : leftDependents) {
453                            return dep;
454                    }
455                    return null;
456    //              try {
457    //                      return leftDependents.first();
458    //              } catch (NoSuchElementException e) {
459    //                      return null;
460    //              }
461            }
462            
463            public DependencyNode getRightDependent(int index) {
464                    int size = rightDependents.size();
465                    if (index < size) {
466                            return rightDependents.toArray(new DependencyNode[size])[size - 1 - index];
467                    }
468                    return null;
469    //              if (0 <= index && index < rightDependents.size()) {
470    //                      int i = 0;
471    //                      DependencyNode candidate = null;
472    //                      
473    //                      for (DependencyNode node : rightDependents) {
474    //                              candidate = node;
475    //                              if (i == index) {
476    //                                      return candidate;
477    //                              }
478    //                              i++;
479    //                      }
480    //              }
481    //              return null;
482            }
483            
484            /**
485             * Return the number of right dependents
486             * 
487             * @return the number of right dependents
488             */
489            public int getRightDependentCount() {
490                    return rightDependents.size();
491            }
492            
493            public SortedSet<DependencyNode> getRightDependents() {
494                    return rightDependents;
495            }
496    
497            /**
498             * Returns the right sibling if it exists, otherwise <code>null</code>
499             * 
500             * @return the right sibling if it exists, otherwise <code>null</code>
501             */
502            public DependencyNode getRightSibling() throws MaltChainedException {
503                    return null;
504            }
505            
506            /**
507             * Returns the right sibling at the same side of head as the node it self. If not found <code>null</code is returned
508             * 
509             * @return the right sibling at the same side of head as the node it self. If not found <code>null</code is returned
510             */
511            public DependencyNode getSameSideRightSibling() throws MaltChainedException {
512                    return null;
513            }
514            
515            /**
516             * Returns the closest right dependent to the node it self, if not found <code>null</code> is returned.
517             * 
518             * @return the closest right dependent to the node it self, if not found <code>null</code> is returned.
519             */
520            public DependencyNode getClosestRightDependent() {
521                    for (DependencyNode dep : rightDependents) {
522                            return dep;
523                    }
524                    return null;
525    //              try {
526    //                      return rightDependents.first();
527    //              } catch (NoSuchElementException e) {
528    //                      return null;
529    //              }
530            }
531            
532            public DependencyNode getRightmostDependent() {
533                    int n = rightDependents.size();
534                    int i = 1;
535                    for (DependencyNode node : rightDependents) {
536                            if (i == n) {
537                                    return node;
538                            }
539                            i++;
540                    }
541                    return null;
542    //              try {
543    //                      return rightDependents.last();
544    //              } catch (NoSuchElementException e) {
545    //                      return null;
546    //              }
547            }
548            
549            /**
550             * Returns <code>true</code> if the node has one or more right dependents, otherwise <code>false</code>.
551             * 
552             * @return <code>true</code> if the node has one or more right dependents, otherwise <code>false</code>.
553             */
554            public boolean hasRightDependent() {
555                    return !rightDependents.isEmpty();
556            }
557    
558            protected void getDependencyDominationSet(SortedSet<DependencyNode> dominationSet) {
559                    if (leftDependents.size() > 0 || rightDependents.size() > 0) {
560                            dominationSet.addAll(leftDependents);
561                            dominationSet.addAll(rightDependents);
562                            
563                            for (DependencyNode node : leftDependents) {
564                                    ((Token)node).getDependencyDominationSet(dominationSet);
565                            }
566                            for (DependencyNode node : rightDependents) {
567                                    ((Token)node).getDependencyDominationSet(dominationSet);
568                            }
569                    }
570            }
571            
572    //      private SortedSet<DependencyNode> getDependencyDominationSet() {
573    //              SortedSet<DependencyNode> dominationSet = new TreeSet<DependencyNode>();
574    //              getDependencyDominationSet(dominationSet);
575    //              return dominationSet;
576    //      }
577            
578            public boolean isProjective() throws MaltChainedException {
579                    return true;
580            }
581            
582            public int getDependencyNodeDepth() throws MaltChainedException {
583                    return 0;
584            }
585            @Override
586            public int getIndex() {
587                    return 0;
588            }
589    
590            public int getCompareToIndex() {
591                    return 0;
592            }
593            
594            @Override
595            public boolean isRoot() {
596                    return true;
597            }
598            
599            public ComparableNode getLeftmostProperDescendant() throws MaltChainedException {
600                    NonTerminalNode node = this;
601                    ComparableNode candidate = null;
602                    while (node != null) {
603                            candidate = node.getLeftChild();
604                            if (candidate == null || candidate instanceof TokenNode) {
605                                    break;
606                            }
607                            node = (NonTerminalNode)candidate;
608                    }
609                    
610                    if (candidate == null && candidate instanceof NonTerminalNode) {
611                            candidate = null;
612                            DependencyNode dep = null;
613                            for (int index : ((TokenStructure)getBelongsToGraph()).getTokenIndices()) {
614                                    dep = ((TokenStructure)getBelongsToGraph()).getTokenNode(index);
615                                    while (dep != null) {
616                                            if (dep == this ) {
617                                                    return dep;
618                                            }
619                                            dep = dep.getHead();
620                                    }
621                            }
622                    }
623                    return candidate;       
624            }
625            
626            public ComparableNode getRightmostProperDescendant() throws MaltChainedException {
627                    NonTerminalNode node = this;
628                    ComparableNode candidate = null;
629                    while (node != null) {
630                            candidate = node.getRightChild();
631                            if (candidate == null || candidate instanceof TokenNode) {
632                                    break;
633                            }
634                            node = (NonTerminalNode)candidate;
635                    }
636                    if (candidate == null && candidate instanceof NonTerminalNode) {
637                            candidate = null;
638                            DependencyNode dep = null;
639                            for (int i = ((TokenStructure)getBelongsToGraph()).getHighestTokenIndex(); i > 0; i--) {
640                                    dep = ((TokenStructure)getBelongsToGraph()).getTokenNode(i);
641                                    while (dep != null) {
642                                            if (dep == this ) {
643                                                    return dep;
644                                            }
645                                            dep = dep.getHead();
646                                    }
647                            }
648                    }
649                    return candidate;
650            }
651            
652            public ComparableNode getLeftmostDescendant() throws MaltChainedException {
653                    return getLeftmostProperDescendant();
654            }
655            
656            public ComparableNode getRightmostDescendant() throws MaltChainedException {
657                    return getRightmostProperDescendant();
658            }
659            
660    //      public void reArrangeChildrenAccordingToLeftAndRightProperDesendant() throws MaltChainedException {
661    //              int i = 0;
662    //              int leftMostCorner = -1;
663    //              int leftMostCornerChildIndex = -1;
664    //              while (i < children.size()) {        
665    //                      if (leftMostCorner == -1) {
666    //                              leftMostCorner = getChild(i).getLeftmostProperDescendantIndex();
667    //                              leftMostCornerChildIndex = i;
668    //                      } else if (getChild(i) instanceof NonTerminal && getChild(i).getLeftmostProperDescendantIndex() < leftMostCorner) {
669    //                              NonTerminalNode child = (NonTerminal)getChild(i);
670    //                              PhraseStructureNode leftMostCornerChild = getChild(leftMostCornerChildIndex);
671    //                              if (leftMostCornerChild.getParent() != null) {
672    //                                      LabelSet labelSet = leftMostCornerChild.getParentEdge().getLabelSet();
673    //                                      ((PhraseStructure)getBelongsToGraph()).removePhraseStructureEdge(this, leftMostCornerChild);
674    //                                      Edge e = ((PhraseStructure)getBelongsToGraph()).addPhraseStructureEdge(child, leftMostCornerChild);
675    //                                      e.addLabel(labelSet);
676    //                              }
677    //                              child.reArrangeChildrenAccordingToLeftAndRightProperDesendant();
678    //                              i = -1;
679    //                              leftMostCorner = -1;
680    //                              leftMostCornerChildIndex = -1;
681    //                      } else {
682    //                              leftMostCorner = getChild(i).getLeftmostProperDescendantIndex();
683    //                              leftMostCornerChildIndex = i;
684    //                      }
685    //                      i++;
686    //              }
687    //
688    //              for (int j = 0, n=children.size(); j < n; j++) {
689    //                      if (getChild(j) instanceof NonTerminalNode) {
690    //                              ((NonTerminalNode)getChild(j)).reArrangeChildrenAccordingToLeftAndRightProperDesendant();
691    //                      }
692    //              }
693    //      }
694            
695            @Override
696            public void setIndex(int index) throws MaltChainedException { }
697            
698            public void clear() throws MaltChainedException {
699                    super.clear();
700                    component = this;
701                    rank = 0;
702                    leftDependents.clear();
703                    rightDependents.clear();
704                    children.clear();
705            }
706            
707            public int compareTo(ComparableNode o) {
708                    final int BEFORE = -1;
709                final int EQUAL = 0;
710                final int AFTER = 1;
711                if ( this == o ) return EQUAL;
712                try {
713                        final int thisLCorner = this.getLeftmostProperDescendantIndex();
714                        final int thatLCorner = (o instanceof TokenNode)?o.getCompareToIndex():o.getLeftmostProperDescendantIndex();
715                        final int thisRCorner = this.getRightmostProperDescendantIndex();
716                        final int thatRCorner = (o instanceof TokenNode)?o.getCompareToIndex():o.getRightmostProperDescendantIndex();
717    
718    //                  if (thisLCorner == -1 || thatLCorner == -1) {
719    //                          if (thisRCorner < thatRCorner) return BEFORE;
720    //                          if (thisRCorner > thatRCorner) return AFTER;
721    //                  }
722    //                  if (thisRCorner == -1 || thatRCorner == -1) {
723    //                          if (thisLCorner < thatLCorner) return BEFORE;
724    //                          if (thisLCorner > thatLCorner) return AFTER;
725    //                  }
726                        if (thisLCorner != -1 && thatLCorner != -1 && thisRCorner != -1 && thatRCorner != -1) {
727                                if (thisLCorner < thatLCorner && thisRCorner < thatRCorner) return BEFORE;
728                                if (thisLCorner > thatLCorner && thisRCorner > thatRCorner) return AFTER;
729                                if (thisLCorner > thatLCorner && thisRCorner < thatRCorner) return BEFORE;
730                                if (thisLCorner < thatLCorner && thisRCorner > thatRCorner) return AFTER;
731                        } else {
732                                if (thisLCorner != -1 && thatLCorner != -1) {
733                                        if (thisLCorner < thatLCorner) return BEFORE;
734                                        if (thisLCorner > thatLCorner) return AFTER;
735                                }
736                                if (thisRCorner != -1 && thatRCorner != -1) {
737                                        if (thisRCorner < thatRCorner) return BEFORE;
738                                        if (thisRCorner > thatRCorner) return AFTER;
739                                }
740                        }
741                    
742    //                  final int thisLCorner = this.getLeftmostDescendantIndex();
743    //                  final int thatLCorner = (o instanceof TerminalNode)?o.getCompareToIndex():o.getLeftmostDescendantIndex();
744    //                  final int thisRCorner = this.getRightmostDescendantIndex();
745    //                  final int thatRCorner = (o instanceof TerminalNode)?o.getCompareToIndex():o.getRightmostDescendantIndex();
746    //
747    //                  if (thisLCorner == -1 || thatLCorner == -1) {
748    //                          if (thisRCorner < thatRCorner) return BEFORE;
749    //                          if (thisRCorner > thatRCorner) return AFTER;
750    //                  }
751    //                  if (thisRCorner == -1 || thatRCorner == -1) {
752    //                          if (thisLCorner < thatLCorner) return BEFORE;
753    //                          if (thisLCorner > thatLCorner) return AFTER;
754    //                  }
755    //                  if (thisLCorner < thatLCorner && thisRCorner < thatRCorner) return BEFORE;
756    //                  if (thisLCorner > thatLCorner && thisRCorner > thatRCorner) return AFTER;
757    //                  if (thisLCorner > thatLCorner && thisRCorner < thatRCorner) return BEFORE;
758    //                  if (thisLCorner < thatLCorner && thisRCorner > thatRCorner) return AFTER;
759                    
760                    
761    //                  int thisCorner = this.getLeftmostDescendantIndex();
762    //                  int thatCorner = (o instanceof TerminalNode)?o.getCompareToIndex():o.getLeftmostDescendantIndex();
763    //                  if (thisCorner != -1 && thatCorner != -1) {
764    //                          if (thisCorner < thatCorner) return BEFORE;
765    //                          if (thisCorner > thatCorner) return AFTER;
766    //                  }
767    //                  thisCorner = this.getRightmostDescendantIndex();
768    //                  thatCorner = (o instanceof TerminalNode)?o.getCompareToIndex():o.getRightmostDescendantIndex();
769    //                  if (thisCorner != -1 && thatCorner != -1) {
770    //                          if (thisCorner < thatCorner) return BEFORE;
771    //                          if (thisCorner > thatCorner) return AFTER;
772    //                  }
773                    } catch (MaltChainedException e) {
774                            if (SystemLogger.logger().isDebugEnabled()) {
775                                    SystemLogger.logger().debug("",e);
776                            } else {
777                                    SystemLogger.logger().error(e.getMessageChain());
778                            }
779                            System.exit(1);
780                    }
781                if (0 < o.getCompareToIndex()) return BEFORE;
782                if (0 > o.getCompareToIndex()) return AFTER;
783                    return super.compareTo(o);
784    //              
785    //              if (o instanceof TerminalNode) {
786    //                      if (0 == o.getIndex()) {
787    //                              
788    //                      } else if (0 < o.getIndex()) {
789    //                              return -1;
790    //                      } else {
791    //                              return 1;
792    //                      }
793    //              } else if (o instanceof Root) {
794    //                      return super.compareTo(o);
795    //              } else if (o instanceof NonTerminalNode) {
796    //                      int lcorner = ((NonTerminalNode)o).getLeftCornerIndex();
797    //                      if (0 == lcorner) {
798    //                              int rcorner = ((NonTerminalNode)o).getRightCornerIndex();
799    //                              if (0 == rcorner) {
800    //                                      if (0 == o.getIndex()) {
801    //                                              return super.compareTo(o);
802    //                                      } else if (0 < o.getIndex()) {
803    //                                              return 1;
804    //                                      } else {
805    //                                              return -1;
806    //                                      }
807    //                              } else if (0 < rcorner) {
808    //                                      return -1;
809    //                              } else {
810    //                                      return 1;
811    //                              }
812    //                      } else if (0 < lcorner) {
813    //                              return -1;
814    //                      } else {
815    //                              return 1;
816    //                      }
817    //              }
818    //              return super.compareTo(o);
819            }
820            
821            public boolean equals(Object obj) {
822                    return super.equals(obj);
823            }
824            
825            public int hashCode() {
826                    return 31 * 7 + super.hashCode();
827            }
828            
829            public String toString() {
830                    StringBuilder sb = new StringBuilder();
831                    sb.append(super.toString());
832                    return sb.toString();
833            }
834    }