001 package org.maltparser.core.syntaxgraph.node; 002 003 import java.util.NoSuchElementException; 004 import java.util.Set; 005 import java.util.SortedSet; 006 import java.util.TreeSet; 007 008 import org.maltparser.core.exception.MaltChainedException; 009 import org.maltparser.core.helper.SystemLogger; 010 import org.maltparser.core.symbol.SymbolTable; 011 import org.maltparser.core.syntaxgraph.LabelSet; 012 import org.maltparser.core.syntaxgraph.SyntaxGraphException; 013 import org.maltparser.core.syntaxgraph.edge.Edge; 014 015 016 public class Token extends GraphNode implements TokenNode, DependencyNode, PhraseStructureNode { 017 /** 018 * the previous terminal node in the linear precedence 019 */ 020 protected TokenNode predecessor = null; 021 /** 022 * the next terminal node in the linear precedence 023 */ 024 protected TokenNode successor = null; 025 026 /** 027 * a reference to a node where the node is part of a component. If the node is unconnected it will reference to it self. 028 */ 029 protected DependencyNode component; 030 protected int rank; 031 032 protected int index; 033 034 protected PhraseStructureNode parent; 035 protected final SortedSet<DependencyNode> heads; 036 protected final SortedSet<DependencyNode> leftDependents; 037 protected final SortedSet<DependencyNode> rightDependents; 038 039 040 public Token() throws MaltChainedException { 041 parent = null; 042 heads = new TreeSet<DependencyNode>(); 043 leftDependents = new TreeSet<DependencyNode>(); 044 rightDependents = new TreeSet<DependencyNode>(); 045 clear(); 046 } 047 048 /** 049 * Sets the predecessor terminal node in the linear order of the terminal nodes. 050 * 051 * @param predecessor the predecessor terminal node 052 */ 053 public void setPredecessor(TokenNode predecessor) { 054 this.predecessor = predecessor; 055 } 056 057 /** 058 * Sets the predecessor terminal node in the linear order of the terminal nodes. 059 * 060 * @param successor the successor terminal node 061 */ 062 public void setSuccessor(TokenNode successor) { 063 this.successor = successor; 064 } 065 066 /** 067 * Returns the predecessor terminal node in the linear order of the terminal nodes. 068 * 069 * @return the predecessor terminal node in the linear order of the terminal nodes. 070 */ 071 public TokenNode getPredecessor() { 072 return predecessor; 073 } 074 075 /** 076 * Returns the successor terminal node in the linear order of the terminal nodes. 077 * 078 * @return the successor terminal node in the linear order of the terminal nodes. 079 */ 080 public TokenNode getSuccessor() { 081 return successor; 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 public void addIncomingEdge(Edge in) throws MaltChainedException { 112 super.addIncomingEdge(in); 113 if (in.getSource() != null) { 114 if (in.getType() == Edge.DEPENDENCY_EDGE && in.getSource() instanceof DependencyNode) { 115 heads.add((DependencyNode)in.getSource()); 116 } else if (in.getType() == Edge.PHRASE_STRUCTURE_EDGE && in.getSource() instanceof PhraseStructureNode) { 117 parent = (PhraseStructureNode)in.getSource(); 118 } 119 } 120 } 121 122 public void removeIncomingEdge(Edge in) throws MaltChainedException { 123 super.removeIncomingEdge(in); 124 if (in.getSource() != null) { 125 if (in.getType() == Edge.DEPENDENCY_EDGE && in.getSource() instanceof DependencyNode) { 126 heads.remove((DependencyNode)in.getSource()); 127 } else if (in.getType() == Edge.PHRASE_STRUCTURE_EDGE && in.getSource() instanceof PhraseStructureNode) { 128 if (in.getSource() == parent) { 129 this.parent = null; 130 } 131 } 132 } 133 } 134 135 public void addOutgoingEdge(Edge out) throws MaltChainedException { 136 super.addOutgoingEdge(out); 137 if (out.getType() == Edge.DEPENDENCY_EDGE && out.getTarget() instanceof DependencyNode) { 138 final DependencyNode dependent = (DependencyNode)out.getTarget(); 139 if (compareTo(dependent) > 0) { 140 leftDependents.add((DependencyNode)dependent); 141 } else if (compareTo(dependent) < 0) { 142 rightDependents.add((DependencyNode)dependent); 143 } 144 } 145 } 146 147 public void removeOutgoingEdge(Edge out) throws MaltChainedException { 148 super.removeOutgoingEdge(out); 149 if (out.getType() == Edge.DEPENDENCY_EDGE && out.getTarget() instanceof DependencyNode) { 150 final DependencyNode dependent = (DependencyNode)out.getTarget(); 151 if (compareTo(dependent) > 0) { 152 leftDependents.remove((DependencyNode)dependent); 153 } else if (compareTo(dependent) < 0) { 154 rightDependents.remove((DependencyNode)dependent); 155 } 156 } 157 } 158 159 public void setIndex(int index) throws MaltChainedException { 160 if (index > 0) { 161 this.index = index; 162 } else { 163 throw new SyntaxGraphException("A terminal node must have a positive integer value and not index "+index+". "); 164 } 165 } 166 167 public int getIndex() { 168 return index; 169 } 170 171 public int getCompareToIndex() { 172 return index; 173 } 174 175 public boolean isRoot() { 176 return false; 177 } 178 179 public DependencyNode getAncestor() throws MaltChainedException { 180 if (!this.hasHead()) { 181 return this; 182 } 183 184 DependencyNode tmp = this; 185 while (tmp.hasHead()) { 186 tmp = tmp.getHead(); 187 } 188 return tmp; 189 } 190 191 public DependencyNode getProperAncestor() throws MaltChainedException { 192 if (!this.hasHead()) { 193 return null; 194 } 195 196 DependencyNode tmp = this; 197 while (tmp.hasHead()) { 198 tmp = tmp.getHead(); 199 } 200 return tmp; 201 } 202 203 public ComparableNode getLeftmostProperDescendant() throws MaltChainedException { 204 ComparableNode candidate = null; 205 ComparableNode tmp = null; 206 for (DependencyNode ldep : leftDependents) { 207 if (candidate == null) { 208 candidate = ldep; 209 } else if (ldep.getIndex() < candidate.getIndex() ) { 210 candidate = ldep; 211 } 212 tmp = ((Token)ldep).getLeftmostProperDescendant(); 213 if (tmp == null) { 214 continue; 215 } 216 if (candidate == null) { 217 candidate = tmp; 218 } else if (tmp.getIndex() < candidate.getIndex() ) { 219 candidate = tmp; 220 } 221 if (candidate.getIndex() == 1) { 222 return candidate; 223 } 224 } 225 for (DependencyNode rdep : rightDependents) { 226 if (candidate == null) { 227 candidate = rdep; 228 } else if (rdep.getIndex() < candidate.getIndex() ) { 229 candidate = rdep; 230 } 231 tmp = ((Token)rdep).getLeftmostProperDescendant(); 232 if (tmp == null) { 233 continue; 234 } 235 if (candidate == null) { 236 candidate = tmp; 237 } else if (tmp.getIndex() < candidate.getIndex() ) { 238 candidate = tmp; 239 } 240 if (candidate.getIndex() == 1) { 241 return candidate; 242 } 243 } 244 return candidate; 245 } 246 247 public ComparableNode getRightmostProperDescendant() throws MaltChainedException { 248 ComparableNode candidate = null; 249 ComparableNode tmp = null; 250 for (DependencyNode ldep : leftDependents) { 251 if (candidate == null) { 252 candidate = ldep; 253 } else if (ldep.getIndex() > candidate.getIndex() ) { 254 candidate = ldep; 255 } 256 tmp = ((Token)ldep).getRightmostProperDescendant(); 257 if (tmp == null) { 258 continue; 259 } 260 if (candidate == null) { 261 candidate = tmp; 262 } else if (tmp.getIndex() > candidate.getIndex() ) { 263 candidate = tmp; 264 } 265 } 266 for (DependencyNode rdep : rightDependents) { 267 if (candidate == null) { 268 candidate = rdep; 269 } else if (rdep.getIndex() > candidate.getIndex() ) { 270 candidate = rdep; 271 } 272 tmp = ((Token)rdep).getRightmostProperDescendant(); 273 if (tmp == null) { 274 continue; 275 } 276 if (candidate == null) { 277 candidate = tmp; 278 } else if (tmp.getIndex() > candidate.getIndex() ) { 279 candidate = tmp; 280 } 281 } 282 return candidate; 283 } 284 285 public ComparableNode getLeftmostDescendant() throws MaltChainedException { 286 ComparableNode candidate = this; 287 ComparableNode tmp = null; 288 for (DependencyNode ldep : leftDependents) { 289 if (candidate == null) { 290 candidate = ldep; 291 } else if (ldep.getIndex() < candidate.getIndex() ) { 292 candidate = ldep; 293 } 294 tmp = ((Token)ldep).getLeftmostDescendant(); 295 if (tmp == null) { 296 continue; 297 } 298 if (candidate == null) { 299 candidate = tmp; 300 } else if (tmp.getIndex() < candidate.getIndex() ) { 301 candidate = tmp; 302 } 303 if (candidate.getIndex() == 1) { 304 return candidate; 305 } 306 } 307 for (DependencyNode rdep : rightDependents) { 308 if (candidate == null) { 309 candidate = rdep; 310 } else if (rdep.getIndex() < candidate.getIndex() ) { 311 candidate = rdep; 312 } 313 tmp = ((Token)rdep).getLeftmostDescendant(); 314 if (tmp == null) { 315 continue; 316 } 317 if (candidate == null) { 318 candidate = tmp; 319 } else if (tmp.getIndex() < candidate.getIndex() ) { 320 candidate = tmp; 321 } 322 if (candidate.getIndex() == 1) { 323 return candidate; 324 } 325 } 326 return candidate; 327 } 328 329 public ComparableNode getRightmostDescendant() throws MaltChainedException { 330 ComparableNode candidate = this; 331 ComparableNode tmp = null; 332 for (DependencyNode ldep : leftDependents) { 333 if (candidate == null) { 334 candidate = ldep; 335 } else if (ldep.getIndex() > candidate.getIndex() ) { 336 candidate = ldep; 337 } 338 tmp = ((Token)ldep).getRightmostDescendant(); 339 if (tmp == null) { 340 continue; 341 } 342 if (candidate == null) { 343 candidate = tmp; 344 } else if (tmp.getIndex() > candidate.getIndex() ) { 345 candidate = tmp; 346 } 347 } 348 for (DependencyNode rdep : rightDependents) { 349 if (candidate == null) { 350 candidate = rdep; 351 } else if (rdep.getIndex() > candidate.getIndex() ) { 352 candidate = rdep; 353 } 354 tmp = ((Token)rdep).getRightmostDescendant(); 355 if (tmp == null) { 356 continue; 357 } 358 if (candidate == null) { 359 candidate = tmp; 360 } else if (tmp.getIndex() > candidate.getIndex() ) { 361 candidate = tmp; 362 } 363 } 364 return candidate; 365 } 366 367 public PhraseStructureNode getParent() { 368 return parent; 369 } 370 371 public Edge getParentEdge() throws MaltChainedException { 372 for (Edge e : incomingEdges) { 373 if (e.getSource() == parent && e.getType() == Edge.PHRASE_STRUCTURE_EDGE) { 374 return e; 375 } 376 } 377 return null; 378 } 379 380 public String getParentEdgeLabelSymbol(SymbolTable table) throws MaltChainedException { 381 for (Edge e : incomingEdges) { 382 if (e.getSource() == parent && e.getType() == Edge.PHRASE_STRUCTURE_EDGE) { 383 return e.getLabelSymbol(table); 384 } 385 } 386 return null; 387 } 388 389 public int getParentEdgeLabelCode(SymbolTable table) throws MaltChainedException { 390 for (Edge e : incomingEdges) { 391 if (e.getSource() == parent && e.getType() == Edge.PHRASE_STRUCTURE_EDGE) { 392 return e.getLabelCode(table); 393 } 394 } 395 return -1; 396 } 397 398 public boolean hasParentEdgeLabel(SymbolTable table) throws MaltChainedException { 399 for (Edge e : incomingEdges) { 400 if (e.getSource() == parent && e.getType() == Edge.PHRASE_STRUCTURE_EDGE) { 401 return e.hasLabel(table); 402 } 403 } 404 return false; 405 } 406 407 public boolean hasAtMostOneHead() { 408 return heads.size() <= 1; 409 } 410 411 public boolean hasAncestorInside(int left, int right) throws MaltChainedException { 412 DependencyNode tmp = this; 413 if (tmp.getHead() != null) { 414 tmp = tmp.getHead(); 415 if (tmp.getIndex() >= left && tmp.getIndex() <= right) { 416 return true; 417 } 418 } 419 return false; 420 } 421 422 public Set<Edge> getHeadEdges() throws MaltChainedException { 423 return incomingEdges; 424 } 425 426 public Set<DependencyNode> getHeads() throws MaltChainedException { 427 return heads; 428 } 429 430 public boolean hasHead() { 431 return heads.size() != 0; 432 } 433 434 public DependencyNode getHead() throws MaltChainedException { 435 if (!hasHead()) { 436 return null; 437 } 438 if (heads.size() > 1) { 439 throw new SyntaxGraphException("The dependency node is multi-headed and it is ambigious to return a single-head dependency node. "); 440 } 441 // heads.first(); 442 for (DependencyNode head : heads) { 443 return head; 444 } 445 return null; 446 } 447 448 public Edge getHeadEdge() throws MaltChainedException { 449 if (heads.size() == 0) { 450 return null; 451 } 452 if (incomingEdges.size() == 1 && incomingEdges.first() instanceof DependencyNode) { 453 return incomingEdges.first(); 454 } 455 if (heads.size() == 1) { 456 for (Edge e : incomingEdges) { 457 if (e.getSource() == heads.first()) { 458 return e; 459 } 460 } 461 } 462 return null; 463 } 464 465 public void addHeadEdgeLabel(SymbolTable table, String symbol) throws MaltChainedException { 466 if (hasHead()) { 467 getHeadEdge().addLabel(table, symbol); 468 } 469 } 470 471 public void addHeadEdgeLabel(SymbolTable table, int code) throws MaltChainedException { 472 if (hasHead()) { 473 getHeadEdge().addLabel(table, code); 474 } 475 } 476 477 public void addHeadEdgeLabel(LabelSet labelSet) throws MaltChainedException { 478 if (hasHead()) { 479 getHeadEdge().addLabel(labelSet); 480 } 481 } 482 483 public boolean hasHeadEdgeLabel(SymbolTable table) throws MaltChainedException { 484 if (!hasHead()) { 485 return false; 486 } 487 return getHeadEdge().hasLabel(table); 488 } 489 490 public String getHeadEdgeLabelSymbol(SymbolTable table) throws MaltChainedException { 491 return getHeadEdge().getLabelSymbol(table); 492 } 493 494 public int getHeadEdgeLabelCode(SymbolTable table) throws MaltChainedException { 495 if (!hasHead()) { 496 return 0; 497 } 498 return getHeadEdge().getLabelCode(table); 499 } 500 501 public boolean isHeadEdgeLabeled() throws MaltChainedException { 502 if (!hasHead()) { 503 return false; 504 } 505 return getHeadEdge().isLabeled(); 506 } 507 508 public int nHeadEdgeLabels() throws MaltChainedException { 509 if (!hasHead()) { 510 return 0; 511 } 512 return getHeadEdge().nLabels(); 513 } 514 515 public Set<SymbolTable> getHeadEdgeLabelTypes() throws MaltChainedException { 516 return getHeadEdge().getLabelTypes(); 517 } 518 519 public LabelSet getHeadEdgeLabelSet() throws MaltChainedException { 520 return getHeadEdge().getLabelSet(); 521 } 522 523 public boolean hasDependent() { 524 return hasLeftDependent() || hasRightDependent(); 525 } 526 527 /** 528 * Returns <code>true</code> if the node has one or more left dependents, otherwise <code>false</code>. 529 * 530 * @return <code>true</code> if the node has one or more left dependents, otherwise <code>false</code>. 531 */ 532 public boolean hasLeftDependent() { 533 return !leftDependents.isEmpty(); 534 } 535 536 /** 537 * Returns the left dependent at the position <code>index</code>, where <code>index==0</code> equals the left most dependent. 538 * 539 * @param index the index 540 * @return the left dependent at the position <code>index</code>, where <code>index==0</code> equals the left most dependent 541 */ 542 public DependencyNode getLeftDependent(int index) { 543 if (0 <= index && index < leftDependents.size()) { 544 int i = 0; 545 DependencyNode candidate = null; 546 547 for (DependencyNode node : leftDependents) { 548 candidate = node; 549 if (i == index) { 550 return candidate; 551 } 552 i++; 553 } 554 } 555 return null; 556 } 557 558 /** 559 * Return the number of left dependents 560 * 561 * @return the number of left dependents 562 */ 563 public int getLeftDependentCount() { 564 return leftDependents.size(); 565 } 566 567 public SortedSet<DependencyNode> getLeftDependents() { 568 return leftDependents; 569 } 570 571 /** 572 * Returns the left sibling if it exists, otherwise <code>null</code> 573 * 574 * @return the left sibling if it exists, otherwise <code>null</code> 575 */ 576 public DependencyNode getLeftSibling() throws MaltChainedException { 577 if (getHead() == null) { 578 return null; 579 } 580 581 DependencyNode candidate = null; 582 for (DependencyNode node : getHead().getLeftDependents()) { 583 if (node == this) { 584 return candidate; 585 } 586 candidate = node; 587 } 588 for (DependencyNode node : getHead().getRightDependents()) { 589 if (node == this) { 590 return candidate; 591 } 592 candidate = node; 593 } 594 return null; 595 } 596 597 /** 598 * Returns the left sibling at the same side of head as the node it self. If not found <code>null</code is returned 599 * 600 * @return the left sibling at the same side of head as the node it self. If not found <code>null</code is returned 601 */ 602 public DependencyNode getSameSideLeftSibling() throws MaltChainedException { 603 if (getHead() == null) { 604 return null; 605 } else if (this.getIndex() < getHead().getIndex()) { 606 try { 607 return getHead().getLeftDependents().headSet(this).last(); 608 } catch (NoSuchElementException e) { 609 return null; 610 } 611 } else if (this.getIndex() > getHead().getIndex()) { 612 try { 613 return getHead().getRightDependents().headSet(this).last(); 614 } catch (NoSuchElementException e) { 615 return null; 616 } 617 } 618 return null; 619 } 620 621 /** 622 * Returns the closest left dependent to the node it self, if not found <code>null</code> is returned. 623 * 624 * @return the closest left dependent to the node it self, if not found <code>null</code> is returned. 625 */ 626 public DependencyNode getClosestLeftDependent() { 627 try { 628 return leftDependents.last(); 629 } catch (NoSuchElementException e) { 630 return null; 631 } 632 } 633 634 public DependencyNode getLeftmostDependent() { 635 for (DependencyNode dep : leftDependents) { 636 return dep; 637 } 638 return null; 639 // try { 640 // return leftDependents.first(); 641 // } catch (NoSuchElementException e) { 642 // return null; 643 // } 644 } 645 646 public DependencyNode getRightDependent(int index) { 647 int size = rightDependents.size(); 648 if (index < size) { 649 return rightDependents.toArray(new DependencyNode[size])[size - 1 - index]; 650 } 651 return null; 652 // if (0 <= index && index < rightDependents.size()) { 653 // int i = 0; 654 // DependencyNode candidate = null; 655 // 656 // for (DependencyNode node : rightDependents) { 657 // candidate = node; 658 // if (i == index) { 659 // return candidate; 660 // } 661 // i++; 662 // } 663 // } 664 // return null; 665 } 666 667 /** 668 * Return the number of right dependents 669 * 670 * @return the number of right dependents 671 */ 672 public int getRightDependentCount() { 673 return rightDependents.size(); 674 } 675 676 /** 677 * Returns a sorted set of right dependents. 678 * 679 * @return a sorted set of right dependents. 680 */ 681 public SortedSet<DependencyNode> getRightDependents() { 682 return rightDependents; 683 } 684 685 /** 686 * Returns the right sibling if it exists, otherwise <code>null</code> 687 * 688 * @return the right sibling if it exists, otherwise <code>null</code> 689 */ 690 public DependencyNode getRightSibling() throws MaltChainedException { 691 if (getHead() == null) { 692 return null; 693 } 694 695 for (DependencyNode node : getHead().getLeftDependents()) { 696 if (node.getIndex() > this.getIndex()) { 697 return node; 698 } 699 } 700 for (DependencyNode node : getHead().getRightDependents()) { 701 if (node.getIndex() > this.getIndex()) { 702 return node; 703 } 704 } 705 return null; 706 } 707 708 /** 709 * Returns the right sibling at the same side of head as the node it self. If not found <code>null</code is returned 710 * 711 * @return the right sibling at the same side of head as the node it self. If not found <code>null</code is returned 712 */ 713 public DependencyNode getSameSideRightSibling() throws MaltChainedException { 714 if (getHead() == null) { 715 return null; 716 } else if (this.getIndex() < getHead().getIndex()) { 717 final SortedSet<DependencyNode> tailSet = getHead().getLeftDependents().tailSet(this); 718 if (tailSet.size() <= 1) { 719 return null; 720 } 721 return tailSet.toArray(new DependencyNode[tailSet.size()])[1]; 722 } else if (this.getIndex() > getHead().getIndex()) { 723 final SortedSet<DependencyNode> tailSet = getHead().getRightDependents().tailSet(this); 724 if (tailSet.size() <= 1) { 725 return null; 726 } 727 return tailSet.toArray(new DependencyNode[tailSet.size()])[1]; 728 } 729 return null; 730 } 731 732 /** 733 * Returns the closest right dependent to the node it self, if not found <code>null</code> is returned. 734 * 735 * @return the closest right dependent to the node it self, if not found <code>null</code> is returned. 736 */ 737 public DependencyNode getClosestRightDependent() { 738 for (DependencyNode dep : rightDependents) { 739 return dep; 740 } 741 return null; 742 // try { 743 // return rightDependents.first(); 744 // } catch (NoSuchElementException e) { 745 // return null; 746 // } 747 } 748 749 public DependencyNode getRightmostDependent() { 750 int n = rightDependents.size(); 751 int i = 1; 752 for (DependencyNode node : rightDependents) { 753 if (i == n) { 754 return node; 755 } 756 i++; 757 } 758 return null; 759 // try { 760 // return rightDependents.last(); 761 // } catch (NoSuchElementException e) { 762 // return null; 763 // } 764 } 765 766 protected void getDependencyDominationSet(SortedSet<DependencyNode> dominationSet) { 767 if (leftDependents.size() > 0 || rightDependents.size() > 0) { 768 dominationSet.addAll(leftDependents); 769 dominationSet.addAll(rightDependents); 770 771 for (DependencyNode node : leftDependents) { 772 ((Token)node).getDependencyDominationSet(dominationSet); 773 } 774 for (DependencyNode node : rightDependents) { 775 ((Token)node).getDependencyDominationSet(dominationSet); 776 } 777 } 778 } 779 780 // private SortedSet<DependencyNode> getDependencyDominationSet() { 781 // SortedSet<DependencyNode> dominationSet = new TreeSet<DependencyNode>(); 782 // getDependencyDominationSet(dominationSet); 783 // return dominationSet; 784 // } 785 786 787 /** 788 * Returns <code>true</code> if the node has one or more right dependents, otherwise <code>false</code>. 789 * 790 * @return <code>true</code> if the node has one or more right dependents, otherwise <code>false</code>. 791 */ 792 public boolean hasRightDependent() { 793 return !rightDependents.isEmpty(); 794 } 795 796 public boolean isProjective() throws MaltChainedException { 797 if (hasHead() && !getHead().isRoot()) { 798 final DependencyNode head = getHead(); 799 if (getHead().getIndex() < this.getIndex()) { 800 TokenNode terminals = ((TokenNode)head); 801 DependencyNode tmp = null; 802 while (true) { 803 if (terminals == null || terminals.getSuccessor() == null) { 804 return false; 805 } 806 if (terminals.getSuccessor() == this) { 807 break; 808 } 809 tmp = terminals = terminals.getSuccessor(); 810 while (tmp != this && tmp != head) { 811 if (!tmp.hasHead()) { 812 return false; 813 } 814 tmp = tmp.getHead(); 815 } 816 } 817 } else { 818 TokenNode terminals = ((TokenNode)this); 819 DependencyNode tmp = null; 820 while (true) { 821 if (terminals == null || terminals.getSuccessor() == null) { 822 return false; 823 } 824 if (terminals.getSuccessor() == head) { 825 break; 826 } 827 tmp = terminals = terminals.getSuccessor(); 828 while (tmp != this && tmp != head) { 829 if (!tmp.hasHead()) { 830 return false; 831 } 832 tmp = tmp.getHead(); 833 } 834 } 835 } 836 } 837 return true; 838 } 839 840 public int getDependencyNodeDepth() throws MaltChainedException { 841 DependencyNode tmp = this; 842 int depth = 0; 843 while (tmp.hasHead()) { 844 depth++; 845 tmp = tmp.getHead(); 846 } 847 return depth; 848 } 849 850 public void clear() throws MaltChainedException { 851 super.clear(); 852 predecessor = null; 853 successor = null; 854 component = this; 855 rank = 0; 856 parent = null; 857 heads.clear(); 858 leftDependents.clear(); 859 rightDependents.clear(); 860 } 861 862 @Override 863 public int compareTo(ComparableNode that) { 864 final int BEFORE = -1; 865 final int EQUAL = 0; 866 final int AFTER = 1; 867 if (this == that) return EQUAL; 868 869 if (that instanceof TokenNode) { 870 if (this.index < that.getCompareToIndex()) return BEFORE; 871 if (this.index > that.getCompareToIndex()) return AFTER; 872 return super.compareTo(that); 873 } 874 if (that instanceof NonTerminalNode) { 875 try { 876 final int thisLCorner = this.index; 877 final int thatLCorner = that.getLeftmostProperDescendantIndex(); 878 final int thisRCorner = this.index; 879 final int thatRCorner = that.getRightmostProperDescendantIndex(); 880 881 // if (thisLCorner == -1 || thatLCorner == -1) { 882 // if (thisRCorner < thatRCorner) return BEFORE; 883 // if (thisRCorner > thatRCorner) return AFTER; 884 // } 885 // if (thisRCorner == -1 || thatRCorner == -1) { 886 // if (thisLCorner < thatLCorner) return BEFORE; 887 // if (thisLCorner > thatLCorner) return AFTER; 888 // } 889 890 if (thisLCorner != -1 && thatLCorner != -1 && thisRCorner != -1 && thatRCorner != -1) { 891 if (thisLCorner < thatLCorner && thisRCorner < thatRCorner) return BEFORE; 892 if (thisLCorner > thatLCorner && thisRCorner > thatRCorner) return AFTER; 893 if (thisLCorner > thatLCorner && thisRCorner < thatRCorner) return BEFORE; 894 if (thisLCorner < thatLCorner && thisRCorner > thatRCorner) return AFTER; 895 } else { 896 if (thisLCorner != -1 && thatLCorner != -1) { 897 if (thisLCorner < thatLCorner) return BEFORE; 898 if (thisLCorner > thatLCorner) return AFTER; 899 } 900 if (thisRCorner != -1 && thatRCorner != -1) { 901 if (thisRCorner < thatRCorner) return BEFORE; 902 if (thisRCorner > thatRCorner) return AFTER; 903 } 904 } 905 906 907 908 // final int thisLCorner = this.index; 909 // final int thatLCorner = that.getLeftmostDescendantIndex(); 910 // final int thisRCorner = this.index; 911 // final int thatRCorner = that.getRightmostDescendantIndex(); 912 // 913 // if (thisLCorner == -1 || thatLCorner == -1) { 914 // if (thisRCorner < thatRCorner) return BEFORE; 915 // if (thisRCorner > thatRCorner) return AFTER; 916 // } 917 // if (thisRCorner == -1 || thatRCorner == -1) { 918 // if (thisLCorner < thatLCorner) return BEFORE; 919 // if (thisLCorner > thatLCorner) return AFTER; 920 // } 921 // if (thisLCorner < thatLCorner && thisRCorner < thatRCorner) return BEFORE; 922 // if (thisLCorner > thatLCorner && thisRCorner > thatRCorner) return AFTER; 923 // if (thisLCorner > thatLCorner && thisRCorner < thatRCorner) return BEFORE; 924 // if (thisLCorner < thatLCorner && thisRCorner > thatRCorner) return AFTER; 925 926 927 928 // int corner = that.getLeftmostDescendantIndex(); 929 // if (corner != -1) { 930 // if (this.index < corner) return BEFORE; 931 // if (this.index > corner) return AFTER; 932 // } 933 // corner = that.getRightmostDescendantIndex(); 934 // if (corner != -1) { 935 // if (this.index < corner) return BEFORE; 936 // if (this.index > corner) return AFTER; 937 // } 938 } catch (MaltChainedException e) { 939 if (SystemLogger.logger().isDebugEnabled()) { 940 SystemLogger.logger().debug("",e); 941 } else { 942 SystemLogger.logger().error(e.getMessageChain()); 943 } 944 System.exit(1); 945 } 946 } 947 if (this.index < that.getCompareToIndex()) return BEFORE; 948 if (this.index > that.getCompareToIndex()) return AFTER; 949 return super.compareTo(that); 950 } 951 952 public boolean equals(Object obj) { 953 Token v = (Token)obj; 954 if (!(this.predecessor == v.predecessor && this.successor == v.successor)) return false; 955 return super.equals(obj); 956 } 957 958 public int hashCode() { 959 int hash = 7; 960 hash = 31 * hash + (null == predecessor ? 0 : predecessor.hashCode()); 961 hash = 31 * hash + (null == successor ? 0 : successor.hashCode()); 962 return 31 * hash + super.hashCode(); 963 } 964 965 966 public String toString() { 967 final StringBuilder sb = new StringBuilder(); 968 sb.append(super.toString()); 969 return sb.toString(); 970 } 971 }