1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.util.ArrayList ; 23 24 import org.apache.bcel.classfile.Field; 25 import org.apache.bcel.generic.ALOAD; 26 import org.apache.bcel.generic.ASTORE; 27 import org.apache.bcel.generic.BranchHandle; 28 import org.apache.bcel.generic.CHECKCAST; 29 import org.apache.bcel.generic.ConstantPoolGen; 30 import org.apache.bcel.generic.GETFIELD; 31 import org.apache.bcel.generic.GOTO; 32 import org.apache.bcel.generic.IFNONNULL; 33 import org.apache.bcel.generic.INVOKESPECIAL; 34 import org.apache.bcel.generic.INVOKESTATIC; 35 import org.apache.bcel.generic.INVOKEVIRTUAL; 36 import org.apache.bcel.generic.InstructionList; 37 import org.apache.bcel.generic.L2I; 38 import org.apache.bcel.generic.LocalVariableGen; 39 import org.apache.bcel.generic.NEW; 40 import org.apache.bcel.generic.PUSH; 41 import org.apache.bcel.generic.PUTFIELD; 42 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 43 import org.apache.xalan.xsltc.compiler.util.MatchGenerator; 44 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 45 import org.apache.xalan.xsltc.compiler.util.NodeCounterGenerator; 46 import org.apache.xalan.xsltc.compiler.util.RealType; 47 import org.apache.xalan.xsltc.compiler.util.Type; 48 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 49 import org.apache.xalan.xsltc.compiler.util.Util; 50 51 55 final class Number extends Instruction implements Closure { 56 private static final int LEVEL_SINGLE = 0; 57 private static final int LEVEL_MULTIPLE = 1; 58 private static final int LEVEL_ANY = 2; 59 60 static final private String [] ClassNames = { 61 "org.apache.xalan.xsltc.dom.SingleNodeCounter", "org.apache.xalan.xsltc.dom.MultipleNodeCounter", "org.apache.xalan.xsltc.dom.AnyNodeCounter" }; 65 66 static final private String [] FieldNames = { 67 "___single_node_counter", "___multiple_node_counter", "___any_node_counter" }; 71 72 private Pattern _from = null; 73 private Pattern _count = null; 74 private Expression _value = null; 75 76 private AttributeValueTemplate _lang = null; 77 private AttributeValueTemplate _format = null; 78 private AttributeValueTemplate _letterValue = null; 79 private AttributeValueTemplate _groupingSeparator = null; 80 private AttributeValueTemplate _groupingSize = null; 81 82 private int _level = LEVEL_SINGLE; 83 private boolean _formatNeeded = false; 84 85 private String _className = null; 86 private ArrayList _closureVars = null; 87 88 90 94 public boolean inInnerClass() { 95 return (_className != null); 96 } 97 98 101 public Closure getParentClosure() { 102 return null; 103 } 104 105 109 public String getInnerClassName() { 110 return _className; 111 } 112 113 116 public void addVariable(VariableRefBase variableRef) { 117 if (_closureVars == null) { 118 _closureVars = new ArrayList (); 119 } 120 121 if (!_closureVars.contains(variableRef)) { 123 _closureVars.add(variableRef); 124 } 125 } 126 127 129 public void parseContents(Parser parser) { 130 final int count = _attributes.getLength(); 131 132 for (int i = 0; i < count; i++) { 133 final String name = _attributes.getQName(i); 134 final String value = _attributes.getValue(i); 135 136 if (name.equals("value")) { 137 _value = parser.parseExpression(this, name, null); 138 } 139 else if (name.equals("count")) { 140 _count = parser.parsePattern(this, name, null); 141 } 142 else if (name.equals("from")) { 143 _from = parser.parsePattern(this, name, null); 144 } 145 else if (name.equals("level")) { 146 if (value.equals("single")) { 147 _level = LEVEL_SINGLE; 148 } 149 else if (value.equals("multiple")) { 150 _level = LEVEL_MULTIPLE; 151 } 152 else if (value.equals("any")) { 153 _level = LEVEL_ANY; 154 } 155 } 156 else if (name.equals("format")) { 157 _format = new AttributeValueTemplate(value, parser, this); 158 _formatNeeded = true; 159 } 160 else if (name.equals("lang")) { 161 _lang = new AttributeValueTemplate(value, parser, this); 162 _formatNeeded = true; 163 } 164 else if (name.equals("letter-value")) { 165 _letterValue = new AttributeValueTemplate(value, parser, this); 166 _formatNeeded = true; 167 } 168 else if (name.equals("grouping-separator")) { 169 _groupingSeparator = new AttributeValueTemplate(value, parser, this); 170 _formatNeeded = true; 171 } 172 else if (name.equals("grouping-size")) { 173 _groupingSize = new AttributeValueTemplate(value, parser, this); 174 _formatNeeded = true; 175 } 176 } 177 } 178 179 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 180 if (_value != null) { 181 Type tvalue = _value.typeCheck(stable); 182 if (tvalue instanceof RealType == false) { 183 _value = new CastExpr(_value, Type.Real); 184 } 185 } 186 if (_count != null) { 187 _count.typeCheck(stable); 188 } 189 if (_from != null) { 190 _from.typeCheck(stable); 191 } 192 if (_format != null) { 193 _format.typeCheck(stable); 194 } 195 if (_lang != null) { 196 _lang.typeCheck(stable); 197 } 198 if (_letterValue != null) { 199 _letterValue.typeCheck(stable); 200 } 201 if (_groupingSeparator != null) { 202 _groupingSeparator.typeCheck(stable); 203 } 204 if (_groupingSize != null) { 205 _groupingSize.typeCheck(stable); 206 } 207 return Type.Void; 208 } 209 210 213 public boolean hasValue() { 214 return _value != null; 215 } 216 217 221 public boolean isDefault() { 222 return _from == null && _count == null; 223 } 224 225 private void compileDefault(ClassGenerator classGen, 226 MethodGenerator methodGen) { 227 int index; 228 ConstantPoolGen cpg = classGen.getConstantPool(); 229 InstructionList il = methodGen.getInstructionList(); 230 231 int[] fieldIndexes = getXSLTC().getNumberFieldIndexes(); 232 233 if (fieldIndexes[_level] == -1) { 234 Field defaultNode = new Field(ACC_PRIVATE, 235 cpg.addUtf8(FieldNames[_level]), 236 cpg.addUtf8(NODE_COUNTER_SIG), 237 null, 238 cpg.getConstantPool()); 239 240 classGen.addField(defaultNode); 242 243 fieldIndexes[_level] = cpg.addFieldref(classGen.getClassName(), 245 FieldNames[_level], 246 NODE_COUNTER_SIG); 247 } 248 249 il.append(classGen.loadTranslet()); 251 il.append(new GETFIELD(fieldIndexes[_level])); 252 final BranchHandle ifBlock1 = il.append(new IFNONNULL(null)); 253 254 index = cpg.addMethodref(ClassNames[_level], 256 "getDefaultNodeCounter", 257 "(" + TRANSLET_INTF_SIG 258 + DOM_INTF_SIG 259 + NODE_ITERATOR_SIG 260 + ")" + NODE_COUNTER_SIG); 261 il.append(classGen.loadTranslet()); 262 il.append(methodGen.loadDOM()); 263 il.append(methodGen.loadIterator()); 264 il.append(new INVOKESTATIC(index)); 265 il.append(DUP); 266 267 il.append(classGen.loadTranslet()); 269 il.append(SWAP); 270 il.append(new PUTFIELD(fieldIndexes[_level])); 271 final BranchHandle ifBlock2 = il.append(new GOTO(null)); 272 273 ifBlock1.setTarget(il.append(classGen.loadTranslet())); 275 il.append(new GETFIELD(fieldIndexes[_level])); 276 277 ifBlock2.setTarget(il.append(NOP)); 278 } 279 280 285 private void compileConstructor(ClassGenerator classGen) { 286 MethodGenerator cons; 287 final InstructionList il = new InstructionList(); 288 final ConstantPoolGen cpg = classGen.getConstantPool(); 289 290 cons = new MethodGenerator(ACC_PUBLIC, 291 org.apache.bcel.generic.Type.VOID, 292 new org.apache.bcel.generic.Type[] { 293 Util.getJCRefType(TRANSLET_INTF_SIG), 294 Util.getJCRefType(DOM_INTF_SIG), 295 Util.getJCRefType(NODE_ITERATOR_SIG) 296 }, 297 new String [] { 298 "dom", 299 "translet", 300 "iterator" 301 }, 302 "<init>", _className, il, cpg); 303 304 il.append(ALOAD_0); il.append(ALOAD_1); il.append(ALOAD_2); il.append(new ALOAD(3)); 309 int index = cpg.addMethodref(ClassNames[_level], 310 "<init>", 311 "(" + TRANSLET_INTF_SIG 312 + DOM_INTF_SIG 313 + NODE_ITERATOR_SIG 314 + ")V"); 315 il.append(new INVOKESPECIAL(index)); 316 il.append(RETURN); 317 318 cons.stripAttributes(true); 319 cons.setMaxLocals(); 320 cons.setMaxStack(); 321 classGen.addMethod(cons.getMethod()); 322 } 323 324 328 private void compileLocals(NodeCounterGenerator nodeCounterGen, 329 MatchGenerator matchGen, 330 InstructionList il) 331 { 332 int field; 333 LocalVariableGen local; 334 ConstantPoolGen cpg = nodeCounterGen.getConstantPool(); 335 336 local = matchGen.addLocalVariable("iterator", 338 Util.getJCRefType(NODE_ITERATOR_SIG), 339 null, null); 340 field = cpg.addFieldref(NODE_COUNTER, "_iterator", 341 ITERATOR_FIELD_SIG); 342 il.append(ALOAD_0); il.append(new GETFIELD(field)); 344 il.append(new ASTORE(local.getIndex())); 345 matchGen.setIteratorIndex(local.getIndex()); 346 347 local = matchGen.addLocalVariable("translet", 349 Util.getJCRefType(TRANSLET_SIG), 350 null, null); 351 field = cpg.addFieldref(NODE_COUNTER, "_translet", 352 "Lorg/apache/xalan/xsltc/Translet;"); 353 il.append(ALOAD_0); il.append(new GETFIELD(field)); 355 il.append(new CHECKCAST(cpg.addClass(TRANSLET_CLASS))); 356 il.append(new ASTORE(local.getIndex())); 357 nodeCounterGen.setTransletIndex(local.getIndex()); 358 359 local = matchGen.addLocalVariable("document", 361 Util.getJCRefType(DOM_INTF_SIG), 362 null, null); 363 field = cpg.addFieldref(_className, "_document", DOM_INTF_SIG); 364 il.append(ALOAD_0); il.append(new GETFIELD(field)); 366 il.append(new ASTORE(local.getIndex())); 368 matchGen.setDomIndex(local.getIndex()); 369 } 370 371 private void compilePatterns(ClassGenerator classGen, 372 MethodGenerator methodGen) 373 { 374 int current; 375 int field; 376 LocalVariableGen local; 377 MatchGenerator matchGen; 378 NodeCounterGenerator nodeCounterGen; 379 380 _className = getXSLTC().getHelperClassName(); 381 nodeCounterGen = new NodeCounterGenerator(_className, 382 ClassNames[_level], 383 toString(), 384 ACC_PUBLIC | ACC_SUPER, 385 null, 386 classGen.getStylesheet()); 387 InstructionList il = null; 388 ConstantPoolGen cpg = nodeCounterGen.getConstantPool(); 389 390 final int closureLen = (_closureVars == null) ? 0 : 392 _closureVars.size(); 393 394 for (int i = 0; i < closureLen; i++) { 395 VariableBase var = 396 ((VariableRefBase) _closureVars.get(i)).getVariable(); 397 398 nodeCounterGen.addField(new Field(ACC_PUBLIC, 399 cpg.addUtf8(var.getEscapedName()), 400 cpg.addUtf8(var.getType().toSignature()), 401 null, cpg.getConstantPool())); 402 } 403 404 compileConstructor(nodeCounterGen); 406 407 410 if (_from != null) { 411 il = new InstructionList(); 412 matchGen = 413 new MatchGenerator(ACC_PUBLIC | ACC_FINAL, 414 org.apache.bcel.generic.Type.BOOLEAN, 415 new org.apache.bcel.generic.Type[] { 416 org.apache.bcel.generic.Type.INT, 417 }, 418 new String [] { 419 "node", 420 }, 421 "matchesFrom", _className, il, cpg); 422 423 compileLocals(nodeCounterGen,matchGen,il); 424 425 il.append(matchGen.loadContextNode()); 427 _from.translate(nodeCounterGen, matchGen); 428 _from.synthesize(nodeCounterGen, matchGen); 429 il.append(IRETURN); 430 431 matchGen.stripAttributes(true); 432 matchGen.setMaxLocals(); 433 matchGen.setMaxStack(); 434 matchGen.removeNOPs(); 435 nodeCounterGen.addMethod(matchGen.getMethod()); 436 } 437 438 441 if (_count != null) { 442 il = new InstructionList(); 443 matchGen = new MatchGenerator(ACC_PUBLIC | ACC_FINAL, 444 org.apache.bcel.generic.Type.BOOLEAN, 445 new org.apache.bcel.generic.Type[] { 446 org.apache.bcel.generic.Type.INT, 447 }, 448 new String [] { 449 "node", 450 }, 451 "matchesCount", _className, il, cpg); 452 453 compileLocals(nodeCounterGen,matchGen,il); 454 455 il.append(matchGen.loadContextNode()); 457 _count.translate(nodeCounterGen, matchGen); 458 _count.synthesize(nodeCounterGen, matchGen); 459 460 il.append(IRETURN); 461 462 matchGen.stripAttributes(true); 463 matchGen.setMaxLocals(); 464 matchGen.setMaxStack(); 465 matchGen.removeNOPs(); 466 nodeCounterGen.addMethod(matchGen.getMethod()); 467 } 468 469 getXSLTC().dumpClass(nodeCounterGen.getJavaClass()); 470 471 cpg = classGen.getConstantPool(); 473 il = methodGen.getInstructionList(); 474 475 final int index = cpg.addMethodref(_className, "<init>", 476 "(" + TRANSLET_INTF_SIG 477 + DOM_INTF_SIG 478 + NODE_ITERATOR_SIG 479 + ")V"); 480 il.append(new NEW(cpg.addClass(_className))); 481 il.append(DUP); 482 il.append(classGen.loadTranslet()); 483 il.append(methodGen.loadDOM()); 484 il.append(methodGen.loadIterator()); 485 il.append(new INVOKESPECIAL(index)); 486 487 for (int i = 0; i < closureLen; i++) { 489 final VariableRefBase varRef = (VariableRefBase) _closureVars.get(i); 490 final VariableBase var = varRef.getVariable(); 491 final Type varType = var.getType(); 492 493 il.append(DUP); 495 il.append(var.loadInstruction()); 496 il.append(new PUTFIELD( 497 cpg.addFieldref(_className, var.getEscapedName(), 498 varType.toSignature()))); 499 } 500 } 501 502 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 503 int index; 504 final ConstantPoolGen cpg = classGen.getConstantPool(); 505 final InstructionList il = methodGen.getInstructionList(); 506 507 il.append(classGen.loadTranslet()); 509 510 if (hasValue()) { 511 compileDefault(classGen, methodGen); 512 _value.translate(classGen, methodGen); 513 514 index = cpg.addMethodref(MATH_CLASS, "round", "(D)J"); 516 il.append(new INVOKESTATIC(index)); 517 il.append(new L2I()); 518 519 index = cpg.addMethodref(NODE_COUNTER, 521 "setValue", 522 "(I)" + NODE_COUNTER_SIG); 523 il.append(new INVOKEVIRTUAL(index)); 524 } 525 else if (isDefault()) { 526 compileDefault(classGen, methodGen); 527 } 528 else { 529 compilePatterns(classGen, methodGen); 530 } 531 532 if (!hasValue()) { 534 il.append(methodGen.loadContextNode()); 535 index = cpg.addMethodref(NODE_COUNTER, 536 SET_START_NODE, 537 "(I)" + NODE_COUNTER_SIG); 538 il.append(new INVOKEVIRTUAL(index)); 539 } 540 541 if (_formatNeeded) { 543 if (_format != null) { 544 _format.translate(classGen, methodGen); 545 } 546 else { 547 il.append(new PUSH(cpg, "1")); 548 } 549 550 if (_lang != null) { 551 _lang.translate(classGen, methodGen); 552 } 553 else { 554 il.append(new PUSH(cpg, "en")); } 556 557 if (_letterValue != null) { 558 _letterValue.translate(classGen, methodGen); 559 } 560 else { 561 il.append(new PUSH(cpg, Constants.EMPTYSTRING)); 562 } 563 564 if (_groupingSeparator != null) { 565 _groupingSeparator.translate(classGen, methodGen); 566 } 567 else { 568 il.append(new PUSH(cpg, Constants.EMPTYSTRING)); 569 } 570 571 if (_groupingSize != null) { 572 _groupingSize.translate(classGen, methodGen); 573 } 574 else { 575 il.append(new PUSH(cpg, "0")); 576 } 577 578 index = cpg.addMethodref(NODE_COUNTER, "getCounter", 579 "(" + STRING_SIG + STRING_SIG 580 + STRING_SIG + STRING_SIG 581 + STRING_SIG + ")" + STRING_SIG); 582 il.append(new INVOKEVIRTUAL(index)); 583 } 584 else { 585 index = cpg.addMethodref(NODE_COUNTER, "setDefaultFormatting", 586 "()" + NODE_COUNTER_SIG); 587 il.append(new INVOKEVIRTUAL(index)); 588 589 index = cpg.addMethodref(NODE_COUNTER, "getCounter", 590 "()" + STRING_SIG); 591 il.append(new INVOKEVIRTUAL(index)); 592 } 593 594 il.append(methodGen.loadHandler()); 596 index = cpg.addMethodref(TRANSLET_CLASS, 597 CHARACTERSW, 598 CHARACTERSW_SIG); 599 il.append(new INVOKEVIRTUAL(index)); 600 } 601 } 602 | Popular Tags |