001 package railo.transformer.bytecode.statement.tag; 002 003 import org.objectweb.asm.Label; 004 import org.objectweb.asm.Opcodes; 005 import org.objectweb.asm.Type; 006 import org.objectweb.asm.commons.GeneratorAdapter; 007 import org.objectweb.asm.commons.Method; 008 009 import railo.runtime.exp.TemplateException; 010 import railo.runtime.type.scope.Undefined; 011 import railo.runtime.util.NumberIterator; 012 import railo.transformer.bytecode.BytecodeContext; 013 import railo.transformer.bytecode.BytecodeException; 014 import railo.transformer.bytecode.Statement; 015 import railo.transformer.bytecode.expression.Expression; 016 import railo.transformer.bytecode.util.Types; 017 import railo.transformer.bytecode.visitor.DecisionIntVisitor; 018 import railo.transformer.bytecode.visitor.NotVisitor; 019 import railo.transformer.bytecode.visitor.ParseBodyVisitor; 020 import railo.transformer.bytecode.visitor.TryFinallyVisitor; 021 import railo.transformer.bytecode.visitor.WhileVisitor; 022 023 public final class TagOutput extends TagBase { 024 025 026 public static final int TYPE_QUERY = 0; 027 public static final int TYPE_GROUP = 1; 028 public static final int TYPE_INNER_GROUP = 2; 029 public static final int TYPE_INNER_QUERY = 3; 030 public static final int TYPE_NORMAL= 4; 031 032 // int getCurrentrow() 033 public static final Method GET_CURRENTROW = new Method( 034 "getCurrentrow", 035 Types.INT_VALUE, 036 new Type[]{}); 037 038 // Undefined us() 039 public static final Type UNDEFINED = Type.getType(Undefined.class); 040 public static final Method US = new Method( 041 "us", 042 UNDEFINED, 043 new Type[]{}); 044 045 // void addCollection(Query coll) 046 public static final Method ADD_COLLECTION = new Method( 047 "addCollection", 048 Types.VOID, 049 new Type[]{Types.QUERY}); 050 051 // void removeCollection() 052 public static final Method REMOVE_COLLECTION = new Method( 053 "removeCollection", 054 Types.VOID, 055 new Type[]{}); 056 057 058 059 // Query getQuery(String key) 060 public static final Method GET_QUERY = new Method( 061 "getQuery", 062 Types.QUERY, 063 new Type[]{Types.STRING}); 064 065 // int getRecordcount() 066 public static final Method GET_RECORDCOUNT = new Method( 067 "getRecordcount", 068 Types.INT_VALUE, 069 new Type[]{}); 070 071 // double range(double number, double from) 072 public static final Method RANGE = new Method( 073 "range", 074 Types.DOUBLE_VALUE, 075 new Type[]{Types.DOUBLE_VALUE,Types.DOUBLE_VALUE}); 076 077 public static final Type NUMBER_ITERATOR = Type.getType(NumberIterator.class); 078 079 // NumberIterator load(double from, double to, double max) 080 public static final Method LOAD_3 = new Method( 081 "load", 082 NUMBER_ITERATOR, 083 new Type[]{Types.DOUBLE_VALUE,Types.DOUBLE_VALUE,Types.DOUBLE_VALUE}); 084 085 086 // NumberIterator load(double from, double to, double max) 087 public static final Method LOAD_2 = new Method( 088 "load", 089 NUMBER_ITERATOR, 090 new Type[]{Types.DOUBLE_VALUE,Types.DOUBLE_VALUE}); 091 092 093 // NumberIterator load(NumberIterator ni, Query query, String groupName, boolean caseSensitive) 094 public static final Method LOAD_5 = new Method( 095 "load", 096 NUMBER_ITERATOR, 097 new Type[]{Types.PAGE_CONTEXT, NUMBER_ITERATOR,Types.QUERY,Types.STRING,Types.BOOLEAN_VALUE}); 098 099 // boolean isValid() 100 public static final Method IS_VALID = new Method( 101 "isValid", 102 Types.BOOLEAN_VALUE, 103 new Type[]{}); 104 105 // int current() 106 public static final Method CURRENT = new Method( 107 "current", 108 Types.INT_VALUE, 109 new Type[]{}); 110 111 // void release(NumberIterator ni) 112 public static final Method REALEASE = new Method( 113 "release", 114 Types.VOID, 115 new Type[]{NUMBER_ITERATOR}); 116 117 // void setCurrent(int current) 118 public static final Method SET_CURRENT = new Method( 119 "setCurrent", 120 Types.VOID, 121 new Type[]{Types.INT_VALUE}); 122 123 124 // void reset() 125 public static final Method RESET = new Method( 126 "reset", 127 Types.VOID, 128 new Type[]{Types.INT_VALUE}); 129 130 // int first() 131 public static final Method FIRST = new Method( 132 "first", 133 Types.INT_VALUE, 134 new Type[]{}); 135 private static final Method GET_ID = new Method( 136 "getId", 137 Types.INT_VALUE, 138 new Type[]{}); 139 140 141 private int type; 142 143 private int numberIterator=-1; 144 private int query=-1; 145 //private int queryImpl=-1; 146 private int group=-1; 147 148 149 150 public TagOutput(int line) { 151 super(line); 152 } 153 public TagOutput(int sl,int el) { 154 super(sl,el); 155 } 156 157 158 public static TagOutput getParentTagOutputQuery(Statement stat) throws BytecodeException { 159 Statement parent=stat.getParent(); 160 if(parent==null) throw new BytecodeException("there is no parent output with query",-1); 161 else if(parent instanceof TagOutput) { 162 if(((TagOutput)parent).hasQuery()) 163 return ((TagOutput)parent); 164 } 165 return getParentTagOutputQuery(parent); 166 } 167 168 public void setType(int type) { 169 this.type=type; 170 } 171 172 173 /** 174 * 175 * @see railo.transformer.bytecode.statement.tag.TagBase#_writeOut(org.objectweb.asm.commons.GeneratorAdapter) 176 */ 177 public void _writeOut(BytecodeContext bc) throws BytecodeException { 178 boolean old; 179 switch(type) { 180 case TYPE_GROUP: 181 old = bc.changeDoSubFunctions(false); 182 writeOutTypeGroup(bc); 183 bc.changeDoSubFunctions(old); 184 break; 185 case TYPE_INNER_GROUP: 186 old = bc.changeDoSubFunctions(false); 187 writeOutTypeInnerGroup(bc); 188 bc.changeDoSubFunctions(old); 189 break; 190 case TYPE_INNER_QUERY: 191 old = bc.changeDoSubFunctions(false); 192 writeOutTypeInnerQuery(bc); 193 bc.changeDoSubFunctions(old); 194 break; 195 case TYPE_NORMAL: 196 writeOutTypeNormal(bc); 197 break; 198 case TYPE_QUERY: 199 old = bc.changeDoSubFunctions(false); 200 writeOutTypeQuery(bc); 201 bc.changeDoSubFunctions(old); 202 break; 203 204 default: 205 throw new BytecodeException("invalid type",getLine()); 206 } 207 } 208 209 210 private void writeOutTypeGroup(BytecodeContext bc) throws BytecodeException { 211 GeneratorAdapter adapter = bc.getAdapter(); 212 ParseBodyVisitor pbv=new ParseBodyVisitor(); 213 pbv.visitBegin(bc); 214 215 // Group 216 Attribute attrGroup = getAttribute("group"); 217 group=adapter.newLocal(Types.STRING); 218 attrGroup.getValue().writeOut(bc, Expression.MODE_REF); 219 adapter.storeLocal(group); 220 221 // Group Case Sensitve 222 Attribute attrGroupCS = getAttribute("groupcasesensitive"); 223 int groupCaseSensitive=adapter.newLocal(Types.BOOLEAN_VALUE); 224 if(attrGroupCS!=null) attrGroupCS.getValue().writeOut(bc, Expression.MODE_VALUE); 225 else adapter.push(true); 226 adapter.storeLocal(groupCaseSensitive); 227 228 TagOutput parent = TagOutput.getParentTagOutputQuery(this); 229 numberIterator = parent.getNumberIterator(); 230 query = parent.getQuery(); 231 //queryImpl = parent.getQueryImpl(); 232 233 // current 234 int current=adapter.newLocal(Types.INT_VALUE); 235 adapter.loadLocal(numberIterator); 236 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 237 adapter.storeLocal(current); 238 239 240 // current 241 int icurrent=adapter.newLocal(Types.INT_VALUE); 242 WhileVisitor wv = new WhileVisitor(); 243 wv.visitBeforeExpression(bc); 244 245 //while(ni.isValid()) { 246 adapter.loadLocal(numberIterator); 247 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.IS_VALID); 248 249 wv.visitAfterExpressionBeforeBody(bc); 250 251 // if(!query.go(ni.current()))break; 252 adapter.loadLocal(query); 253 adapter.loadLocal(numberIterator); 254 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 255 /* FUTURE 256 adapter.loadArg(0); 257 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 258 adapter.invokeInterface(Types.QUERY, TagLoop.GO_2); 259 */ 260 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 261 262 NotVisitor.visitNot(bc); 263 Label _if=new Label(); 264 adapter.ifZCmp(Opcodes.IFEQ, _if); 265 wv.visitBreak(bc); 266 adapter.visitLabel(_if); 267 268 // NumberIterator oldNi=numberIterator; 269 int oldNi=adapter.newLocal(TagOutput.NUMBER_ITERATOR); 270 271 adapter.loadLocal(numberIterator); 272 adapter.storeLocal(oldNi); 273 274 // numberIterator=NumberIterator.load(ni,query,group,grp_case); 275 adapter.loadArg(0); 276 adapter.loadLocal(numberIterator); 277 adapter.loadLocal(query); 278 adapter.loadLocal(group); 279 adapter.loadLocal(groupCaseSensitive); 280 adapter.invokeStatic(TagOutput.NUMBER_ITERATOR, TagOutput.LOAD_5); 281 adapter.storeLocal(numberIterator); 282 283 // current=oldNi.current(); 284 adapter.loadLocal(oldNi); 285 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 286 adapter.storeLocal(icurrent); 287 288 getBody().writeOut(bc); 289 290 //tmp(adapter,current); 291 292 293 // NumberIterator.release(ni); 294 adapter.loadLocal(numberIterator); 295 adapter.invokeStatic(TagOutput.NUMBER_ITERATOR, TagOutput.REALEASE); 296 297 // numberIterator=oldNi; 298 adapter.loadLocal(oldNi); 299 adapter.storeLocal(numberIterator); 300 301 // ni.setCurrent(current+1); 302 adapter.loadLocal(numberIterator); 303 adapter.loadLocal(icurrent); 304 adapter.push(1); 305 adapter.visitInsn(Opcodes.IADD); 306 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.SET_CURRENT); 307 308 wv.visitAfterBody(bc,getEndLine()); 309 310 311 //query.go(ni.current(),pc.getId()) 312 resetCurrentrow(adapter,current); 313 314 // ni.first(); 315 adapter.loadLocal(numberIterator); 316 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.FIRST); 317 adapter.pop(); 318 319 320 pbv.visitEnd(bc); 321 } 322 323 324 private void resetCurrentrow(GeneratorAdapter adapter, int current) { 325 //query.go(ni.current(),pc.getId()) 326 adapter.loadLocal(query); 327 adapter.loadLocal(current); 328 /* FUTURE 329 adapter.loadArg(0); 330 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 331 adapter.invokeInterface(Types.QUERY, TagLoop.GO_2); 332 */ 333 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 334 335 adapter.pop(); 336 337 } 338 private void writeOutTypeInnerGroup(BytecodeContext bc) throws BytecodeException { 339 GeneratorAdapter adapter = bc.getAdapter(); 340 341 TagOutput parent = TagOutput.getParentTagOutputQuery(this); 342 numberIterator = parent.getNumberIterator(); 343 query = parent.getQuery(); 344 //queryImpl = parent.getQueryImpl(); 345 346 int current=adapter.newLocal(Types.INT_VALUE); 347 adapter.loadLocal(numberIterator); 348 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 349 adapter.storeLocal(current); 350 351 352 // inner current 353 int icurrent=adapter.newLocal(Types.INT_VALUE); 354 WhileVisitor wv = new WhileVisitor(); 355 wv.visitBeforeExpression(bc); 356 357 //while(ni.isValid()) { 358 adapter.loadLocal(numberIterator); 359 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.IS_VALID); 360 361 wv.visitAfterExpressionBeforeBody(bc); 362 363 // if(!query.go(ni.current()))break; 364 365 adapter.loadLocal(query); 366 adapter.loadLocal(numberIterator); 367 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 368 /*FUTURE 369 adapter.loadArg(0); 370 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 371 adapter.invokeInterface(Types.QUERY, TagLoop.GO_2); 372 */ 373 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 374 375 NotVisitor.visitNot(bc); 376 Label _if=new Label(); 377 adapter.ifZCmp(Opcodes.IFEQ, _if); 378 wv.visitBreak(bc); 379 adapter.visitLabel(_if); 380 381 // current=ni.current(); 382 adapter.loadLocal(numberIterator); 383 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 384 adapter.storeLocal(icurrent); 385 386 getBody().writeOut(bc); 387 388 // ni.setCurrent(current+1); 389 adapter.loadLocal(numberIterator); 390 adapter.loadLocal(icurrent); 391 adapter.push(1); 392 adapter.visitInsn(Opcodes.IADD); 393 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.SET_CURRENT); 394 395 wv.visitAfterBody(bc,getEndLine()); 396 397 resetCurrentrow(adapter,current); 398 399 400 // ni.first(); 401 adapter.loadLocal(numberIterator); 402 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.FIRST); 403 adapter.pop(); 404 } 405 406 407 private void writeOutTypeInnerQuery(BytecodeContext bc) throws BytecodeException { 408 GeneratorAdapter adapter = bc.getAdapter(); 409 //if(tr ue)return ; 410 TagOutput parent = TagOutput.getParentTagOutputQuery(this); 411 numberIterator = parent.getNumberIterator(); 412 query = parent.getQuery(); 413 //queryImpl = parent.getQueryImpl(); 414 415 //int currentOuter=ni.current(); 416 int currentOuter=adapter.newLocal(Types.INT_VALUE); 417 adapter.loadLocal(numberIterator); 418 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 419 adapter.storeLocal(currentOuter); 420 421 // current 422 int current=adapter.newLocal(Types.INT_VALUE); 423 424 WhileVisitor wv = new WhileVisitor(); 425 wv.visitBeforeExpression(bc); 426 427 //while(ni.isValid()) { 428 adapter.loadLocal(numberIterator); 429 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.IS_VALID); 430 431 wv.visitAfterExpressionBeforeBody(bc); 432 433 // if(!query.go(ni.current()))break; 434 adapter.loadLocal(query); 435 adapter.loadLocal(numberIterator); 436 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 437 /* FUTURE 438 adapter.loadArg(0); 439 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 440 adapter.invokeInterface(Types.QUERY, TagLoop.GO_2); 441 */ 442 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 443 444 NotVisitor.visitNot(bc); 445 Label _if=new Label(); 446 adapter.ifZCmp(Opcodes.IFEQ, _if); 447 wv.visitBreak(bc); 448 adapter.visitLabel(_if); 449 450 // current=ni.current(); 451 adapter.loadLocal(numberIterator); 452 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 453 adapter.storeLocal(current); 454 455 getBody().writeOut(bc); 456 457 // ni.setCurrent(current+1); 458 adapter.loadLocal(numberIterator); 459 adapter.loadLocal(current); 460 adapter.push(1); 461 adapter.visitInsn(Opcodes.IADD); 462 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.SET_CURRENT); 463 464 wv.visitAfterBody(bc,getEndLine()); 465 466 467 // ni.setCurrent(currentOuter); 468 adapter.loadLocal(numberIterator); 469 adapter.loadLocal(currentOuter); 470 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.SET_CURRENT); 471 472 adapter.loadLocal(query); 473 adapter.loadLocal(currentOuter); 474 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 475 adapter.pop(); 476 //adapter.pop(); 477 } 478 479 480 /** 481 * write out normal query 482 * @param adapter 483 * @throws TemplateException 484 */ 485 private void writeOutTypeNormal(BytecodeContext bc) throws BytecodeException { 486 ParseBodyVisitor pbv=new ParseBodyVisitor(); 487 pbv.visitBegin(bc); 488 getBody().writeOut(bc); 489 pbv.visitEnd(bc); 490 } 491 492 493 private void writeOutTypeQuery(BytecodeContext bc) throws BytecodeException { 494 GeneratorAdapter adapter = bc.getAdapter(); 495 496 numberIterator = adapter.newLocal(TagOutput.NUMBER_ITERATOR); 497 ParseBodyVisitor pbv=new ParseBodyVisitor(); 498 pbv.visitBegin(bc); 499 500 501 // Query query=pc.getQuery(@query); 502 query =adapter.newLocal(Types.QUERY); 503 adapter.loadArg(0); 504 getAttribute("query").getValue().writeOut(bc, Expression.MODE_REF); 505 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagOutput.GET_QUERY); 506 //adapter.dup(); 507 adapter.storeLocal(query); 508 509 //queryImpl = adapter.newLocal(Types.QUERY_IMPL); 510 //adapter.checkCast(Types.QUERY_IMPL); 511 //adapter.storeLocal(queryImpl); 512 513 514 515 // int startAt=query.getCurrentrow(); 516 int startAt=adapter.newLocal(Types.INT_VALUE); 517 adapter.loadLocal(query); 518 519 /* FUTURE 520 adapter.loadArg(0); 521 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagLoop.GET_ID); 522 adapter.invokeInterface(Types.QUERY_IMPL, TagLoop.GET_CURRENTROW_1); 523 */ 524 adapter.invokeInterface(Types.QUERY, TagLoop.GET_CURRENTROW_0); 525 526 adapter.storeLocal(startAt); 527 528 529 530 // if(query.getRecordcount()>0) { 531 DecisionIntVisitor div=new DecisionIntVisitor(); 532 div.visitBegin(); 533 adapter.loadLocal(query); 534 adapter.invokeInterface(Types.QUERY, TagOutput.GET_RECORDCOUNT); 535 div.visitGT(); 536 adapter.push(0); 537 div.visitEnd(bc); 538 Label ifRecCount=new Label(); 539 adapter.ifZCmp(Opcodes.IFEQ, ifRecCount); 540 541 // startrow 542 int from = adapter.newLocal(Types.DOUBLE_VALUE); 543 Attribute attrStartRow = getAttribute("startrow"); 544 if(attrStartRow!=null){ 545 // NumberRange.range(@startrow,1) 546 attrStartRow.getValue().writeOut(bc, Expression.MODE_VALUE); 547 adapter.push(1d); 548 adapter.invokeStatic(Types.NUMBER_RANGE, TagOutput.RANGE); 549 //adapter.visitInsn(Opcodes.D2I); 550 } 551 else { 552 adapter.push(1d); 553 } 554 adapter.storeLocal(from); 555 556 // numberIterator 557 558 Attribute attrMaxRow = getAttribute("maxrows"); 559 560 adapter.loadLocal(from); 561 adapter.loadLocal(query); 562 adapter.invokeInterface(Types.QUERY, TagOutput.GET_RECORDCOUNT); 563 adapter.visitInsn(Opcodes.I2D); 564 if(attrMaxRow!=null) { 565 attrMaxRow.getValue().writeOut(bc, Expression.MODE_VALUE); 566 adapter.invokeStatic(TagOutput.NUMBER_ITERATOR, TagOutput.LOAD_3); 567 } 568 else { 569 adapter.invokeStatic(TagOutput.NUMBER_ITERATOR, TagOutput.LOAD_2); 570 } 571 adapter.storeLocal(numberIterator); 572 573 // Group 574 Attribute attrGroup = getAttribute("group"); 575 Attribute attrGroupCS = getAttribute("groupcasesensitive"); 576 group=adapter.newLocal(Types.STRING); 577 int groupCaseSensitive=adapter.newLocal(Types.BOOLEAN_VALUE); 578 if(attrGroup!=null) { 579 attrGroup.getValue().writeOut(bc, Expression.MODE_REF); 580 adapter.storeLocal(group); 581 582 if(attrGroupCS!=null) attrGroupCS.getValue().writeOut(bc, Expression.MODE_VALUE); 583 else adapter.push(true); 584 adapter.storeLocal(groupCaseSensitive); 585 } 586 587 // pc.us().addCollection(query); 588 adapter.loadArg(0); 589 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagOutput.US); 590 adapter.loadLocal(query); 591 adapter.invokeInterface(TagOutput.UNDEFINED, TagOutput.ADD_COLLECTION); 592 593 // current 594 int current=adapter.newLocal(Types.INT_VALUE); 595 596 // Try 597 TryFinallyVisitor tfv=new TryFinallyVisitor(); 598 tfv.visitTryBegin(bc); 599 WhileVisitor wv = new WhileVisitor(); 600 wv.visitBeforeExpression(bc); 601 602 //while(ni.isValid()) { 603 adapter.loadLocal(numberIterator); 604 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.IS_VALID); 605 606 wv.visitAfterExpressionBeforeBody(bc); 607 608 // if(!query.go(ni.current()))break; 609 adapter.loadLocal(query); 610 adapter.loadLocal(numberIterator); 611 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 612 /* FUTURE 613 adapter.loadArg(0); 614 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 615 adapter.invokeInterface(Types.QUERY, TagLoop.GO_2); 616 */ 617 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 618 619 NotVisitor.visitNot(bc); 620 Label _if=new Label(); 621 adapter.ifZCmp(Opcodes.IFEQ, _if); 622 wv.visitBreak(bc); 623 adapter.visitLabel(_if); 624 625 if(attrGroup!=null) { 626 // NumberIterator oldNi=numberIterator; 627 int oldNi=adapter.newLocal(TagOutput.NUMBER_ITERATOR); 628 adapter.loadLocal(numberIterator); 629 adapter.storeLocal(oldNi); 630 631 // numberIterator=NumberIterator.load(ni,query,group,grp_case); 632 adapter.loadArg(0); 633 adapter.loadLocal(numberIterator); 634 adapter.loadLocal(query); 635 adapter.loadLocal(group); 636 adapter.loadLocal(groupCaseSensitive); 637 adapter.invokeStatic(TagOutput.NUMBER_ITERATOR, TagOutput.LOAD_5); 638 adapter.storeLocal(numberIterator); 639 640 // current=oldNi.current(); 641 adapter.loadLocal(oldNi); 642 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 643 adapter.storeLocal(current); 644 645 getBody().writeOut(bc); 646 647 //tmp(adapter,current); 648 649 // NumberIterator.release(ni); 650 adapter.loadLocal(numberIterator); 651 adapter.invokeStatic(TagOutput.NUMBER_ITERATOR, TagOutput.REALEASE); 652 653 // numberIterator=oldNi; 654 adapter.loadLocal(oldNi); 655 adapter.storeLocal(numberIterator); 656 } 657 else { 658 // current=ni.current(); 659 adapter.loadLocal(numberIterator); 660 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.CURRENT); 661 adapter.storeLocal(current); 662 663 getBody().writeOut(bc); 664 } 665 666 // ni.setCurrent(current+1); 667 adapter.loadLocal(numberIterator); 668 adapter.loadLocal(current); 669 adapter.push(1); 670 adapter.visitInsn(Opcodes.IADD); 671 adapter.invokeVirtual(TagOutput.NUMBER_ITERATOR, TagOutput.SET_CURRENT); 672 673 wv.visitAfterBody(bc,getEndLine()); 674 675 tfv.visitTryEndFinallyBegin(bc); 676 677 // query.reset(); 678 /*adapter.loadLocal(queryImpl); 679 adapter.loadArg(0); 680 adapter.invokeVirtual(Types.PAGE_CONTEXT, GET_ID); 681 adapter.invokeVirtual(Types.QUERY_IMPL, TagOutput.RESET);*/ 682 683 // query.go(startAt); 684 adapter.loadLocal(query); 685 adapter.loadLocal(startAt); 686 /* FUTURE 687 adapter.loadArg(0); 688 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagLoop.GET_ID); 689 adapter.invokeInterface(Types.QUERY, TagLoop.GO_2); 690 */ 691 adapter.invokeInterface(Types.QUERY, TagLoop.GO_1); 692 693 adapter.pop(); 694 695 696 697 698 // pc.us().removeCollection(); 699 adapter.loadArg(0); 700 adapter.invokeVirtual(Types.PAGE_CONTEXT, TagOutput.US); 701 adapter.invokeInterface(TagOutput.UNDEFINED, TagOutput.REMOVE_COLLECTION); 702 703 // NumberIterator.release(ni); 704 adapter.loadLocal(numberIterator); 705 adapter.invokeStatic(TagOutput.NUMBER_ITERATOR, TagOutput.REALEASE); 706 707 708 tfv.visitFinallyEnd(bc); 709 710 adapter.visitLabel(ifRecCount); 711 712 713 pbv.visitEnd(bc); 714 } 715 716 717 718 /** 719 * returns numberiterator of output 720 * @return numberiterator 721 */ 722 public int getNumberIterator() { 723 return numberIterator; 724 } 725 726 /** 727 * returns query of output 728 * @return query 729 */ 730 public int getQuery() { 731 return query; 732 } 733 734 /*public int getQueryImpl() { 735 return queryImpl; 736 }*/ 737 738 /** 739 * returns query of output 740 * @return query 741 */ 742 public int getGroup() { 743 return group; 744 } 745 746 /** 747 * returns if output has numberiterator 748 * @return has numberiterator 749 */ 750 public boolean hasNumberIterator() { 751 return numberIterator!=-1; 752 } 753 754 /** 755 * returns if output has query 756 * @return has query 757 */ 758 public boolean hasQuery() { 759 return getAttribute("query")!=null; 760 } 761 762 /** 763 * returns if output has query 764 * @return has query 765 */ 766 public boolean hasGroup() { 767 return getAttribute("group")!=null; 768 } 769 770 771 }