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 (heads.size() == 0) { 436 return null; 437 } 438 if (heads.size() == 1) { 439 for (DependencyNode head : heads) { 440 return head; 441 } 442 } 443 444 if (heads.size() > 1) { 445 throw new SyntaxGraphException("The dependency node is multi-headed and it is ambigious to return a single-head dependency node. "); 446 } 447 // heads.first(); 448 449 return null; 450 } 451 452 public Edge getHeadEdge() throws MaltChainedException { 453 if (heads.size() == 0) { 454 return null; 455 } 456 if (incomingEdges.size() == 1 && incomingEdges.first() instanceof DependencyNode) { 457 return incomingEdges.first(); 458 } 459 if (heads.size() == 1) { 460 for (Edge e : incomingEdges) { 461 if (e.getSource() == heads.first()) { 462 return e; 463 } 464 } 465 } 466 return null; 467 } 468 469 public void addHeadEdgeLabel(SymbolTable table, String symbol) throws MaltChainedException { 470 if (hasHead()) { 471 getHeadEdge().addLabel(table, symbol); 472 } 473 } 474 475 public void addHeadEdgeLabel(SymbolTable table, int code) throws MaltChainedException { 476 if (hasHead()) { 477 getHeadEdge().addLabel(table, code); 478 } 479 } 480 481 public void addHeadEdgeLabel(LabelSet labelSet) throws MaltChainedException { 482 if (hasHead()) { 483 getHeadEdge().addLabel(labelSet); 484 } 485 } 486 487 public boolean hasHeadEdgeLabel(SymbolTable table) throws MaltChainedException { 488 if (!hasHead()) { 489 return false; 490 } 491 return getHeadEdge().hasLabel(table); 492 } 493 494 public String getHeadEdgeLabelSymbol(SymbolTable table) throws MaltChainedException { 495 return getHeadEdge().getLabelSymbol(table); 496 } 497 498 public int getHeadEdgeLabelCode(SymbolTable table) throws MaltChainedException { 499 if (!hasHead()) { 500 return 0; 501 } 502 return getHeadEdge().getLabelCode(table); 503 } 504 505 public boolean isHeadEdgeLabeled() throws MaltChainedException { 506 if (!hasHead()) { 507 return false; 508 } 509 return getHeadEdge().isLabeled(); 510 } 511 512 public int nHeadEdgeLabels() throws MaltChainedException { 513 if (!hasHead()) { 514 return 0; 515 } 516 return getHeadEdge().nLabels(); 517 } 518 519 public Set<SymbolTable> getHeadEdgeLabelTypes() throws MaltChainedException { 520 return getHeadEdge().getLabelTypes(); 521 } 522 523 public LabelSet getHeadEdgeLabelSet() throws MaltChainedException { 524 return getHeadEdge().getLabelSet(); 525 } 526 527 public boolean hasDependent() { 528 return hasLeftDependent() || hasRightDependent(); 529 } 530 531 /** 532 * Returns <code>true</code> if the node has one or more left dependents, otherwise <code>false</code>. 533 * 534 * @return <code>true</code> if the node has one or more left dependents, otherwise <code>false</code>. 535 */ 536 public boolean hasLeftDependent() { 537 return !leftDependents.isEmpty(); 538 } 539 540 /** 541 * Returns the left dependent at the position <code>index</code>, where <code>index==0</code> equals the left most dependent. 542 * 543 * @param index the index 544 * @return the left dependent at the position <code>index</code>, where <code>index==0</code> equals the left most dependent 545 */ 546 public DependencyNode getLeftDependent(int index) { 547 if (0 <= index && index < leftDependents.size()) { 548 int i = 0; 549 // DependencyNode candidate = null; 550 551 for (DependencyNode node : leftDependents) { 552 // candidate = node; 553 if (i == index) { 554 return node; 555 } 556 i++; 557 } 558 } 559 return null; 560 } 561 562 /** 563 * Return the number of left dependents 564 * 565 * @return the number of left dependents 566 */ 567 public int getLeftDependentCount() { 568 return leftDependents.size(); 569 } 570 571 public SortedSet<DependencyNode> getLeftDependents() { 572 return leftDependents; 573 } 574 575 /** 576 * Returns the left sibling if it exists, otherwise <code>null</code> 577 * 578 * @return the left sibling if it exists, otherwise <code>null</code> 579 */ 580 public DependencyNode getLeftSibling() throws MaltChainedException { 581 if (getHead() == null) { 582 return null; 583 } 584 585 DependencyNode candidate = null; 586 for (DependencyNode node : getHead().getLeftDependents()) { 587 if (node == this) { 588 return candidate; 589 } 590 candidate = node; 591 } 592 for (DependencyNode node : getHead().getRightDependents()) { 593 if (node == this) { 594 return candidate; 595 } 596 candidate = node; 597 } 598 return null; 599 } 600 601 /** 602 * Returns the left sibling at the same side of head as the node it self. If not found <code>null</code is returned 603 * 604 * @return the left sibling at the same side of head as the node it self. If not found <code>null</code is returned 605 */ 606 public DependencyNode getSameSideLeftSibling() throws MaltChainedException { 607 if (getHead() == null) { 608 return null; 609 } else if (this.getIndex() < getHead().getIndex()) { 610 try { 611 return getHead().getLeftDependents().headSet(this).last(); 612 } catch (NoSuchElementException e) { 613 return null; 614 } 615 } else if (this.getIndex() > getHead().getIndex()) { 616 try { 617 return getHead().getRightDependents().headSet(this).last(); 618 } catch (NoSuchElementException e) { 619 return null; 620 } 621 } 622 return null; 623 } 624 625 /** 626 * Returns the closest left dependent to the node it self, if not found <code>null</code> is returned. 627 * 628 * @return the closest left dependent to the node it self, if not found <code>null</code> is returned. 629 */ 630 public DependencyNode getClosestLeftDependent() { 631 try { 632 return leftDependents.last(); 633 } catch (NoSuchElementException e) { 634 return null; 635 } 636 } 637 638 public DependencyNode getLeftmostDependent() { 639 for (DependencyNode dep : leftDependents) { 640 return dep; 641 } 642 return null; 643 // try { 644 // return leftDependents.first(); 645 // } catch (NoSuchElementException e) { 646 // return null; 647 // } 648 } 649 650 public DependencyNode getRightDependent(int index) { 651 int size = rightDependents.size(); 652 if (index < size) { 653 return rightDependents.toArray(new DependencyNode[size])[size - 1 - index]; 654 } 655 return null; 656 // if (0 <= index && index < rightDependents.size()) { 657 // int i = 0; 658 // DependencyNode candidate = null; 659 // 660 // for (DependencyNode node : rightDependents) { 661 // candidate = node; 662 // if (i == index) { 663 // return candidate; 664 // } 665 // i++; 666 // } 667 // } 668 // return null; 669 } 670 671 /** 672 * Return the number of right dependents 673 * 674 * @return the number of right dependents 675 */ 676 public int getRightDependentCount() { 677 return rightDependents.size(); 678 } 679 680 /** 681 * Returns a sorted set of right dependents. 682 * 683 * @return a sorted set of right dependents. 684 */ 685 public SortedSet<DependencyNode> getRightDependents() { 686 return rightDependents; 687 } 688 689 /** 690 * Returns the right sibling if it exists, otherwise <code>null</code> 691 * 692 * @return the right sibling if it exists, otherwise <code>null</code> 693 */ 694 public DependencyNode getRightSibling() throws MaltChainedException { 695 if (getHead() == null) { 696 return null; 697 } 698 699 for (DependencyNode node : getHead().getLeftDependents()) { 700 if (node.getIndex() > this.getIndex()) { 701 return node; 702 } 703 } 704 for (DependencyNode node : getHead().getRightDependents()) { 705 if (node.getIndex() > this.getIndex()) { 706 return node; 707 } 708 } 709 return null; 710 } 711 712 /** 713 * Returns the right sibling at the same side of head as the node it self. If not found <code>null</code is returned 714 * 715 * @return the right sibling at the same side of head as the node it self. If not found <code>null</code is returned 716 */ 717 public DependencyNode getSameSideRightSibling() throws MaltChainedException { 718 if (getHead() == null) { 719 return null; 720 } else if (this.getIndex() < getHead().getIndex()) { 721 final SortedSet<DependencyNode> tailSet = getHead().getLeftDependents().tailSet(this); 722 if (tailSet.size() <= 1) { 723 return null; 724 } 725 return tailSet.toArray(new DependencyNode[tailSet.size()])[1]; 726 } else if (this.getIndex() > getHead().getIndex()) { 727 final SortedSet<DependencyNode> tailSet = getHead().getRightDependents().tailSet(this); 728 if (tailSet.size() <= 1) { 729 return null; 730 } 731 return tailSet.toArray(new DependencyNode[tailSet.size()])[1]; 732 } 733 return null; 734 } 735 736 /** 737 * Returns the closest right dependent to the node it self, if not found <code>null</code> is returned. 738 * 739 * @return the closest right dependent to the node it self, if not found <code>null</code> is returned. 740 */ 741 public DependencyNode getClosestRightDependent() { 742 for (DependencyNode dep : rightDependents) { 743 return dep; 744 } 745 return null; 746 // try { 747 // return rightDependents.first(); 748 // } catch (NoSuchElementException e) { 749 // return null; 750 // } 751 } 752 753 public DependencyNode getRightmostDependent() { 754 int n = rightDependents.size(); 755 int i = 1; 756 for (DependencyNode node : rightDependents) { 757 if (i == n) { 758 return node; 759 } 760 i++; 761 } 762 return null; 763 // try { 764 // return rightDependents.last(); 765 // } catch (NoSuchElementException e) { 766 // return null; 767 // } 768 } 769 770 protected void getDependencyDominationSet(SortedSet<DependencyNode> dominationSet) { 771 if (leftDependents.size() > 0 || rightDependents.size() > 0) { 772 dominationSet.addAll(leftDependents); 773 dominationSet.addAll(rightDependents); 774 775 for (DependencyNode node : leftDependents) { 776 ((Token)node).getDependencyDominationSet(dominationSet); 777 } 778 for (DependencyNode node : rightDependents) { 779 ((Token)node).getDependencyDominationSet(dominationSet); 780 } 781 } 782 } 783 784 // private SortedSet<DependencyNode> getDependencyDominationSet() { 785 // SortedSet<DependencyNode> dominationSet = new TreeSet<DependencyNode>(); 786 // getDependencyDominationSet(dominationSet); 787 // return dominationSet; 788 // } 789 790 791 /** 792 * Returns <code>true</code> if the node has one or more right dependents, otherwise <code>false</code>. 793 * 794 * @return <code>true</code> if the node has one or more right dependents, otherwise <code>false</code>. 795 */ 796 public boolean hasRightDependent() { 797 return !rightDependents.isEmpty(); 798 } 799 800 public boolean isProjective() throws MaltChainedException { 801 if (hasHead() && !getHead().isRoot()) { 802 final DependencyNode head = getHead(); 803 if (getHead().getIndex() < this.getIndex()) { 804 TokenNode terminals = ((TokenNode)head); 805 DependencyNode tmp = null; 806 while (true) { 807 if (terminals == null || terminals.getSuccessor() == null) { 808 return false; 809 } 810 if (terminals.getSuccessor() == this) { 811 break; 812 } 813 tmp = terminals = terminals.getSuccessor(); 814 while (tmp != this && tmp != head) { 815 if (!tmp.hasHead()) { 816 return false; 817 } 818 tmp = tmp.getHead(); 819 } 820 } 821 } else { 822 TokenNode terminals = ((TokenNode)this); 823 DependencyNode tmp = null; 824 while (true) { 825 if (terminals == null || terminals.getSuccessor() == null) { 826 return false; 827 } 828 if (terminals.getSuccessor() == head) { 829 break; 830 } 831 tmp = terminals = terminals.getSuccessor(); 832 while (tmp != this && tmp != head) { 833 if (!tmp.hasHead()) { 834 return false; 835 } 836 tmp = tmp.getHead(); 837 } 838 } 839 } 840 } 841 return true; 842 } 843 844 public int getDependencyNodeDepth() throws MaltChainedException { 845 DependencyNode tmp = this; 846 int depth = 0; 847 while (tmp.hasHead()) { 848 depth++; 849 tmp = tmp.getHead(); 850 } 851 return depth; 852 } 853 854 public void clear() throws MaltChainedException { 855 super.clear(); 856 predecessor = null; 857 successor = null; 858 component = this; 859 rank = 0; 860 parent = null; 861 heads.clear(); 862 leftDependents.clear(); 863 rightDependents.clear(); 864 } 865 866 @Override 867 public int compareTo(ComparableNode that) { 868 final int BEFORE = -1; 869 final int EQUAL = 0; 870 final int AFTER = 1; 871 if (this == that) return EQUAL; 872 873 if (that instanceof TokenNode) { 874 if (this.index < that.getCompareToIndex()) return BEFORE; 875 if (this.index > that.getCompareToIndex()) return AFTER; 876 return super.compareTo(that); 877 } 878 if (that instanceof NonTerminalNode) { 879 try { 880 final int thisLCorner = this.index; 881 final int thatLCorner = that.getLeftmostProperDescendantIndex(); 882 final int thisRCorner = this.index; 883 final int thatRCorner = that.getRightmostProperDescendantIndex(); 884 885 // if (thisLCorner == -1 || thatLCorner == -1) { 886 // if (thisRCorner < thatRCorner) return BEFORE; 887 // if (thisRCorner > thatRCorner) return AFTER; 888 // } 889 // if (thisRCorner == -1 || thatRCorner == -1) { 890 // if (thisLCorner < thatLCorner) return BEFORE; 891 // if (thisLCorner > thatLCorner) return AFTER; 892 // } 893 894 if (thisLCorner != -1 && thatLCorner != -1 && thisRCorner != -1 && thatRCorner != -1) { 895 if (thisLCorner < thatLCorner && thisRCorner < thatRCorner) return BEFORE; 896 if (thisLCorner > thatLCorner && thisRCorner > thatRCorner) return AFTER; 897 if (thisLCorner > thatLCorner && thisRCorner < thatRCorner) return BEFORE; 898 if (thisLCorner < thatLCorner && thisRCorner > thatRCorner) return AFTER; 899 } else { 900 if (thisLCorner != -1 && thatLCorner != -1) { 901 if (thisLCorner < thatLCorner) return BEFORE; 902 if (thisLCorner > thatLCorner) return AFTER; 903 } 904 if (thisRCorner != -1 && thatRCorner != -1) { 905 if (thisRCorner < thatRCorner) return BEFORE; 906 if (thisRCorner > thatRCorner) return AFTER; 907 } 908 } 909 910 911 912 // final int thisLCorner = this.index; 913 // final int thatLCorner = that.getLeftmostDescendantIndex(); 914 // final int thisRCorner = this.index; 915 // final int thatRCorner = that.getRightmostDescendantIndex(); 916 // 917 // if (thisLCorner == -1 || thatLCorner == -1) { 918 // if (thisRCorner < thatRCorner) return BEFORE; 919 // if (thisRCorner > thatRCorner) return AFTER; 920 // } 921 // if (thisRCorner == -1 || thatRCorner == -1) { 922 // if (thisLCorner < thatLCorner) return BEFORE; 923 // if (thisLCorner > thatLCorner) return AFTER; 924 // } 925 // if (thisLCorner < thatLCorner && thisRCorner < thatRCorner) return BEFORE; 926 // if (thisLCorner > thatLCorner && thisRCorner > thatRCorner) return AFTER; 927 // if (thisLCorner > thatLCorner && thisRCorner < thatRCorner) return BEFORE; 928 // if (thisLCorner < thatLCorner && thisRCorner > thatRCorner) return AFTER; 929 930 931 932 // int corner = that.getLeftmostDescendantIndex(); 933 // if (corner != -1) { 934 // if (this.index < corner) return BEFORE; 935 // if (this.index > corner) return AFTER; 936 // } 937 // corner = that.getRightmostDescendantIndex(); 938 // if (corner != -1) { 939 // if (this.index < corner) return BEFORE; 940 // if (this.index > corner) return AFTER; 941 // } 942 } catch (MaltChainedException e) { 943 if (SystemLogger.logger().isDebugEnabled()) { 944 SystemLogger.logger().debug("",e); 945 } else { 946 SystemLogger.logger().error(e.getMessageChain()); 947 } 948 System.exit(1); 949 } 950 } 951 if (this.index < that.getCompareToIndex()) return BEFORE; 952 if (this.index > that.getCompareToIndex()) return AFTER; 953 return super.compareTo(that); 954 } 955 956 public boolean equals(Object obj) { 957 Token v = (Token)obj; 958 if (!(this.predecessor == v.predecessor && this.successor == v.successor)) return false; 959 return super.equals(obj); 960 } 961 962 public int hashCode() { 963 int hash = 7; 964 hash = 31 * hash + (null == predecessor ? 0 : predecessor.hashCode()); 965 hash = 31 * hash + (null == successor ? 0 : successor.hashCode()); 966 return 31 * hash + super.hashCode(); 967 } 968 969 970 public String toString() { 971 final StringBuilder sb = new StringBuilder(); 972 sb.append(super.toString()); 973 return sb.toString(); 974 } 975 }