    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    }