1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.util.Vector ; 23 24 import org.apache.bcel.generic.ALOAD; 25 import org.apache.bcel.generic.ASTORE; 26 import org.apache.bcel.generic.BranchHandle; 27 import org.apache.bcel.generic.ConstantPoolGen; 28 import org.apache.bcel.generic.GOTO; 29 import org.apache.bcel.generic.IFGT; 30 import org.apache.bcel.generic.INVOKEINTERFACE; 31 import org.apache.bcel.generic.INVOKESPECIAL; 32 import org.apache.bcel.generic.INVOKEVIRTUAL; 33 import org.apache.bcel.generic.InstructionHandle; 34 import org.apache.bcel.generic.InstructionList; 35 import org.apache.bcel.generic.LocalVariableGen; 36 import org.apache.bcel.generic.NEW; 37 import org.apache.bcel.generic.PUSH; 38 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 39 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 40 import org.apache.xalan.xsltc.compiler.util.StringType; 41 import org.apache.xalan.xsltc.compiler.util.Type; 42 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 43 import org.apache.xalan.xsltc.compiler.util.Util; 44 45 49 final class KeyCall extends FunctionCall { 50 51 54 private Expression _name; 55 56 59 private Expression _value; 60 61 64 private Type _valueType; 66 69 private QName _resolvedQName = null; 70 71 83 public KeyCall(QName fname, Vector arguments) { 84 super(fname, arguments); 85 switch(argumentCount()) { 86 case 1: 87 _name = null; 88 _value = argument(0); 89 break; 90 case 2: 91 _name = argument(0); 92 _value = argument(1); 93 break; 94 default: 95 _name = _value = null; 96 break; 97 } 98 } 99 100 107 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 108 final Type returnType = super.typeCheck(stable); 109 110 if (_name != null) { 113 final Type nameType = _name.typeCheck(stable); 114 115 if (_name instanceof LiteralExpr) { 116 final LiteralExpr literal = (LiteralExpr) _name; 117 _resolvedQName = 118 getParser().getQNameIgnoreDefaultNs(literal.getValue()); 119 } 120 else if (nameType instanceof StringType == false) { 121 _name = new CastExpr(_name, Type.String); 122 } 123 } 124 125 _valueType = _value.typeCheck(stable); 133 134 if (_valueType != Type.NodeSet && _valueType != Type.String) 135 { 136 _value = new CastExpr(_value, Type.String); 137 } 138 139 return returnType; 140 } 141 142 153 public void translate(ClassGenerator classGen, 154 MethodGenerator methodGen) { 155 final ConstantPoolGen cpg = classGen.getConstantPool(); 156 final InstructionList il = methodGen.getInstructionList(); 157 158 final int getNodeHandle = cpg.addInterfaceMethodref(DOM_INTF, 159 "getNodeHandle", 160 "(I)"+NODE_SIG); 161 162 final int dupInit = cpg.addMethodref(DUP_FILTERED_ITERATOR, 165 "<init>", 166 "("+NODE_ITERATOR_SIG+")V"); 167 168 il.append(new NEW(cpg.addClass(DUP_FILTERED_ITERATOR))); 169 il.append(DUP); 170 translateCall(classGen, methodGen); 171 il.append(new INVOKESPECIAL(dupInit)); 172 173 } 174 175 180 private void translateCall(ClassGenerator classGen, 181 MethodGenerator methodGen) { 182 183 final ConstantPoolGen cpg = classGen.getConstantPool(); 184 final InstructionList il = methodGen.getInstructionList(); 185 186 final int getNodeValue = cpg.addInterfaceMethodref(DOM_INTF, 188 GET_NODE_VALUE, 189 "(I)"+STRING_SIG); 190 191 final int getKeyIndex = cpg.addMethodref(TRANSLET_CLASS, 193 "getKeyIndex", 194 "(Ljava/lang/String;)"+ 195 KEY_INDEX_SIG); 196 197 final int lookupId = cpg.addMethodref(KEY_INDEX_CLASS, 199 "lookupId", 200 "(Ljava/lang/Object;)V"); 201 final int lookupKey = cpg.addMethodref(KEY_INDEX_CLASS, 202 "lookupKey", 203 "(Ljava/lang/Object;)V"); 204 205 final int merge = cpg.addMethodref(KEY_INDEX_CLASS, 207 "merge", 208 "("+KEY_INDEX_SIG+")V"); 209 210 final int indexConstructor = cpg.addMethodref(TRANSLET_CLASS, 212 "createKeyIndex", 213 "()"+KEY_INDEX_SIG); 214 215 final int keyDom = cpg.addMethodref(XSLT_PACKAGE + ".dom.KeyIndex", 217 "setDom", 218 "("+DOM_INTF_SIG+")V"); 219 220 221 final LocalVariableGen returnIndex = 223 methodGen.addLocalVariable("returnIndex", 224 Util.getJCRefType(KEY_INDEX_SIG), 225 il.getEnd(), null); 226 227 final LocalVariableGen searchIndex = 229 methodGen.addLocalVariable("searchIndex", 230 Util.getJCRefType(KEY_INDEX_SIG), 231 il.getEnd(), null); 232 233 if (_valueType == Type.NodeSet) { 237 il.append(methodGen.loadCurrentNode()); 239 il.append(methodGen.loadIterator()); 240 241 _value.translate(classGen, methodGen); 243 _value.startIterator(classGen, methodGen); 244 il.append(methodGen.storeIterator()); 245 246 il.append(classGen.loadTranslet()); 248 il.append(new INVOKEVIRTUAL(indexConstructor)); 249 il.append(DUP); 250 il.append(methodGen.loadDOM()); 251 il.append(new INVOKEVIRTUAL(keyDom)); 252 il.append(new ASTORE(returnIndex.getIndex())); 253 254 il.append(classGen.loadTranslet()); 256 if (_name == null) { 257 il.append(new PUSH(cpg,"##id")); 258 } 259 else if (_resolvedQName != null) { 260 il.append(new PUSH(cpg, _resolvedQName.toString())); 261 } 262 else { 263 _name.translate(classGen, methodGen); 264 } 265 266 il.append(new INVOKEVIRTUAL(getKeyIndex)); 267 il.append(new ASTORE(searchIndex.getIndex())); 268 269 271 final BranchHandle nextNode = il.append(new GOTO(null)); 274 final InstructionHandle loop = il.append(NOP); 275 276 il.append(new ALOAD(returnIndex.getIndex())); 278 279 il.append(new ALOAD(searchIndex.getIndex())); 281 il.append(DUP); 282 il.append(methodGen.loadDOM()); 283 il.append(methodGen.loadCurrentNode()); 284 il.append(new INVOKEINTERFACE(getNodeValue, 2)); 285 if (_name == null) { 286 il.append(new INVOKEVIRTUAL(lookupId)); 287 } 288 else { 289 il.append(new INVOKEVIRTUAL(lookupKey)); 290 } 291 292 il.append(new INVOKEVIRTUAL(merge)); 294 295 nextNode.setTarget(il.append(methodGen.loadIterator())); 297 il.append(methodGen.nextNode()); 298 il.append(DUP); 299 il.append(methodGen.storeCurrentNode()); 300 il.append(new IFGT(loop)); 301 302 304 il.append(methodGen.storeIterator()); 306 il.append(methodGen.storeCurrentNode()); 307 308 il.append(new ALOAD(returnIndex.getIndex())); 310 } 311 else { 314 il.append(classGen.loadTranslet()); 317 if (_name == null) { 318 il.append(new PUSH(cpg,"##id")); 319 } 320 else if (_resolvedQName != null) { 321 il.append(new PUSH(cpg, _resolvedQName.toString())); 322 } 323 else { 324 _name.translate(classGen, methodGen); 325 } 326 il.append(new INVOKEVIRTUAL(getKeyIndex)); 327 328 il.append(DUP); 331 332 _value.translate(classGen, methodGen); 333 334 if (_name == null) { 335 il.append(new INVOKEVIRTUAL(lookupId)); 336 } 337 else { 338 il.append(new INVOKEVIRTUAL(lookupKey)); 339 } 340 } 341 } 342 } 343 | Popular Tags |