001package gudusoft.gsqlparser.nodes; 002 003import gudusoft.gsqlparser.*; 004import gudusoft.gsqlparser.scriptWriter.TScriptGenerator; 005import gudusoft.gsqlparser.sqlenv.TSQLEnv; 006import gudusoft.gsqlparser.util.gspMD5Utils; 007 008import java.util.ArrayList; 009import java.util.Iterator; 010 011import static java.nio.charset.StandardCharsets.UTF_8; 012 013/** 014 * This class is the root class for all syntax/parse tree nodes. 015 * A syntax/parse tree node is composed of a sequence of tokens generated by the lexer. 016 * <p> 017 * The syntax node usually includes sub-nodes such as a where clause including expression node. 018 * 019 * <br> Check {@link #getNodeType()} for type of this node. 020 * <br> This node includes all tokens from {@link #getStartToken() start token} and {@link #getEndToken() end token} 021 */ 022 023public abstract class TParseTreeNode implements Visitable,Iterator<TSourceToken>{ 024 025 public void setEvaluateDatatype(Class<?> evaluateDatatype) { 026 this.evaluateDatatype = evaluateDatatype; 027 } 028 029 /** 030 * Support String, Integer, Double and Boolean type 031 * 032 * @return 033 */ 034 public Class<?> getEvaluateDatatype() { 035 return evaluateDatatype; 036 } 037 038 private Class<?> evaluateDatatype; 039 private Object evalValue; 040 041 public void setEvalValue(Object evalValue) { 042 this.evalValue = evalValue; 043 } 044 045 public Object getEvalValue() { 046 return evalValue; 047 } 048 049 private String plainText = null; 050 051 public void setPlainText(String plainText) { 052 this.plainText = plainText; 053 } 054 055 public String getPlainText() { 056 if (plainText == null){ 057 return toString(); 058 }else{ 059 return plainText; 060 } 061 } 062 063 private ESqlClause location = ESqlClause.unknown; 064 065 public void setLocation(ESqlClause location) { 066 this.location = location; 067 } 068 069 /** 070 * SQL clause that include this objectName such as select list, from clause, set clause 071 * 072 * @return SQL clause that include this objectName 073 */ 074 public ESqlClause getLocation() { 075 return location; 076 } 077 078 private String compactString = null; 079 080 /** 081 * representation of this node by removing all spaces, return and comments 082 * @return string representation of this node by removing all spaces, return and comments 083 */ 084 public String getCompactString(){ 085 if (compactString != null) return compactString; 086 087 StringBuilder sb = new StringBuilder(); 088 TSourceToken st = null; 089 currentIterateToken = null; 090 while (this.hasNext()){ 091 st = next(); 092 if ((st.tokencode == TBaseType.lexspace)||(st.tokencode == TBaseType.lexnewline) 093 ||(st.tokencode == TBaseType.cmtslashstar)||(st.tokencode == TBaseType.cmtdoublehyphen) 094 ) { 095 continue; 096 }else{ 097 sb.append(st.toString()); 098 } 099 } 100 101 compactString = sb.toString(); 102 return compactString; 103 } 104 105 private String md5 = null; 106 /** 107 * md5 hash code of the string representation of this node. 108 * If the string of this node is empty, return the md5 value of the class name of this node. 109 * 110 * 1. remove all spaces, return, comments inside the node<br> 111 * 2. turn number constant in where clause into ? character. <br> 112 * 3. turn string constant in where clause into ?? character. <br> 113 * 4. turn all string of the token into uppercase if it's not a delimited identifier. 114 * 115 * @return md5 hash code of the string representation of this node 116 */ 117 public String getMd5(){ 118 if (md5 != null) return md5; 119 120 StringBuilder sb = new StringBuilder(); 121 TSourceToken st = null; 122 currentIterateToken = null; 123 while (this.hasNext()){ 124 st = next(); 125 // cmtslashstar lexspace lexnewline cmtdoublehyphen 126 if ((st.tokencode == TBaseType.lexspace)||(st.tokencode == TBaseType.lexnewline) 127 ||(st.tokencode == TBaseType.cmtslashstar)||(st.tokencode == TBaseType.cmtdoublehyphen) 128 ){ 129 continue; 130 } else if ((st.tokencode == TBaseType.fconst)||(st.tokencode == TBaseType.iconst)){ 131 if (st.location == ESqlClause.where){ 132 sb.append("?"); 133 }else{ 134 sb.append(st.toString()); 135 } 136 } else if (st.tokencode == TBaseType.sconst){ 137 if (st.location == ESqlClause.where){ 138 sb.append("??"); 139 }else{ 140 sb.append(st.toString()); 141 } 142 } else if (TSQLEnv.isDelimitedIdentifier(this.dbvendor,st.toString())){ 143 sb.append(st.toString()); 144 }else { 145 sb.append(st.toString().toUpperCase()); 146 } 147 } 148 byte[] md5InBytes; 149 if (sb.toString().length() > 0){ 150 md5InBytes = gspMD5Utils.digest(sb.toString().getBytes(UTF_8)); 151 }else{ 152 md5InBytes = gspMD5Utils.digest(this.getClass().getName() .getBytes(UTF_8)); 153 } 154 md5 = gspMD5Utils.bytesToHex(md5InBytes); 155 return md5; 156 157 } 158 159 public TParseTreeNode getParentObjectName() { 160 return parent; 161 } 162 163 public void setParent(TParseTreeNode parent) { 164 this.parent = parent; 165 } 166 167 private TParseTreeNode parent = null; 168 169// public void appendAToken(TSourceToken st){ 170// // this token is not belonged to this node 171// this.getEndToken() 172// } 173 public static boolean doubleLinkedTokenListToString = true; 174 175// TSourceToken st = getStartToken(); 176// TSourceToken et = getEndToken(); 177 public void insertAfterAToken(TSourceToken anchorToken){ 178 if ((anchorToken == null)||(this.getEndToken() == null)||(this.getStartToken() == null) )return; 179 this.getEndToken().setNextTokenInChain(anchorToken.getNextTokenInChain()); 180 if (anchorToken.getNextTokenInChain() != null){ 181 anchorToken.getNextTokenInChain().setPrevTokenInChain(this.getEndToken()); 182 }else{ 183 if (anchorToken.getNodesEndWithThisToken().size() > 0){ 184 for(Object o:anchorToken.getNodesEndWithThisToken()){ 185 TParseTreeNode node = (TParseTreeNode)o; 186 node.setEndToken(this.getEndToken()); 187 } 188 } 189 } 190 anchorToken.setNextTokenInChain(this.getStartToken()); 191 this.getStartToken().setPrevTokenInChain(anchorToken); 192 193 } 194 195 public void insertNewNodeBeforeMe(TParseTreeNode newNode, boolean needCommaBefore){ 196 197 updateNodeWithTheSameStartToken(nodeActionInsert,newNode.getStartToken()); 198 199 newNode.getStartToken().setPrevTokenInChain(this.getStartToken().getPrevTokenInChain()); 200 if (this.getStartToken().getPrevTokenInChain() != null){ 201 this.getStartToken().getPrevTokenInChain().setNextTokenInChain(newNode.getStartToken()); 202 } 203 204 newNode.getEndToken().setNextTokenInChain(this.getStartToken()); 205 this.getStartToken().setPrevTokenInChain(newNode.getEndToken()); 206 207 if (needCommaBefore) { 208 TSourceToken commaToken = new TSourceToken(","); 209 newNode.getEndToken().insertANewTokenAfterMe(commaToken); 210 } 211 212 } 213 214 public void appendNewNode(TParseTreeNode newNode, boolean needCommaBefore){ 215 // the new node must be share the same parent node with this node 216 217 refreshAllNodesTokenCount(); 218 updateMeNodeWithTheSameEndToken(nodeActionAppend,newNode.getEndToken()); 219 220 newNode.getEndToken().setNextTokenInChain(this.getEndToken().getNextTokenInChain()); 221 if (this.getEndToken().getNextTokenInChain() != null){ 222 this.getEndToken().getNextTokenInChain().setPrevTokenInChain(newNode.getEndToken()); 223 } 224 225 newNode.getStartToken().setPrevTokenInChain(this.getEndToken()); 226 this.getEndToken().setNextTokenInChain(newNode.getStartToken()); 227 228 if (needCommaBefore) { 229 TSourceToken commaToken = new TSourceToken(","); 230 this.getEndToken().insertANewTokenAfterMe(commaToken); 231 } 232 233 } 234 235 public void replaceWithNewNode(TParseTreeNode newNode){ 236 if ((getStartToken() == null)||(getEndToken() == null)) return; 237 if ((newNode.getStartToken() == null)||(newNode.getEndToken() == null)) return; 238 239 if (getStartToken().getPrevTokenInChain() == null) return; 240 241 refreshAllNodesTokenCount(); 242 updateNodeWithTheSameStartToken(nodeActionUpdate,newNode.startToken); 243 updateMeNodeWithTheSameEndToken(nodeActionUpdate,newNode.endToken); 244 245 getStartToken().getPrevTokenInChain().setNextTokenInChain(newNode.getStartToken()); 246 newNode.getStartToken().setPrevTokenInChain(getStartToken().getPrevTokenInChain()); 247 248 newNode.getEndToken().setNextTokenInChain(getEndToken().getNextTokenInChain()); 249 if (getEndToken().getNextTokenInChain() != null){ 250 getEndToken().getNextTokenInChain().setPrevTokenInChain(newNode.getEndToken()); 251 } 252 253 } 254 255 256 257 TSourceToken currentIterateToken = null; 258 259 260 public void resetIterator(){ 261 currentIterateToken = null; 262 } 263 264 @Override 265 public boolean hasNext() { 266 if ((getStartToken() != null)&&(getEndToken() != null)&&(currentIterateToken != getEndToken())){ 267 return true; 268 } 269 else{ 270 return false; 271 } 272 273 } 274 275 @Override 276 public TSourceToken next() { 277 if (this.hasNext()){ 278 if (currentIterateToken == null){ 279 currentIterateToken = getStartToken(); 280 }else { 281 currentIterateToken = currentIterateToken.getNextTokenInChain(); 282 } 283 284 return currentIterateToken; 285 } 286 else 287 return null; 288 } 289 290 @Override 291 public void remove() { 292 throw new UnsupportedOperationException(); 293 } 294 295// @Override 296// public Iterator<TSourceToken> iterator() { 297// return new TokenSetIterator(); 298// } 299// 300// private class TokenSetIterator implements Iterator { 301// TSourceToken st = getStartToken(); 302// TSourceToken et = getEndToken(); 303// TSourceToken currentToken = null; 304// 305// public boolean hasNext() { 306// if ((st != null)&&(et != null)&&(currentToken != et)){ 307// return true; 308// } 309// else 310// return false; 311// } 312// 313// public TSourceToken next() { 314// if (this.hasNext()){ 315// if (currentToken == null){ 316// currentToken = st; 317// }else { 318// currentToken = currentToken.getNextTokenInChain(); 319// } 320// 321// return currentToken; 322// } 323// else 324// return null; 325// } 326// 327// @Override 328// public void remove() { 329// 330// } 331// } 332 333 public void setNodeStatus(ENodeStatus nodeStatus) { 334 this.nodeStatus = nodeStatus; 335 } 336 337 public ENodeStatus getNodeStatus() { 338 339 return nodeStatus; 340 } 341 342 private ENodeStatus nodeStatus = ENodeStatus.nsNormal; 343 344 345 346 public void addToTokenChain(TSourceToken anchorToken, boolean beforeAnchorToken){ 347 348 }; 349 350 private int tokenCount = -1; 351 352 public int getTokenCount() { 353 if (tokenCount == -1){ 354 calculateTokenCount(); 355 } 356 return tokenCount; 357 } 358 359 public void refreshAllNodesTokenCount(){ 360 if (this.startToken != null){ 361 for(int i=0;i<this.startToken.getNodesStartFromThisToken().size();i++){ 362 TParseTreeNode node = this.startToken.getNodesStartFromThisToken().get(i); 363 node.calculateTokenCount(); 364 } 365 } 366 367 if (this.endToken != null){ 368 for(int i=0;i<this.endToken.getNodesEndWithThisToken().size();i++){ 369 TParseTreeNode node = this.endToken.getNodesEndWithThisToken().get(i); 370 node.calculateTokenCount(); 371 } 372 } 373 374 } 375 376 public void calculateTokenCount(){ 377 int ret = 0; 378 TSourceToken prevst = null; 379 this.resetIterator(); 380 while (this.hasNext()){ 381 ret++; 382 TSourceToken st = this.next(); 383 if (st == null){ 384 if (TBaseType.DEBUG){ 385 System.out.println("==========ERROR: start and token is not in the same chain ===============\n"); 386 System.out.println("Start Token:"+this.getStartToken().toString()); 387 System.out.println("End Token:"+this.getEndToken().toString()); 388 if (prevst != null){ 389 System.out.println("Prev token, code:"+prevst.tokencode+", Text:"+prevst.toString()); 390 }else{ 391 System.out.println("Prev token is null"); 392 } 393 System.out.println("============================\n"); 394 } 395 break; 396 } 397 prevst = st; 398 } 399 this.resetIterator(); 400 this.tokenCount = ret; 401 } 402 403 public final static int nodeActionUnknown = 0; 404 public final static int nodeActionRemove = 1; 405 public final static int nodeActionInsert = 2; 406 public final static int nodeActionUpdate = 3; 407 public final static int nodeActionUpdateText = 4; 408 public final static int nodeActionAppend = 5; 409 public final static int nodeChangeStartToken = 6; 410 public final static int nodeChangeEndToken = 7; 411 412 void updateStatusOfNodeShareSameTokens(int nodeAction){ 413 TSourceToken startToken = getStartToken(); 414 TSourceToken endToken = getEndToken(); 415 if (endToken == null) return; 416 if (startToken == null) return; 417 418 // System.out.println("node token count:"+thisNodeTokenCount); 419 this.resetIterator(); 420 while(this.hasNext()){ 421 TSourceToken st = this.next(); 422 // System.out.println(st.toString()); 423 if (st == null) break; 424 425 for(int i=0;i<st.getNodesStartFromThisToken().size();i++){ 426 TParseTreeNode node = st.getNodesStartFromThisToken().get(i); 427 if (st == startToken){ 428 if (this == node){ 429 switch (nodeAction){ 430 case nodeActionRemove: 431 node.nodeStatus = ENodeStatus.nsRemoved; 432 break; 433 default: 434 node.nodeStatus = ENodeStatus.nsDetached; 435 break; 436 } 437 }else if (node.getTokenCount() == this.getTokenCount()){ 438 switch (nodeAction){ 439 case nodeActionRemove: 440 node.nodeStatus = ENodeStatus.nsRemoved; 441 break; 442 default: 443 node.nodeStatus = ENodeStatus.nsDetached; 444 break; 445 } 446 }else if (node.getTokenCount() > this.getTokenCount()){ 447 node.nodeStatus = ENodeStatus.nsPartitial; 448 }else{ 449 node.nodeStatus = ENodeStatus.nsDetached; 450 } 451 }else{ 452 node.nodeStatus = ENodeStatus.nsDetached; 453 } 454 } 455 456 for(int i=0;i<st.getNodesEndWithThisToken().size();i++){ 457 TParseTreeNode node = st.getNodesEndWithThisToken().get(i); 458 if (st == endToken){ 459 if (this == node){ 460 switch (nodeAction){ 461 case nodeActionRemove: 462 node.nodeStatus = ENodeStatus.nsRemoved; 463 break; 464 default: 465 node.nodeStatus = ENodeStatus.nsDetached; 466 break; 467 } 468 }else if (node.getTokenCount() == this.getTokenCount()){ 469 switch (nodeAction){ 470 case nodeActionRemove: 471 node.nodeStatus = ENodeStatus.nsRemoved; 472 break; 473 default: 474 node.nodeStatus = ENodeStatus.nsDetached; 475 break; 476 } 477 }else if (node.getTokenCount() > this.getTokenCount()){ 478 node.nodeStatus = ENodeStatus.nsPartitial; 479 }else{ 480 switch (nodeAction){ 481 case nodeActionRemove: 482 node.nodeStatus = ENodeStatus.nsRemoved; 483 break; 484 default: 485 node.nodeStatus = ENodeStatus.nsDetached; 486 break; 487 } 488 } 489 }else{ 490 switch (nodeAction){ 491 case nodeActionRemove: 492 node.nodeStatus = ENodeStatus.nsRemoved; 493 break; 494 default: 495 node.nodeStatus = ENodeStatus.nsDetached; 496 break; 497 } 498 } 499 } 500 501 } 502 this.resetIterator(); 503 } 504 505 void updateNodeWithTheSameStartToken(int nodeAction, TSourceToken newStartToken){ 506 TSourceToken oldStartToken = this.getStartToken(); 507 for(int i=0;i<oldStartToken.getNodesStartFromThisToken().size();i++){ 508 TParseTreeNode node = oldStartToken.getNodesStartFromThisToken().get(i); 509 if (node == this){ // myself 510 switch (nodeAction){ 511 case nodeActionRemove: 512 node.startToken = null; 513 break; 514 case nodeActionUpdate: 515 case nodeActionUpdateText: 516 case nodeChangeStartToken: 517 node.startToken = newStartToken; 518 newStartToken.getNodesStartFromThisToken().push(node); 519 default: 520 break; 521 } 522 }else if((node.getTokenCount() == this.getTokenCount())){ // node with same tokens 523 switch (nodeAction){ 524 case nodeActionRemove: 525 node.startToken = null; 526 break; 527 case nodeActionUpdate: 528 case nodeActionUpdateText: 529 case nodeChangeStartToken: 530 node.startToken = newStartToken; 531 newStartToken.getNodesStartFromThisToken().push(node); 532 default: 533 break; 534 } 535 } 536 else if((node.getTokenCount() > this.getTokenCount())) { // parent node 537 node.startToken = newStartToken; 538 newStartToken.getNodesStartFromThisToken().push(node); 539 }else{ // sub node 540 541 } 542 } 543 } 544 545 void updateMeNodeWithTheSameEndToken(int nodeAction, TSourceToken newEndToken){ 546 TSourceToken oldEndToken = this.getEndToken(); 547 for(int i=0;i<oldEndToken.getNodesEndWithThisToken().size();i++){ 548 TParseTreeNode node = oldEndToken.getNodesEndWithThisToken().get(i); 549 if (node == this){ // myself 550 switch (nodeAction){ 551 case nodeActionRemove: 552 node.endToken = null; 553 break; 554 case nodeActionUpdate: 555 case nodeActionUpdateText: 556 case nodeChangeEndToken: 557 node.endToken = newEndToken; 558 newEndToken.getNodesEndWithThisToken().push(node); 559 default: 560 break; 561 } 562 }else if((node.getTokenCount() == this.getTokenCount())){ // node with same tokens 563 switch (nodeAction){ 564 case nodeActionRemove: 565 node.endToken = null; 566 break; 567 case nodeActionUpdate: 568 case nodeActionUpdateText: 569 case nodeChangeEndToken: 570 node.endToken = newEndToken; 571 newEndToken.getNodesEndWithThisToken().push(node); 572 default: 573 break; 574 } 575 } 576 else if((node.getTokenCount() > this.getTokenCount())) { // parent node 577 node.endToken = newEndToken; 578 newEndToken.getNodesEndWithThisToken().push(node); 579 }else{ // sub node 580 581 } 582 } 583 } 584 585 /** 586 * both begin and end token will be removed from the chain 587 * 588 * @param startToken 589 * @param endToken 590 */ 591 public static void removeTokensBetweenToken(TSourceToken startToken, TSourceToken endToken){ 592 if ((startToken == null)||(endToken == null)) return; 593 startToken.removeFromChain(); 594 while (startToken != endToken){ 595 startToken = startToken.getNextTokenInChain(); 596 if (startToken == null) break; 597 startToken.removeFromChain(); 598 } 599 } 600 601 public static void removeTokensBetweenNodes(TParseTreeNode startNode, TParseTreeNode endNode){ 602 if ((startNode == null)||(endNode == null)) return; 603 if ((startNode.getEndToken() == null)||(endNode.getStartToken() == null)) return; 604 TSourceToken startToken = startNode.getEndToken().getNextTokenInChain(); 605 TSourceToken endToken = endNode.getStartToken().getPrevTokenInChain(); 606 if ((startToken == null)||(endToken == null)) return; 607 608 startToken.removeFromChain(); 609 while (startToken != endToken){ 610 startToken = startToken.getNextTokenInChain(); 611 if (startToken == null) break; 612 startToken.removeFromChain(); 613 } 614 } 615 616 public void removeTokens(){ 617 if (this.nodeStatus == ENodeStatus.nsRemoved) return; 618 619 TSourceToken oldStartToken = getStartToken(); 620 TSourceToken oldEndToken = getEndToken(); 621 if (oldEndToken == null) return; 622 if (oldStartToken == null) return; 623 624 refreshAllNodesTokenCount(); 625 updateStatusOfNodeShareSameTokens(nodeActionRemove); 626 627 if (oldStartToken.getPrevTokenInChain() != null){ 628 updateMeNodeWithTheSameEndToken(nodeActionRemove,oldStartToken.getPrevTokenInChain()); 629 oldStartToken.getPrevTokenInChain().setNextTokenInChain(oldEndToken.getNextTokenInChain()); 630 } 631 if (oldEndToken.getNextTokenInChain() != null){ 632 updateNodeWithTheSameStartToken(nodeActionRemove,oldEndToken.getNextTokenInChain()); 633 oldEndToken.getNextTokenInChain().setPrevTokenInChain(oldStartToken.getPrevTokenInChain()); 634 } 635 636 if (this.nodeStatus == ENodeStatus.nsNormal){ 637 this.nodeStatus = ENodeStatus.nsRemoved; 638 } 639 640 this.setStartTokenDirectly(null); 641 this.setEndTokenDirectly(null); 642 643 } 644 645 646 647 /** 648 * SQL dialect of this statement. 649 */ 650 public EDbVendor dbvendor = EDbVendor.dbvgeneric; 651 652 /** 653 * The parser that generate this node. 654 * 655 * @return parser that generate this node 656 */ 657 public TGSqlParser getGsqlparser() { 658 if (gsqlparser == null){ 659 if (getStartToken() != null){ 660 // TODO removed in 2.6.8.1, to avoid memory leak in TTypeName 661 // gsqlparser = getStartToken().getGsqlparser(); 662 } 663 } 664 return gsqlparser; 665 } 666 667 boolean includingComment = true; 668 669 670 public void setIncludingComment(boolean includingComment) { 671 this.includingComment = includingComment; 672 } 673 674 private TGSqlParser gsqlparser = null; 675 676 public void setGsqlparser(TGSqlParser gsqlparser) { 677 this.gsqlparser = gsqlparser; 678 if (gsqlparser != null){ 679 this.dbvendor = gsqlparser.getDbVendor(); 680 } 681 } 682 683 private int dummyTag = 0; 684 685 public void setDummyTag(int dummyTag) { 686 this.dummyTag = dummyTag; 687 } 688 689 /** 690 * A temporary value can be used for any purposes 691 * 692 * @return a temporary value used for any purposes 693 */ 694 public int getDummyTag() { 695 return dummyTag; 696 } 697 698 699 private TSourceToken startToken; 700 701 /** 702 * The first token in this parse tree node 703 * 704 * @return the first token of node 705 */ 706 public TSourceToken getStartToken() { 707 return startToken; 708 } 709 710 /** 711 * The last token of the node 712 * 713 * @return the last token of node 714 */ 715 public TSourceToken getEndToken() { 716 return endToken; 717 } 718 719 private TSourceToken endToken; 720 private long lineNo = -1; 721 722 /** 723 * Column position of the first token of this node 724 * 725 * @return column position 726 */ 727 public long getColumnNo() { 728 if (this.getStartToken() != null){ 729 columnNo = this.getStartToken().columnNo; 730 } 731 return columnNo; 732 } 733 734 /** 735 * Line number of the first token of this node 736 * 737 * @return line number 738 */ 739 public long getLineNo() { 740 if (this.getStartToken() != null){ 741 lineNo = this.getStartToken().lineNo; 742 } 743 return lineNo; 744 } 745 746 private long columnNo = -1; 747 748 private int nodeType; 749 /** 750 * Set the node type for this node. 751 * 752 * @param nodeType The node type. 753 */ 754 public void setNodeType(int nodeType) 755 { 756 this.nodeType = nodeType; 757 } 758 759 /** 760 * A unique value to distinguish this node from others 761 * 762 * @return enum value of node type 763 * @see gudusoft.gsqlparser.nodes.ENodeType 764 */ 765 public int getNodeType() 766 { 767 return nodeType; 768 } 769 770 String getastext(){ return "";} 771 String getasprettytext(){ return "";} 772 773 /** 774 * Initialize a query tree node. 775 * Used internally 776 * 777 * @param arg1 first argument 778 */ 779 public void init(Object arg1) 780 { 781 } 782 783 public void init(Object arg1, Object arg2) 784 { 785 } 786 787 public void init(Object arg1, Object arg2, Object arg3) 788 { 789 } 790 791 public void init(Object arg1, Object arg2, Object arg3, Object arg4) 792 { 793 } 794 795 public void init(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) 796 { 797 } 798 799 public void init(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) 800 { 801 } 802 803 /** 804 * Analyze the sub-nodes inside this node. 805 * Such as build the relationship between table and column. 806 * 807 * @param psql SQL statement this node belongs to 808 * @param plocation SQL clause this node belongs to 809 */ 810 public void doParse(TCustomSqlStatement psql, ESqlClause plocation){ 811 812 } 813 814 public void setStartToken(ArrayList startNode) { 815 if (startNode == null) return; 816 if (startNode.size() == 0) return; 817 TParseTreeNode parseTreeNode = (TParseTreeNode)startNode.get(0); 818 this.setStartToken(parseTreeNode.getStartToken()); 819 } 820 821 public void setEndToken(ArrayList endNode) { 822 if (endNode == null) return; 823 if (endNode.size() == 0 ) return; 824 TParseTreeNode parseTreeNode = (TParseTreeNode)endNode.get(endNode.size()-1); 825 this.setEndToken(parseTreeNode.getEndToken()); 826 } 827 828 public void setStartToken(TSourceToken newStartToken) { 829 if (newStartToken == null) return; 830 TSourceToken oldStartToken = this.startToken; 831 if (oldStartToken != null){ 832 if (oldStartToken.getNodesStartFromThisToken().peek() == this){ 833 oldStartToken.getNodesStartFromThisToken().pop(); 834 } 835 } 836 if (newStartToken.getNodesStartFromThisToken().indexOf(this) == -1) 837 { 838 newStartToken.getNodesStartFromThisToken().push(this); 839 } 840 841 this.startToken = newStartToken; 842 } 843 844 public void setStartToken(TSourceTokenList startTokenList) { 845 if (startTokenList == null) return; 846 this.setStartToken(startTokenList.get(0)); 847 } 848 849 public void setStartToken(TParseTreeNode startNode) { 850 if (startNode == null) return; 851 this.setStartToken(startNode.getStartToken()); 852 } 853 854 public void setStartTokenDirectly(TSourceToken newStartToken) { 855 this.startToken = newStartToken; 856 } 857 public void setEndTokenDirectly(TSourceToken newEndToken) { 858 this.endToken = newEndToken; 859 } 860 861 public void setEndToken(TSourceToken newEndToken) { 862 if (newEndToken == null) return; 863 TSourceToken oldEndToken = this.getEndToken(); 864 865 if (oldEndToken != null){ 866 if (oldEndToken.getNodesEndWithThisToken().peek() == this){ 867 oldEndToken.getNodesEndWithThisToken().pop(); 868 } 869 } 870 871 if (newEndToken.getNodesEndWithThisToken().indexOf(this) == -1){ 872 newEndToken.getNodesEndWithThisToken().push(this); 873 } 874 875 this.endToken = newEndToken; 876 } 877 878 public void setEndToken(TSourceTokenList endTokenList) { 879 if (endTokenList == null) return; 880 this.setEndToken(endTokenList.get(endTokenList.size()-1)); 881 } 882 883// public void setEndToken(TParseTreeNodeList endNodeList) { 884// if (endNodeList == null) return; 885// this.setEndToken(endNodeList.getEndToken()); 886// } 887 888 889 890 public void setEndToken(TFromTableList endNode) { 891 if (endNode == null) return; 892 this.setEndToken(endNode.getEndToken()); 893 } 894 895 public void setEndToken(TParseTreeNode endNode) { 896 if (endNode == null) return; 897 this.setEndToken(endNode.getEndToken()); 898 } 899 900 private void setStartTokenToNull(){ 901 this.startToken = null; 902 } 903 904 private void setEndTokenToNull(){ 905 this.endToken = null; 906 } 907 908 private void resetStartAndEndTokenBeforeRemoveTokens(TSourceTokenList stList, int start, int end,boolean isReplace,TSourceToken relpacedStartToken,TSourceToken replacedEndToken){ 909 910 for(int m = start; m<=end;m++){ 911 if ((m>stList.size()-1) ||(m<0)) break; 912 TSourceToken deletedToken = stList.get(m); 913 for(int i=0;i<deletedToken.getNodesStartFromThisToken().size();i++){ 914 TParseTreeNode node = deletedToken.getNodesStartFromThisToken().get(i); 915 TSourceToken EndSt = node.getEndToken(); 916 917 if (isReplace&&((m==start)||(m==end))){ 918 node.setStartToken(relpacedStartToken); 919 }else{ 920 if (EndSt == null){ 921 node.setStartTokenToNull(); 922 }else{ 923 if (EndSt.posinlist > end){ 924 node.setStartToken(stList.get(end+1)); 925 }else if (EndSt.posinlist < start){ 926 node.setStartTokenToNull(); 927 node.setEndTokenToNull(); 928 }else{ 929 node.setStartTokenToNull(); 930 node.setEndTokenToNull(); 931 } 932 } 933 } 934 } // nodes start from this token 935 936 for (int i=0;i<deletedToken.getNodesEndWithThisToken().size();i++){ 937 TParseTreeNode node = deletedToken.getNodesEndWithThisToken().get(i); 938 TSourceToken startSt = node.getStartToken(); 939 940 if (isReplace&&((m==start)||(m==end))){ 941 node.setEndToken(replacedEndToken); 942 }else{ 943 if (startSt == null){ 944 node.setEndTokenToNull(); 945 }else{ 946 if (startSt.posinlist > end){ 947 node.setStartTokenToNull(); 948 node.setEndTokenToNull(); 949 }else if (startSt.posinlist < start){ 950 node.setEndToken(stList.get(start - 1)); 951 }else{ 952 node.setStartTokenToNull(); 953 node.setEndTokenToNull(); 954 } 955 } 956 } 957 }// nodes end with this token 958 959 }//loop all tokens to be deleted in this parse tree nodes 960 } 961 962 963 964 private void fastResetStartAndEndTokenBeforeRemoveTokens(TSourceTokenList stList, int start, int end,TSourceToken replacedToken){ 965 int[] startEnd; 966 if (start != end) { 967 startEnd = new int[2]; 968 startEnd[0] = start; 969 startEnd[1] = end; 970 } 971 else { 972 startEnd = new int[1]; 973 startEnd[0] = start; 974 } 975 for(int m : startEnd){ 976 TSourceToken deletedToken = stList.get(m); 977 for(int i=0;i<deletedToken.getNodesStartFromThisToken().size();i++){ 978 TParseTreeNode node = deletedToken.getNodesStartFromThisToken().get(i); 979 node.setStartToken(replacedToken); 980 } // nodes start from this token 981 982 for (int i=0;i<deletedToken.getNodesEndWithThisToken().size();i++){ 983 TParseTreeNode node = deletedToken.getNodesEndWithThisToken().get(i); 984 node.setEndToken(replacedToken); 985 }// nodes end with this token 986 987 }//loop all tokens to be deleted in this parse tree nodes 988 } 989 990 /** 991 * @deprecated since v1.8.8.0, use scriptWriter technology to modify the node 992 * Set the new string text of a node will destroy all the sub-node structure 993 * 994 * @param sqlSegment that override original text of this node. 995 */ 996 997 /* 998 * <p>1. new string will be tokenized into a list of source tokens: stlist 999 * <p>2. link alternativetoken of start token of this node to the first token in stlist generated in step 1. 1000 * <p>3. link back alternative token of last token in stlist to the last token of this node. 1001 * <p>So, if you find a start token of parse tree node has an alternativetoken, then text of this node should be modified by using setString(String sqlSegment) 1002 * <p> if a parse tree node with an alias clause like: tablename as tablealias, 1003 * <p> TTable.setString() will replace whole text "tablename as tablealias" including alias clause. 1004 * 1005 * steps to set new string(sqlSegment) of parse tree node 1006 * length(sqlSegment)=0 or sqlSegment = one space,, means remove this node from parse tree 1007 * length(sqlSegment) > 0 , means replace source tokens of this node with new tokens 1008 * 1009 */ 1010 public void setString2(String sqlSegment){ 1011 1012// TGSqlParser l_sqlparser = new TGSqlParser(getGsqlparser().getDbVendor()); 1013// l_sqlparser.sqltext = sqlSegment; 1014// l_sqlparser.tokenizeSqltext(); 1015 1016 TSingletonParser singletonParser = TSingletonParser.getInstance(); 1017 1018 TSourceTokenList stList; 1019 if (this.dbvendor == EDbVendor.dbvgeneric){ 1020 stList = singletonParser.getTokens(TGSqlParser.currentDBVendor,sqlSegment); 1021 }else{ 1022 stList = singletonParser.getTokens(this.dbvendor,sqlSegment); 1023 } 1024 1025 1026 1027 if ((getStartToken() == null)&&(getEndToken() == null)){ 1028 // this is a manually created parse tree node, not created by yacc 1029// l_sqlparser.sourcetokenlist.get(0).container = l_sqlparser.sourcetokenlist; 1030// l_sqlparser.sourcetokenlist.get(l_sqlparser.sourcetokenlist.size()-1).container = l_sqlparser.sourcetokenlist; 1031 setStartToken(stList.get(0)); 1032 setEndToken(stList.get(stList.size()-1)); 1033 return; 1034 } 1035 1036 TSourceToken lcStartToken = getStartToken(); 1037 TSourceToken lcEndToken = getEndToken(); 1038 1039 // TSourceTokenList stList = lcEndToken.container; 1040 1041 int lcStartTokenPos = lcStartToken.posinlist; 1042 int lcEndTokenPos = lcEndToken.posinlist; 1043 1044 1045 if ((sqlSegment.length()==0) || (sqlSegment == " ")){ 1046 1047 //reset start and end token of those parse tree node 1048 resetStartAndEndTokenBeforeRemoveTokens(stList, lcStartTokenPos, lcEndTokenPos,false,null,null); 1049 1050 // remove token from list 1051 for(int i=lcEndTokenPos;i>=lcStartTokenPos;i--){ 1052 stList.remove(i); 1053 } 1054 1055 // reindex posinlist after remove token from container 1056 for(int i=lcStartTokenPos;i<stList.size();i++){ 1057 stList.get(i).posinlist = i; 1058 } 1059 1060 }else{ 1061 //replace 1062 //reset start and end token of those parse tree node 1063 TSourceToken lcReplacedStartToken = stList.get(0); 1064 TSourceToken lcReplacedEndToken = stList.get(stList.size()-1); 1065 resetStartAndEndTokenBeforeRemoveTokens(stList, lcStartTokenPos, lcEndTokenPos,true,lcReplacedStartToken,lcReplacedEndToken); 1066 1067 // remove token from list 1068 for(int i=lcEndTokenPos;i>=lcStartTokenPos;i--){ 1069 stList.remove(i); 1070 } 1071 1072 1073// for(int i = stList.size()-1; i>=0; i--){ 1074// TSourceToken st = stList.get(i); 1075// st.container = stList; 1076// stList.add(lcStartTokenPos,st); 1077// } 1078 1079 // reindex posinlist after remove token from container 1080 for(int i=lcStartTokenPos;i<stList.size();i++){ 1081 TSourceToken st = stList.get(i); 1082 st.posinlist = i; 1083 } 1084 1085 } 1086 1087 } 1088 1089 /** 1090 * Set the text of the node and update the corresponding source tokens synchronously. 1091 * This way, when the toString() method of the node itself or its parent node is called, 1092 * it will return the modified text. 1093 * 1094 * @param sqlSegment 1095 */ 1096 public void setString(String sqlSegment){ 1097 if (doubleLinkedTokenListToString){ 1098 setText(sqlSegment); 1099 }else{ 1100 setString2(sqlSegment); 1101 } 1102 } 1103 1104 public void fastSetString(String sqlSegment){ 1105 1106 TSourceToken replaceToken = new TSourceToken(sqlSegment); 1107 setText(replaceToken, replaceToken); 1108 } 1109 1110 1111 /** 1112 * return null if no comment is found before this node. 1113 * 1114 * @return the comment before this node 1115 */ 1116 public String getCommentBeforeNode(){ 1117 String ret = null; 1118 TSourceToken lcStartToken; 1119 1120 if (doubleLinkedTokenListToString){ 1121 lcStartToken = getStartToken(); 1122 if (lcStartToken == null) return null; 1123 1124 TSourceToken lcCurrentToken = lcStartToken.getPrevTokenInChain(); 1125 while (lcCurrentToken != null){ 1126 if ((lcCurrentToken.tokentype == ETokenType.ttreturn)||(lcCurrentToken.tokentype == ETokenType.ttwhitespace)) 1127 { 1128 if (ret != null){ 1129 ret = lcCurrentToken.toString() + ret ; 1130 } 1131 lcCurrentToken = lcCurrentToken.getPrevTokenInChain(); 1132 continue; 1133 } 1134 else if (lcCurrentToken.astext.trim().length() == 0) { 1135 lcCurrentToken = lcCurrentToken.getPrevTokenInChain(); 1136 continue; 1137 } 1138 if ((lcCurrentToken.tokencode == TBaseType.cmtslashstar) ||(lcCurrentToken.tokencode == TBaseType.cmtdoublehyphen) 1139 || lcCurrentToken.astext.startsWith("--") || lcCurrentToken.astext.startsWith("/*") 1140 ){ 1141 if (ret == null){ 1142 ret = lcCurrentToken.toString(); 1143 }else{ 1144 ret = lcCurrentToken.toString()+ ret; 1145 } 1146 1147 lcCurrentToken = lcCurrentToken.getPrevTokenInChain(); 1148 continue; 1149 } 1150 1151 break; 1152 } 1153 }else{ 1154 lcStartToken = getStartToken(); 1155 if (lcStartToken == null) return null; 1156 1157 TSourceTokenList stList = lcStartToken.container; 1158 if (stList == null) return null; 1159 1160 int b = lcStartToken.posinlist; 1161 1162 for(int i = b - 1 ; i>=0;i--){ 1163 TSourceToken st = stList.get(i); 1164 if ((st.tokencode == TBaseType.lexspace)|| (st.tokencode == TBaseType.lexnewline)) continue; 1165 if (st.astext.trim().length() == 0) continue; 1166 if ((st.tokencode == TBaseType.cmtslashstar) ||(st.tokencode == TBaseType.cmtdoublehyphen)){ 1167 if (ret == null){ 1168 ret = st.toString(); 1169 }else{ 1170 ret = st.toString()+TBaseType.newline + ret; 1171 } 1172 continue; 1173 } 1174 else if (st.astext.startsWith("--") || st.astext.startsWith("/*")){ 1175 if (ret == null){ 1176 ret = st.toString(); 1177 }else{ 1178 ret = st.toString()+TBaseType.newline + ret; 1179 } 1180 continue; 1181 } 1182 break; 1183 } 1184 } 1185 1186 return ret; 1187 } 1188 1189 public String getCommentAfterNode(){ 1190 String ret = null; 1191 TSourceToken lcEndToken; 1192 1193 if (!doubleLinkedTokenListToString) return ret; 1194 1195 lcEndToken = getEndToken(); 1196 if (lcEndToken == null) return null; 1197 1198 TSourceToken lcCurrentToken = lcEndToken; 1199 while (lcCurrentToken != null){ 1200 if ((lcCurrentToken.tokentype == ETokenType.ttreturn)||(lcCurrentToken.tokentype == ETokenType.ttwhitespace)) 1201 { 1202 if (ret != null){ 1203 ret = lcCurrentToken.toString() + ret ; 1204 } 1205 lcCurrentToken = lcCurrentToken.getPrevTokenInChain(); 1206 continue; 1207 } 1208 else if (lcCurrentToken.astext.trim().length() == 0) { 1209 lcCurrentToken = lcCurrentToken.getPrevTokenInChain(); 1210 continue; 1211 } 1212 if ((lcCurrentToken.tokencode == TBaseType.cmtslashstar) ||(lcCurrentToken.tokencode == TBaseType.cmtdoublehyphen) 1213 || lcCurrentToken.astext.startsWith("--") || lcCurrentToken.astext.startsWith("/*") 1214 ){ 1215 if (ret == null){ 1216 ret = lcCurrentToken.toString(); 1217 }else{ 1218 ret = lcCurrentToken.toString() +ret ; 1219 } 1220 1221 lcCurrentToken = lcCurrentToken.getPrevTokenInChain(); 1222 continue; 1223 } 1224 1225 break; 1226 } 1227 1228 return ret.trim(); // 移调第一个space or return token if any 1229 1230 } 1231 1232 /** 1233 * String representation of this parse tree node. 1234 * <p> 1235 * This string was generated by collecting text from the start token of this node to the end token of this node. 1236 * If this node was modified, then use {@link #toScript()} to get string representation of this node. 1237 * 1238 * @return string representation of this parse tree node 1239 */ 1240 public String toString2(){ 1241 String ret = null; 1242 TSourceToken lcStartToken = getStartToken(); 1243 if (lcStartToken == null) return null; 1244 1245 TSourceToken lcEndToken = getEndToken(); 1246 if (lcEndToken == null) return null; 1247 1248 TSourceTokenList stList = lcStartToken.container; 1249 if (stList == null) return null; 1250 1251 int b = lcStartToken.posinlist; 1252 int e = lcEndToken.posinlist; 1253 1254 StringBuffer sb = new StringBuffer(""); 1255 1256 for(int i= b ; i<=e;i++){ 1257 if(!includingComment && ((stList.get(i).tokencode == TBaseType.cmtslashstar) ||(stList.get(i).tokencode == TBaseType.cmtdoublehyphen))){ 1258 continue; 1259 } 1260 sb.append(stList.get(i).toString()); 1261 } 1262 1263 return sb.toString(); 1264 } 1265 1266 /** 1267 * The returned text is formed by concatenating the source tokens contained in this node one by one. 1268 * 1269 * @return 1270 */ 1271 public String toString(){ 1272 if (doubleLinkedTokenListToString){ 1273 String ret = null; 1274 TSourceToken lcStartToken = getStartToken(); 1275 if (lcStartToken == null) return null; 1276 TSourceToken lcEndToken = getEndToken(); 1277 if (lcEndToken == null) return null; 1278 1279 boolean chainUnchanged = true; 1280 1281 StringBuffer sb = new StringBuffer(""); 1282 TSourceToken lcPrevSt = null; 1283 boolean ignoreNextReturnToken = false, isChainModified = false; 1284 1285 TSourceToken lcCurrentToken = lcStartToken; 1286 while (lcCurrentToken != null){ 1287 if (lcCurrentToken.tokentype == ETokenType.ttreturn){ 1288 if (ignoreNextReturnToken && (isChainModified||((lcPrevSt != null)&&(lcCurrentToken.posinlist - lcPrevSt.posinlist != 1))) ){ 1289 lcCurrentToken.tokenstatus = ETokenStatus.tsdeleted; 1290 //System.out.println("Find deleted token:"+lcCurrentToken.astext); 1291 }else{ 1292 ignoreNextReturnToken = true; 1293 } 1294 }else if (lcCurrentToken.tokentype != ETokenType.ttwhitespace){ 1295 ignoreNextReturnToken = false; 1296 } 1297 if (!isChainModified && lcPrevSt != null){ 1298 isChainModified = (lcCurrentToken.posinlist - lcPrevSt.posinlist != 1); 1299 1300 if (isChainModified){ 1301 //System.out.println("token chain changed"); 1302 } 1303 } 1304 lcPrevSt = lcCurrentToken; 1305 1306 if (lcCurrentToken.equals(lcEndToken)){ 1307 break; 1308 }else{ 1309 lcCurrentToken = lcCurrentToken.getNextTokenInChain(); 1310 } 1311 } 1312 1313 lcCurrentToken = lcStartToken; 1314 while (lcCurrentToken != null){ 1315 if((lcCurrentToken.tokenstatus == ETokenStatus.tsdeleted) 1316 ||(!includingComment && ((lcCurrentToken.tokencode == TBaseType.cmtslashstar) ||(lcCurrentToken.tokencode == TBaseType.cmtdoublehyphen))) 1317 ){ 1318 // ignore this token, do nothing 1319 // System.out.println("out: ignore deleted token:"+lcCurrentToken.astext); 1320 }else{ 1321 // 1322 sb.append(lcCurrentToken.toString()); 1323 } 1324 1325 if (lcCurrentToken.equals(lcEndToken)){ 1326 break; 1327 }else{ 1328 lcCurrentToken = lcCurrentToken.getNextTokenInChain(); 1329 } 1330 } 1331 1332 return sb.toString(); 1333 1334 }else 1335 { 1336 return toString2(); 1337 } 1338 } 1339 1340 1341 void setText(String nodeText, EDbVendor dbVendor){ 1342 this.dbvendor = dbVendor; 1343 setText(nodeText); 1344 } 1345 1346 private boolean tokensInChain = true; 1347 1348 public boolean isTokensInChain() { 1349 return tokensInChain; 1350 } 1351 1352 void setText(TSourceToken startToken, TSourceToken endToken){ 1353 TSourceToken newStartToken = startToken; 1354 TSourceToken newEndToken = endToken; 1355 1356 TSourceToken oldStartToken = getStartToken(); 1357 TSourceToken oldEndToken = getEndToken(); 1358 tokensInChain = false; 1359 if ((oldStartToken == null)||(oldEndToken == null)){ 1360 setStartToken(newStartToken); 1361 setEndToken(newEndToken); 1362 nodeStatus = ENodeStatus.nsFlattened; 1363 return; 1364 } 1365 1366 refreshAllNodesTokenCount(); 1367 1368 updateStatusOfNodeShareSameTokens(nodeActionUpdateText); 1369 1370 updateNodeWithTheSameStartToken(nodeActionUpdateText,newStartToken); 1371 updateMeNodeWithTheSameEndToken(nodeActionUpdateText,newEndToken); 1372 1373 if (oldStartToken.getPrevTokenInChain() != null){ 1374 oldStartToken.getPrevTokenInChain().setNextTokenInChain(newStartToken); 1375 newStartToken.setPrevTokenInChain(oldStartToken.getPrevTokenInChain()); 1376 } 1377 1378 if (oldEndToken.getNextTokenInChain() != null){ 1379 oldEndToken.getNextTokenInChain().setPrevTokenInChain(newEndToken); 1380 newEndToken.setNextTokenInChain(oldEndToken.getNextTokenInChain()); 1381 } 1382 1383 tokensInChain = true; 1384 } 1385 /** 1386 * set text of this node, if the original token of this node 1387 * is in a token chain, then merge the new token into the chain as well. 1388 * 1389 * use double linked list 1390 * 1391 * @param nodeText node text 1392 */ 1393 void setText(String nodeText){ 1394 if ((this.getNodeStatus() == ENodeStatus.nsRemoved)||(nodeText.length() == 0)) return; 1395 // if ((nodeText.length() == 0)) return; 1396 1397// TGSqlParser sqlParser = new TGSqlParser(TGSqlParser.currentDBVendor); 1398// sqlParser.sqltext = nodeText; 1399// sqlParser.tokenizeSqltext(); 1400// TSourceToken newStartToken = sqlParser.getSourcetokenlist().get(0); 1401// TSourceToken newEndToken = sqlParser.getSourcetokenlist().get(sqlParser.getSourcetokenlist().size() - 1); 1402// setText(newStartToken, newEndToken); 1403 1404 TSingletonParser singletonParser = TSingletonParser.getInstance(); 1405 1406 TSourceTokenList stList; 1407 if (this.dbvendor == EDbVendor.dbvgeneric){ 1408 stList = singletonParser.getTokens(TGSqlParser.currentDBVendor,nodeText); 1409 }else{ 1410 stList = singletonParser.getTokens(this.dbvendor,nodeText); 1411 } 1412 1413 1414 TSourceToken newStartToken = stList.get(0); 1415 TSourceToken newEndToken = stList.get(stList.size() - 1); 1416 setText(newStartToken, newEndToken); 1417 1418 } 1419 1420 1421 /** 1422 * @deprecated since v1.8.8.0, use scriptWriter technology to modify the node 1423 * Inserts tokens(from start token to end token ) of this parse tree node at the specified position in this 1424 * list. Shifts the element currently at that position (if any) and 1425 * any subsequent elements to the right . 1426 1427 * @param targetList the new list of source tokens 1428 * @param index the position insert the targetList 1429 * @return length of the source token list after insert targetList 1430 */ 1431 public int addAllMyTokensToTokenList(TSourceTokenList targetList, int index){ 1432 int ret = -1; 1433 1434 TSourceToken lcStartToken = getStartToken(); 1435 if (lcStartToken == null) return ret; 1436 1437 TSourceToken lcEndToken = getEndToken(); 1438 if (lcEndToken == null) return ret; 1439 1440 TSourceTokenList stList = lcStartToken.container; 1441 if (stList == null) return ret; 1442 1443 for(int i=lcEndToken.posinlist;i>=lcStartToken.posinlist;i--){ 1444 targetList.add(index,stList.get(i)); 1445 stList.get(i).container = targetList; 1446 } 1447 1448 // reindex posinlist after remove token from container 1449 for(int i=index;i<targetList.size();i++){ 1450 targetList.get(i).posinlist = i; 1451 } 1452 1453 return lcEndToken.posinlist - lcStartToken.posinlist + 1; 1454 } 1455 1456 /** 1457 * @deprecated since v1.8.8.0, use scriptWriter technology to modify the node 1458 * 1459 * @param additionalToken usually was comma before or after this parse tree node that also need to be deleted 1460 * @return length of the source token list after remove tokens 1461 */ 1462 protected int removeAllMyTokensFromTokenList(TSourceToken additionalToken){ 1463 1464 int ret = -1; 1465 TSourceToken lcStartToken = getStartToken(); 1466 if (lcStartToken == null) return ret; 1467 int lcStartTokenPos = lcStartToken.posinlist; 1468 1469 1470 TSourceToken lcEndToken = getEndToken(); 1471 if (lcEndToken == null) return ret; 1472 int lcEndTokenPos = lcEndToken.posinlist; 1473 1474 1475 TSourceTokenList stList = lcStartToken.container; 1476 if (stList == null) return ret; 1477 1478 if ((additionalToken != null)&&(additionalToken.tokentype != ETokenType.ttRemoved)){ 1479 if (additionalToken.posinlist < lcStartTokenPos){ 1480 lcStartTokenPos = additionalToken.posinlist; 1481 additionalToken.tokentype = ETokenType.ttRemoved; 1482 }else if(additionalToken.posinlist > lcEndTokenPos){ 1483 lcEndTokenPos = additionalToken.posinlist; 1484 additionalToken.tokentype = ETokenType.ttRemoved; 1485 } 1486 } 1487 1488 //reset start and end token of those parse tree node 1489 resetStartAndEndTokenBeforeRemoveTokens(stList, lcStartTokenPos, lcEndTokenPos,false,null,null); 1490 1491 // remove token from list 1492 for(int i=lcEndTokenPos;i>=lcStartTokenPos;i--){ 1493 if ((i>stList.size()-1) ||(i<0)) break; 1494 stList.remove(i); 1495 } 1496 1497 // reindex posinlist after remove token from container 1498 for(int i=lcStartTokenPos;i<stList.size();i++){ 1499 if ((i>stList.size()-1) ||(i<0)) break; 1500 stList.get(i).posinlist = i; 1501 } 1502 1503 return lcStartTokenPos - lcEndTokenPos +1; 1504 } 1505 1506 /** 1507 * @deprecated since v1.8.8.0, use scriptWriter technology to modify the node 1508 * parse string to tokens, then add those tokens to the end of this parse tree node 1509 * 1510 * @param sqlSegment 1511 */ 1512// protected void appendString(String sqlSegment){ 1513// 1514// if (sqlSegment.length() == 0) return; 1515// if (getStartToken() == null) return; 1516// if (getEndToken() == null) return; 1517// 1518// TSourceToken lcEndToken = getEndToken(); 1519// 1520// TSourceTokenList stList = lcEndToken.container; 1521// 1522// int lcEndTokenPos = lcEndToken.posinlist; 1523// 1524//// TGSqlParser l_sqlparser = new TGSqlParser(getGsqlparser().getDbVendor()); 1525//// l_sqlparser.sqltext = sqlSegment; 1526// 1527// TGSqlParser l_sqlparser; 1528// if (this.dbvendor == EDbVendor.dbvgeneric){ 1529// l_sqlparser = TGSqlParser.getSingletonParser(getGsqlparser().getDbVendor()); 1530// }else{ 1531// l_sqlparser = TGSqlParser.getSingletonParser(this.dbvendor); 1532// } 1533// 1534// synchronized(this) { 1535// l_sqlparser.tokenizeSqltext(); 1536// if (l_sqlparser.sourcetokenlist.size() == 0) return; 1537// TSourceToken endTokenOfNewSourceTokenList = l_sqlparser.sourcetokenlist.get(l_sqlparser.sourcetokenlist.size()-1); 1538// 1539// for(int i = l_sqlparser.sourcetokenlist.size()-1; i>=0; i--){ 1540// TSourceToken st = l_sqlparser.sourcetokenlist.get(i); 1541// st.container = stList; 1542// stList.add(lcEndTokenPos+1,st); 1543// } 1544// 1545// // reindex posinlist after remove token from container 1546// for(int i=lcEndTokenPos+1;i<stList.size();i++){ 1547// stList.get(i).posinlist = i; 1548// } 1549// 1550// for(int i=0;i<lcEndToken.getNodesEndWithThisToken().size();i++){ 1551// TParseTreeNode node = lcEndToken.getNodesEndWithThisToken().get(i); 1552// node.setEndToken(endTokenOfNewSourceTokenList); 1553// } 1554// } 1555// 1556//} 1557 1558 /** 1559 * Accept a visitor 1560 * 1561 * @param v visitor is a descendant class of {@link TParseTreeVisitor} 1562 */ 1563 public void accept(TParseTreeVisitor v) 1564 { 1565 1566 } 1567 1568 /** 1569 * Accept a visitor to iterate this class and sub-nodes of this class 1570 * 1571 * @param v visitor is a descendant class of {@link TParseTreeVisitor} 1572 */ 1573 public void acceptChildren(TParseTreeVisitor v) 1574 { 1575 1576 } 1577 1578 private TScriptGenerator scriptGenerator = null; 1579 1580 /** 1581 * Return the text string of this node, the return value is the same as {@link #toString()} if this node is not modified manually 1582 * after created by parser. 1583 * <br> 1584 * If this node is modified, then use this method to get string representation instead of the {@link #toString()} method. 1585 * 1586 * @return text string of this node 1587 */ 1588 public String toScript(){ 1589 if (scriptGenerator == null){ 1590 scriptGenerator = new TScriptGenerator(); 1591 } 1592 return scriptGenerator.generateScript(this); 1593 } 1594 1595 public void setChanged(){ 1596 // set the changed status to the first token of this node 1597 if (getStartToken() == null) return; 1598 getStartToken().setTokenstatus(ETokenStatus.tschanged); 1599 } 1600 1601 /** 1602 * Detect wether this node is modified by checking all tokens included in this node. 1603 * @return true if this node is modified. 1604 */ 1605 public boolean isChanged(){ 1606 boolean ret = false; 1607 TSourceToken lcStartToken = getStartToken(); 1608 if (lcStartToken == null) return ret; 1609 1610 TSourceToken lcEndToken = getEndToken(); 1611 if (lcEndToken == null) return ret; 1612 1613 TSourceTokenList stList = lcStartToken.container; 1614 if (stList == null) return ret; 1615 1616 int b = lcStartToken.posinlist; 1617 int e = lcEndToken.posinlist; 1618 1619 for(int i= b ; i<=e;i++){ 1620 if (stList.get(i).getTokenstatus() == ETokenStatus.tschanged){ 1621 ret = true; 1622 break; 1623 } 1624 } 1625 return ret; 1626 } 1627 1628 protected void doAppendNewNode( TParseTreeNode newNode, TParseTreeNode anchorNode,boolean needCommaBefore){ 1629 if (anchorNode != null){ 1630 anchorNode.appendNewNode(newNode,needCommaBefore); 1631 }else{ 1632 if (!newNode.isTokensInChain()){ 1633 this.appendNewNode(newNode,false); 1634 this.setEndToken(newNode.getEndToken()); 1635 } 1636 } 1637 } 1638 1639 private TParseTreeNode anchorNode = null; 1640 1641 public void setAnchorNode(TParseTreeNode anchorNode) { 1642 this.anchorNode = anchorNode; 1643 } 1644 1645 public TParseTreeNode getAnchorNode() { 1646 return anchorNode; 1647 } 1648 1649 public void setNewSubNode( TParseTreeNode oldSubNode, TParseTreeNode newSubNode,TParseTreeNode anchorNode){ 1650 if (newSubNode == null){ 1651 //remove the old node 1652 if (oldSubNode != null){ 1653 oldSubNode.removeTokens(); 1654 } 1655 }else { 1656 if (oldSubNode == null){ 1657 // add a total new where clause, we need to find an anchor 1658 if (newSubNode.getNodeStatus()!=ENodeStatus.nsNormal){ 1659 doAppendNewNode(newSubNode,anchorNode,false); 1660 } 1661 1662 }else{ 1663 //replace old where clause 1664 if (newSubNode.getNodeStatus()!=ENodeStatus.nsNormal){ 1665 oldSubNode.replaceWithNewNode(newSubNode); 1666 } 1667 } 1668 } 1669 } 1670 1671 public static boolean subNodeInNode(TParseTreeNode subNode, TParseTreeNode wholeNode){ 1672 if (wholeNode == null) return false; 1673 TSourceToken startToken = wholeNode.getStartToken(); 1674 if (startToken == null) return false; 1675 TSourceToken endToken = wholeNode.getEndToken(); 1676 if (endToken == null) return false; 1677 1678 TSourceToken startTokenOfSubNode = subNode.getStartToken(); 1679 if (startTokenOfSubNode == null) return false; 1680 if (startTokenOfSubNode.lineNo < startToken.lineNo) return false; 1681 if ((startTokenOfSubNode.lineNo == startToken.lineNo) && (startTokenOfSubNode.columnNo < startToken.columnNo)) return false; 1682 1683 TSourceToken endTokenOfSubNode = subNode.getEndToken(); 1684 if (endTokenOfSubNode == null) return false; 1685 1686 if (endTokenOfSubNode.lineNo > endToken.lineNo) return false; 1687 if ((endTokenOfSubNode.lineNo == endToken.lineNo)&&(endTokenOfSubNode.columnNo > endToken.columnNo)) return false; 1688 1689 return true; 1690 } 1691 1692// public int setText(EDbVendor dbVendor, String sqlText){ 1693// TGSqlParser sqlParser = new TGSqlParser(dbvendor); 1694// sqlParser.sqltext = sqlText; 1695// sqlParser.tokenizeSqltext(); 1696// 1697// } 1698 1699} 1700