1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import org.apache.bcel.generic.BranchHandle; 23 import org.apache.bcel.generic.ConstantPoolGen; 24 import org.apache.bcel.generic.GOTO; 25 import org.apache.bcel.generic.IFEQ; 26 import org.apache.bcel.generic.IFGE; 27 import org.apache.bcel.generic.IFGT; 28 import org.apache.bcel.generic.ILOAD; 29 import org.apache.bcel.generic.INVOKEINTERFACE; 30 import org.apache.bcel.generic.INVOKEVIRTUAL; 31 import org.apache.bcel.generic.ISTORE; 32 import org.apache.bcel.generic.InstructionHandle; 33 import org.apache.bcel.generic.InstructionList; 34 import org.apache.bcel.generic.LocalVariableGen; 35 import org.apache.bcel.generic.PUSH; 36 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 37 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 38 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 39 import org.apache.xalan.xsltc.compiler.util.NodeSetType; 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 import org.apache.xalan.xsltc.dom.Axis; 45 import org.apache.xml.utils.XMLChar; 46 47 51 final class Key extends TopLevelElement { 52 53 56 private QName _name; 57 58 61 private Pattern _match; 62 63 66 private Expression _use; 67 68 71 private Type _useType; 72 73 77 public void parseContents(Parser parser) { 78 79 final String name = getAttribute("name"); 81 if (!XMLChar.isValidQName(name)){ 82 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, name, this); 83 parser.reportError(Constants.ERROR, err); 84 } 85 _name = parser.getQNameIgnoreDefaultNs(name); 86 _match = parser.parsePattern(this, "match", null); 87 _use = parser.parseExpression(this, "use", null); 88 89 if (_name == null) { 91 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "name"); 92 return; 93 } 94 if (_match.isDummy()) { 95 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "match"); 96 return; 97 } 98 if (_use.isDummy()) { 99 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "use"); 100 return; 101 } 102 } 103 104 108 public String getName() { 109 return _name.toString(); 110 } 111 112 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 113 _match.typeCheck(stable); 115 116 _useType = _use.typeCheck(stable); 118 if (_useType instanceof StringType == false && 119 _useType instanceof NodeSetType == false) 120 { 121 _use = new CastExpr(_use, Type.String); 122 } 123 124 return Type.Void; 125 } 126 127 132 public void traverseNodeSet(ClassGenerator classGen, 133 MethodGenerator methodGen, 134 int buildKeyIndex) { 135 final ConstantPoolGen cpg = classGen.getConstantPool(); 136 final InstructionList il = methodGen.getInstructionList(); 137 138 final int getNodeValue = cpg.addInterfaceMethodref(DOM_INTF, 140 GET_NODE_VALUE, 141 "(I)"+STRING_SIG); 142 143 final int getNodeIdent = cpg.addInterfaceMethodref(DOM_INTF, 144 "getNodeIdent", 145 "(I)"+NODE_SIG); 146 147 final int keyDom = cpg.addMethodref(TRANSLET_CLASS, 149 "setKeyIndexDom", 150 "("+STRING_SIG+DOM_INTF_SIG+")V"); 151 152 153 final LocalVariableGen parentNode = 157 methodGen.addLocalVariable("parentNode", 158 Util.getJCRefType("I"), 159 il.getEnd(), null); 160 161 il.append(new ISTORE(parentNode.getIndex())); 163 il.append(methodGen.loadDOM()); 164 il.append(new ILOAD(parentNode.getIndex())); 165 il.append(new INVOKEINTERFACE(getNodeIdent, 2)); 166 il.append(new ISTORE(parentNode.getIndex())); 167 168 il.append(methodGen.loadCurrentNode()); 170 il.append(methodGen.loadIterator()); 171 172 _use.translate(classGen, methodGen); 174 _use.startIterator(classGen, methodGen); 175 il.append(methodGen.storeIterator()); 176 177 final BranchHandle nextNode = il.append(new GOTO(null)); 178 final InstructionHandle loop = il.append(NOP); 179 180 il.append(classGen.loadTranslet()); 182 il.append(new PUSH(cpg, _name.toString())); 183 il.append(new ILOAD(parentNode.getIndex())); 184 185 il.append(methodGen.loadDOM()); 187 il.append(methodGen.loadCurrentNode()); 188 il.append(new INVOKEINTERFACE(getNodeValue, 2)); 189 190 il.append(new INVOKEVIRTUAL(buildKeyIndex)); 192 193 il.append(classGen.loadTranslet()); 194 il.append(new PUSH(cpg, getName())); 195 il.append(methodGen.loadDOM()); 196 il.append(new INVOKEVIRTUAL(keyDom)); 197 198 nextNode.setTarget(il.append(methodGen.loadIterator())); 199 il.append(methodGen.nextNode()); 200 201 il.append(DUP); 202 il.append(methodGen.storeCurrentNode()); 203 il.append(new IFGE(loop)); 205 il.append(methodGen.storeIterator()); 207 il.append(methodGen.storeCurrentNode()); 208 } 209 210 214 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 215 216 final ConstantPoolGen cpg = classGen.getConstantPool(); 217 final InstructionList il = methodGen.getInstructionList(); 218 final int current = methodGen.getLocalIndex("current"); 219 220 final int key = cpg.addMethodref(TRANSLET_CLASS, 222 "buildKeyIndex", 223 "("+STRING_SIG+"I"+OBJECT_SIG+")V"); 224 225 final int keyDom = cpg.addMethodref(TRANSLET_CLASS, 227 "setKeyIndexDom", 228 "("+STRING_SIG+DOM_INTF_SIG+")V"); 229 230 final int getNodeIdent = cpg.addInterfaceMethodref(DOM_INTF, 231 "getNodeIdent", 232 "(I)"+NODE_SIG); 233 234 final int git = cpg.addInterfaceMethodref(DOM_INTF, 236 "getAxisIterator", 237 "(I)"+NODE_ITERATOR_SIG); 238 239 il.append(methodGen.loadCurrentNode()); 240 il.append(methodGen.loadIterator()); 241 242 il.append(methodGen.loadDOM()); 244 il.append(new PUSH(cpg,Axis.DESCENDANT)); 245 il.append(new INVOKEINTERFACE(git, 2)); 246 247 il.append(methodGen.loadCurrentNode()); 249 il.append(methodGen.setStartNode()); 250 il.append(methodGen.storeIterator()); 251 252 final BranchHandle nextNode = il.append(new GOTO(null)); 254 final InstructionHandle loop = il.append(NOP); 255 256 il.append(methodGen.loadCurrentNode()); 258 _match.translate(classGen, methodGen); 259 _match.synthesize(classGen, methodGen); final BranchHandle skipNode = il.append(new IFEQ(null)); 261 262 if (_useType instanceof NodeSetType) { 264 il.append(methodGen.loadCurrentNode()); 266 traverseNodeSet(classGen, methodGen, key); 267 } 268 else { 269 il.append(classGen.loadTranslet()); 270 il.append(DUP); 271 il.append(new PUSH(cpg, _name.toString())); 272 il.append(DUP_X1); 273 il.append(methodGen.loadCurrentNode()); 274 _use.translate(classGen, methodGen); 275 il.append(SWAP); 276 il.append(methodGen.loadDOM()); 277 il.append(SWAP); 278 il.append(new INVOKEINTERFACE(getNodeIdent, 2)); 279 il.append(SWAP); 280 il.append(new INVOKEVIRTUAL(key)); 281 282 il.append(methodGen.loadDOM()); 283 il.append(new INVOKEVIRTUAL(keyDom)); 284 } 285 286 final InstructionHandle skip = il.append(NOP); 288 289 il.append(methodGen.loadIterator()); 290 il.append(methodGen.nextNode()); 291 il.append(DUP); 292 il.append(methodGen.storeCurrentNode()); 293 il.append(new IFGT(loop)); 294 295 il.append(methodGen.storeIterator()); 297 il.append(methodGen.storeCurrentNode()); 298 299 nextNode.setTarget(skip); 300 skipNode.setTarget(skip); 301 } 302 } 303 | Popular Tags |