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