1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.text.Collator ; 23 import java.util.ArrayList ; 24 import java.util.NoSuchElementException ; 25 import java.util.StringTokenizer ; 26 import java.util.Vector ; 27 28 import org.apache.bcel.classfile.Field; 29 import org.apache.bcel.classfile.Method; 30 import org.apache.bcel.generic.ALOAD; 31 import org.apache.bcel.generic.ANEWARRAY; 32 import org.apache.bcel.generic.CHECKCAST; 33 import org.apache.bcel.generic.ConstantPoolGen; 34 import org.apache.bcel.generic.GETFIELD; 35 import org.apache.bcel.generic.ICONST; 36 import org.apache.bcel.generic.ILOAD; 37 import org.apache.bcel.generic.INVOKEINTERFACE; 38 import org.apache.bcel.generic.INVOKESPECIAL; 39 import org.apache.bcel.generic.INVOKESTATIC; 40 import org.apache.bcel.generic.INVOKEVIRTUAL; 41 import org.apache.bcel.generic.InstructionHandle; 42 import org.apache.bcel.generic.InstructionList; 43 import org.apache.bcel.generic.NEW; 44 import org.apache.bcel.generic.NOP; 45 import org.apache.bcel.generic.PUSH; 46 import org.apache.bcel.generic.PUTFIELD; 47 import org.apache.bcel.generic.TABLESWITCH; 48 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 49 import org.apache.xalan.xsltc.compiler.util.CompareGenerator; 50 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 51 import org.apache.xalan.xsltc.compiler.util.IntType; 52 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 53 import org.apache.xalan.xsltc.compiler.util.NodeSortRecordFactGenerator; 54 import org.apache.xalan.xsltc.compiler.util.NodeSortRecordGenerator; 55 import org.apache.xalan.xsltc.compiler.util.StringType; 56 import org.apache.xalan.xsltc.compiler.util.Type; 57 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 58 import org.apache.xalan.xsltc.compiler.util.Util; 59 import org.apache.xalan.xsltc.dom.Axis; 60 61 62 67 final class Sort extends Instruction implements Closure { 68 69 private Expression _select; 70 private AttributeValue _order; 71 private AttributeValue _caseOrder; 72 private AttributeValue _dataType; 73 private String _lang; 75 private String _data = null; 76 77 78 private String _className = null; 79 private ArrayList _closureVars = null; 80 private boolean _needsSortRecordFactory = false; 81 82 84 88 public boolean inInnerClass() { 89 return (_className != null); 90 } 91 92 95 public Closure getParentClosure() { 96 return null; 97 } 98 99 103 public String getInnerClassName() { 104 return _className; 105 } 106 107 110 public void addVariable(VariableRefBase variableRef) { 111 if (_closureVars == null) { 112 _closureVars = new ArrayList (); 113 } 114 115 if (!_closureVars.contains(variableRef)) { 117 _closureVars.add(variableRef); 118 _needsSortRecordFactory = true; 119 } 120 } 121 122 124 private void setInnerClassName(String className) { 125 _className = className; 126 } 127 128 131 public void parseContents(Parser parser) { 132 133 final SyntaxTreeNode parent = getParent(); 134 if (!(parent instanceof ApplyTemplates) && 135 !(parent instanceof ForEach)) { 136 reportError(this, parser, ErrorMsg.STRAY_SORT_ERR, null); 137 return; 138 } 139 140 _select = parser.parseExpression(this, "select", "string(.)"); 142 143 String val = getAttribute("order"); 145 if (val.length() == 0) val = "ascending"; 146 _order = AttributeValue.create(this, val, parser); 147 148 val = getAttribute("data-type"); 150 if (val.length() == 0) { 151 try { 152 final Type type = _select.typeCheck(parser.getSymbolTable()); 153 if (type instanceof IntType) 154 val = "number"; 155 else 156 val = "text"; 157 } 158 catch (TypeCheckError e) { 159 val = "text"; 160 } 161 } 162 _dataType = AttributeValue.create(this, val, parser); 163 164 _lang = getAttribute("lang"); val = getAttribute("case-order"); 169 _caseOrder = AttributeValue.create(this, val, parser); 170 171 } 172 173 177 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 178 final Type tselect = _select.typeCheck(stable); 179 180 if (!(tselect instanceof StringType)) { 183 _select = new CastExpr(_select, Type.String); 184 } 185 186 _order.typeCheck(stable); 187 _caseOrder.typeCheck(stable); 188 _dataType.typeCheck(stable); 189 return Type.Void; 190 } 191 192 196 public void translateSortType(ClassGenerator classGen, 197 MethodGenerator methodGen) { 198 _dataType.translate(classGen, methodGen); 199 } 200 201 public void translateSortOrder(ClassGenerator classGen, 202 MethodGenerator methodGen) { 203 _order.translate(classGen, methodGen); 204 } 205 206 public void translateCaseOrder(ClassGenerator classGen, 207 MethodGenerator methodGen) { 208 _caseOrder.translate(classGen, methodGen); 209 } 210 211 public void translateLang(ClassGenerator classGen, 212 MethodGenerator methodGen) { 213 final ConstantPoolGen cpg = classGen.getConstantPool(); 214 final InstructionList il = methodGen.getInstructionList(); 215 il.append(new PUSH(cpg, _lang)); } 217 218 223 public void translateSelect(ClassGenerator classGen, 224 MethodGenerator methodGen) { 225 _select.translate(classGen,methodGen); 226 } 227 228 231 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 232 } 234 235 240 public static void translateSortIterator(ClassGenerator classGen, 241 MethodGenerator methodGen, 242 Expression nodeSet, 243 Vector sortObjects) 244 { 245 final ConstantPoolGen cpg = classGen.getConstantPool(); 246 final InstructionList il = methodGen.getInstructionList(); 247 248 final int init = cpg.addMethodref(SORT_ITERATOR, "<init>", 250 "(" 251 + NODE_ITERATOR_SIG 252 + NODE_SORT_FACTORY_SIG 253 + ")V"); 254 255 il.append(new NEW(cpg.addClass(SORT_ITERATOR))); 256 il.append(DUP); 257 258 if (nodeSet == null) { final int children = cpg.addInterfaceMethodref(DOM_INTF, 261 "getAxisIterator", 262 "(I)"+ 263 NODE_ITERATOR_SIG); 264 il.append(methodGen.loadDOM()); 265 il.append(new PUSH(cpg, Axis.CHILD)); 266 il.append(new INVOKEINTERFACE(children, 2)); 267 } 268 else { 269 nodeSet.translate(classGen, methodGen); 270 } 271 272 compileSortRecordFactory(sortObjects, classGen, methodGen); 275 il.append(new INVOKESPECIAL(init)); 276 } 277 278 279 283 public static void compileSortRecordFactory(Vector sortObjects, 284 ClassGenerator classGen, MethodGenerator methodGen) 285 { 286 String sortRecordClass = 287 compileSortRecord(sortObjects, classGen, methodGen); 288 289 boolean needsSortRecordFactory = false; 290 final int nsorts = sortObjects.size(); 291 for (int i = 0; i < nsorts; i++) { 292 final Sort sort = (Sort) sortObjects.elementAt(i); 293 needsSortRecordFactory |= sort._needsSortRecordFactory; 294 } 295 296 String sortRecordFactoryClass = NODE_SORT_FACTORY; 297 if (needsSortRecordFactory) { 298 sortRecordFactoryClass = 299 compileSortRecordFactory(sortObjects, classGen, methodGen, 300 sortRecordClass); 301 } 302 303 final ConstantPoolGen cpg = classGen.getConstantPool(); 304 final InstructionList il = methodGen.getInstructionList(); 305 306 il.append(new NEW(cpg.addClass(sortRecordFactoryClass))); 307 il.append(DUP); 308 il.append(methodGen.loadDOM()); 309 il.append(new PUSH(cpg, sortRecordClass)); 310 il.append(classGen.loadTranslet()); 311 312 il.append(new PUSH(cpg, nsorts)); 314 il.append(new ANEWARRAY(cpg.addClass(STRING))); 315 for (int level = 0; level < nsorts; level++) { 316 final Sort sort = (Sort)sortObjects.elementAt(level); 317 il.append(DUP); 318 il.append(new PUSH(cpg, level)); 319 sort.translateSortOrder(classGen, methodGen); 320 il.append(AASTORE); 321 } 322 323 il.append(new PUSH(cpg, nsorts)); 324 il.append(new ANEWARRAY(cpg.addClass(STRING))); 325 for (int level = 0; level < nsorts; level++) { 326 final Sort sort = (Sort)sortObjects.elementAt(level); 327 il.append(DUP); 328 il.append(new PUSH(cpg, level)); 329 sort.translateSortType(classGen, methodGen); 330 il.append(AASTORE); 331 } 332 333 il.append(new PUSH(cpg, nsorts)); 334 il.append(new ANEWARRAY(cpg.addClass(STRING))); 335 for (int level = 0; level < nsorts; level++) { 336 final Sort sort = (Sort)sortObjects.elementAt(level); 337 il.append(DUP); 338 il.append(new PUSH(cpg, level)); 339 sort.translateLang(classGen, methodGen); 340 il.append(AASTORE); 341 } 342 343 il.append(new PUSH(cpg, nsorts)); 344 il.append(new ANEWARRAY(cpg.addClass(STRING))); 345 for (int level = 0; level < nsorts; level++) { 346 final Sort sort = (Sort)sortObjects.elementAt(level); 347 il.append(DUP); 348 il.append(new PUSH(cpg, level)); 349 sort.translateCaseOrder(classGen, methodGen); 350 il.append(AASTORE); 351 } 352 353 il.append(new INVOKESPECIAL( 354 cpg.addMethodref(sortRecordFactoryClass, "<init>", 355 "(" + DOM_INTF_SIG 356 + STRING_SIG 357 + TRANSLET_INTF_SIG 358 + "[" + STRING_SIG 359 + "[" + STRING_SIG 360 + "[" + STRING_SIG 361 + "[" + STRING_SIG + ")V"))); 362 363 final ArrayList dups = new ArrayList (); 365 366 for (int j = 0; j < nsorts; j++) { 367 final Sort sort = (Sort) sortObjects.get(j); 368 final int length = (sort._closureVars == null) ? 0 : 369 sort._closureVars.size(); 370 371 for (int i = 0; i < length; i++) { 372 VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); 373 374 if (dups.contains(varRef)) continue; 376 377 final VariableBase var = varRef.getVariable(); 378 379 il.append(DUP); 381 il.append(var.loadInstruction()); 382 il.append(new PUTFIELD( 383 cpg.addFieldref(sortRecordFactoryClass, var.getEscapedName(), 384 var.getType().toSignature()))); 385 dups.add(varRef); 386 } 387 } 388 } 389 390 public static String compileSortRecordFactory(Vector sortObjects, 391 ClassGenerator classGen, MethodGenerator methodGen, 392 String sortRecordClass) 393 { 394 final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); 395 final String className = xsltc.getHelperClassName(); 396 397 final NodeSortRecordFactGenerator sortRecordFactory = 398 new NodeSortRecordFactGenerator(className, 399 NODE_SORT_FACTORY, 400 className + ".java", 401 ACC_PUBLIC | ACC_SUPER | ACC_FINAL, 402 new String [] {}, 403 classGen.getStylesheet()); 404 405 ConstantPoolGen cpg = sortRecordFactory.getConstantPool(); 406 407 final int nsorts = sortObjects.size(); 409 final ArrayList dups = new ArrayList (); 410 411 for (int j = 0; j < nsorts; j++) { 412 final Sort sort = (Sort) sortObjects.get(j); 413 final int length = (sort._closureVars == null) ? 0 : 414 sort._closureVars.size(); 415 416 for (int i = 0; i < length; i++) { 417 final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); 418 419 if (dups.contains(varRef)) continue; 421 422 final VariableBase var = varRef.getVariable(); 423 sortRecordFactory.addField(new Field(ACC_PUBLIC, 424 cpg.addUtf8(var.getEscapedName()), 425 cpg.addUtf8(var.getType().toSignature()), 426 null, cpg.getConstantPool())); 427 dups.add(varRef); 428 } 429 } 430 431 final org.apache.bcel.generic.Type[] argTypes = 433 new org.apache.bcel.generic.Type[7]; 434 argTypes[0] = Util.getJCRefType(DOM_INTF_SIG); 435 argTypes[1] = Util.getJCRefType(STRING_SIG); 436 argTypes[2] = Util.getJCRefType(TRANSLET_INTF_SIG); 437 argTypes[3] = Util.getJCRefType("[" + STRING_SIG); 438 argTypes[4] = Util.getJCRefType("[" + STRING_SIG); 439 argTypes[5] = Util.getJCRefType("[" + STRING_SIG); 440 argTypes[6] = Util.getJCRefType("[" + STRING_SIG); 441 442 final String [] argNames = new String [7]; 443 argNames[0] = DOCUMENT_PNAME; 444 argNames[1] = "className"; 445 argNames[2] = TRANSLET_PNAME; 446 argNames[3] = "order"; 447 argNames[4] = "type"; 448 argNames[5] = "lang"; 449 argNames[6] = "case_order"; 450 451 452 InstructionList il = new InstructionList(); 453 final MethodGenerator constructor = 454 new MethodGenerator(ACC_PUBLIC, 455 org.apache.bcel.generic.Type.VOID, 456 argTypes, argNames, "<init>", 457 className, il, cpg); 458 459 il.append(ALOAD_0); 461 il.append(ALOAD_1); 462 il.append(ALOAD_2); 463 il.append(new ALOAD(3)); 464 il.append(new ALOAD(4)); 465 il.append(new ALOAD(5)); 466 il.append(new ALOAD(6)); 467 il.append(new ALOAD(7)); 468 il.append(new INVOKESPECIAL(cpg.addMethodref(NODE_SORT_FACTORY, 469 "<init>", 470 "(" + DOM_INTF_SIG 471 + STRING_SIG 472 + TRANSLET_INTF_SIG 473 + "[" + STRING_SIG 474 + "[" + STRING_SIG 475 + "[" + STRING_SIG 476 + "[" + STRING_SIG + ")V"))); 477 il.append(RETURN); 478 479 il = new InstructionList(); 481 final MethodGenerator makeNodeSortRecord = 482 new MethodGenerator(ACC_PUBLIC, 483 Util.getJCRefType(NODE_SORT_RECORD_SIG), 484 new org.apache.bcel.generic.Type[] { 485 org.apache.bcel.generic.Type.INT, 486 org.apache.bcel.generic.Type.INT }, 487 new String [] { "node", "last" }, "makeNodeSortRecord", 488 className, il, cpg); 489 490 il.append(ALOAD_0); 491 il.append(ILOAD_1); 492 il.append(ILOAD_2); 493 il.append(new INVOKESPECIAL(cpg.addMethodref(NODE_SORT_FACTORY, 494 "makeNodeSortRecord", "(II)" + NODE_SORT_RECORD_SIG))); 495 il.append(DUP); 496 il.append(new CHECKCAST(cpg.addClass(sortRecordClass))); 497 498 final int ndups = dups.size(); 500 for (int i = 0; i < ndups; i++) { 501 final VariableRefBase varRef = (VariableRefBase) dups.get(i); 502 final VariableBase var = varRef.getVariable(); 503 final Type varType = var.getType(); 504 505 il.append(DUP); 506 507 il.append(ALOAD_0); 509 il.append(new GETFIELD( 510 cpg.addFieldref(className, 511 var.getEscapedName(), varType.toSignature()))); 512 513 il.append(new PUTFIELD( 515 cpg.addFieldref(sortRecordClass, 516 var.getEscapedName(), varType.toSignature()))); 517 } 518 il.append(POP); 519 il.append(ARETURN); 520 521 constructor.setMaxLocals(); 522 constructor.setMaxStack(); 523 sortRecordFactory.addMethod(constructor.getMethod()); 524 makeNodeSortRecord.setMaxLocals(); 525 makeNodeSortRecord.setMaxStack(); 526 sortRecordFactory.addMethod(makeNodeSortRecord.getMethod()); 527 xsltc.dumpClass(sortRecordFactory.getJavaClass()); 528 529 return className; 530 } 531 532 535 private static String compileSortRecord(Vector sortObjects, 536 ClassGenerator classGen, 537 MethodGenerator methodGen) { 538 final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); 539 final String className = xsltc.getHelperClassName(); 540 541 final NodeSortRecordGenerator sortRecord = 543 new NodeSortRecordGenerator(className, 544 NODE_SORT_RECORD, 545 "sort$0.java", 546 ACC_PUBLIC | ACC_SUPER | ACC_FINAL, 547 new String [] {}, 548 classGen.getStylesheet()); 549 550 final ConstantPoolGen cpg = sortRecord.getConstantPool(); 551 552 final int nsorts = sortObjects.size(); 554 final ArrayList dups = new ArrayList (); 555 556 for (int j = 0; j < nsorts; j++) { 557 final Sort sort = (Sort) sortObjects.get(j); 558 559 sort.setInnerClassName(className); 561 562 final int length = (sort._closureVars == null) ? 0 : 563 sort._closureVars.size(); 564 for (int i = 0; i < length; i++) { 565 final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); 566 567 if (dups.contains(varRef)) continue; 569 570 final VariableBase var = varRef.getVariable(); 571 sortRecord.addField(new Field(ACC_PUBLIC, 572 cpg.addUtf8(var.getEscapedName()), 573 cpg.addUtf8(var.getType().toSignature()), 574 null, cpg.getConstantPool())); 575 dups.add(varRef); 576 } 577 } 578 579 Method init = compileInit(sortObjects, sortRecord, 580 cpg, className); 581 Method extract = compileExtract(sortObjects, sortRecord, 582 cpg, className); 583 sortRecord.addMethod(init); 584 sortRecord.addMethod(extract); 585 586 xsltc.dumpClass(sortRecord.getJavaClass()); 587 return className; 588 } 589 590 595 private static Method compileInit(Vector sortObjects, 596 NodeSortRecordGenerator sortRecord, 597 ConstantPoolGen cpg, 598 String className) 599 { 600 final InstructionList il = new InstructionList(); 601 final MethodGenerator init = 602 new MethodGenerator(ACC_PUBLIC, 603 org.apache.bcel.generic.Type.VOID, 604 null, null, "<init>", className, 605 il, cpg); 606 607 il.append(ALOAD_0); 609 il.append(new INVOKESPECIAL(cpg.addMethodref(NODE_SORT_RECORD, 610 "<init>", "()V"))); 611 612 613 614 il.append(RETURN); 615 616 init.stripAttributes(true); 617 init.setMaxLocals(); 618 init.setMaxStack(); 619 620 return init.getMethod(); 621 } 622 623 624 627 private static Method compileExtract(Vector sortObjects, 628 NodeSortRecordGenerator sortRecord, 629 ConstantPoolGen cpg, 630 String className) { 631 final InstructionList il = new InstructionList(); 632 633 final CompareGenerator extractMethod = 635 new CompareGenerator(ACC_PUBLIC | ACC_FINAL, 636 org.apache.bcel.generic.Type.STRING, 637 new org.apache.bcel.generic.Type[] { 638 Util.getJCRefType(DOM_INTF_SIG), 639 org.apache.bcel.generic.Type.INT, 640 org.apache.bcel.generic.Type.INT, 641 Util.getJCRefType(TRANSLET_SIG), 642 org.apache.bcel.generic.Type.INT 643 }, 644 new String [] { "dom", 645 "current", 646 "level", 647 "translet", 648 "last" 649 }, 650 "extractValueFromDOM", className, il, cpg); 651 652 final int levels = sortObjects.size(); 654 final int match[] = new int[levels]; 655 final InstructionHandle target[] = new InstructionHandle[levels]; 656 InstructionHandle tblswitch = null; 657 658 if (levels > 1) { 660 il.append(new ILOAD(extractMethod.getLocalIndex("level"))); 662 tblswitch = il.append(new NOP()); 664 } 665 666 for (int level = 0; level < levels; level++) { 668 match[level] = level; 669 final Sort sort = (Sort)sortObjects.elementAt(level); 670 target[level] = il.append(NOP); 671 sort.translateSelect(sortRecord, extractMethod); 672 il.append(ARETURN); 673 } 674 675 if (levels > 1) { 677 InstructionHandle defaultTarget = 679 il.append(new PUSH(cpg, EMPTYSTRING)); 680 il.insert(tblswitch,new TABLESWITCH(match, target, defaultTarget)); 681 il.append(ARETURN); 682 } 683 684 extractMethod.stripAttributes(true); 685 extractMethod.setMaxLocals(); 686 extractMethod.setMaxStack(); 687 extractMethod.removeNOPs(); 688 689 return extractMethod.getMethod(); 690 } 691 } 692 | Popular Tags |