1 /* 2 * reserved comment block 3 * DO NOT REMOVE OR ALTER! 4 */ 5 /* 6 * Copyright 2001-2004 The Apache Software Foundation. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 /* 21 * $Id: NodeSetType.java,v 1.2.4.1 2005/09/05 11:21:45 pvedula Exp $ 22 */ 23 24 package com.sun.org.apache.xalan.internal.xsltc.compiler.util; 25 26 import com.sun.org.apache.bcel.internal.generic.ALOAD; 27 import com.sun.org.apache.bcel.internal.generic.ASTORE; 28 import com.sun.org.apache.bcel.internal.generic.BranchHandle; 29 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; 30 import com.sun.org.apache.bcel.internal.generic.GOTO; 31 import com.sun.org.apache.bcel.internal.generic.IFLT; 32 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; 33 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; 34 import com.sun.org.apache.bcel.internal.generic.Instruction; 35 import com.sun.org.apache.bcel.internal.generic.InstructionList; 36 import com.sun.org.apache.bcel.internal.generic.PUSH; 37 import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants; 38 import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList; 39 40 /** 41 * @author Jacek Ambroziak 42 * @author Santiago Pericas-Geertsen 43 */ 44 public final class NodeSetType extends Type { NodeSetType()45 protected NodeSetType() {} 46 toString()47 public String toString() { 48 return "node-set"; 49 } 50 identicalTo(Type other)51 public boolean identicalTo(Type other) { 52 return this == other; 53 } 54 toSignature()55 public String toSignature() { 56 return NODE_ITERATOR_SIG; 57 } 58 toJCType()59 public com.sun.org.apache.bcel.internal.generic.Type toJCType() { 60 return new com.sun.org.apache.bcel.internal.generic.ObjectType(NODE_ITERATOR); 61 } 62 63 /** 64 * Translates a node-set into an object of internal type 65 * <code>type</code>. The translation to int is undefined 66 * since node-sets are always converted to 67 * reals in arithmetic expressions. 68 * 69 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 70 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, Type type)71 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 72 Type type) { 73 if (type == Type.String) { 74 translateTo(classGen, methodGen, (StringType) type); 75 } 76 else if (type == Type.Boolean) { 77 translateTo(classGen, methodGen, (BooleanType) type); 78 } 79 else if (type == Type.Real) { 80 translateTo(classGen, methodGen, (RealType) type); 81 } 82 else if (type == Type.Node) { 83 translateTo(classGen, methodGen, (NodeType) type); 84 } 85 else if (type == Type.Reference) { 86 translateTo(classGen, methodGen, (ReferenceType) type); 87 } 88 else if (type == Type.Object) { 89 translateTo(classGen, methodGen, (ObjectType) type); 90 } 91 else { 92 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 93 toString(), type.toString()); 94 classGen.getParser().reportError(Constants.FATAL, err); 95 } 96 } 97 98 /** 99 * Translates an external Java Class into an internal type. 100 * Expects the Java object on the stack, pushes the internal type 101 */ translateFrom(ClassGenerator classGen, MethodGenerator methodGen, Class clazz)102 public void translateFrom(ClassGenerator classGen, 103 MethodGenerator methodGen, Class clazz) 104 { 105 106 InstructionList il = methodGen.getInstructionList(); 107 ConstantPoolGen cpg = classGen.getConstantPool(); 108 if (clazz.getName().equals("org.w3c.dom.NodeList")) { 109 // w3c NodeList is on the stack from the external Java function call. 110 // call BasisFunction to consume NodeList and leave Iterator on 111 // the stack. 112 il.append(classGen.loadTranslet()); // push translet onto stack 113 il.append(methodGen.loadDOM()); // push DOM onto stack 114 final int convert = cpg.addMethodref(BASIS_LIBRARY_CLASS, 115 "nodeList2Iterator", 116 "(" 117 + "Lorg/w3c/dom/NodeList;" 118 + TRANSLET_INTF_SIG 119 + DOM_INTF_SIG 120 + ")" + NODE_ITERATOR_SIG ); 121 il.append(new INVOKESTATIC(convert)); 122 } 123 else if (clazz.getName().equals("org.w3c.dom.Node")) { 124 // w3c Node is on the stack from the external Java function call. 125 // call BasisLibrary.node2Iterator() to consume Node and leave 126 // Iterator on the stack. 127 il.append(classGen.loadTranslet()); // push translet onto stack 128 il.append(methodGen.loadDOM()); // push DOM onto stack 129 final int convert = cpg.addMethodref(BASIS_LIBRARY_CLASS, 130 "node2Iterator", 131 "(" 132 + "Lorg/w3c/dom/Node;" 133 + TRANSLET_INTF_SIG 134 + DOM_INTF_SIG 135 + ")" + NODE_ITERATOR_SIG ); 136 il.append(new INVOKESTATIC(convert)); 137 } 138 else { 139 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 140 toString(), clazz.getName()); 141 classGen.getParser().reportError(Constants.FATAL, err); 142 } 143 } 144 145 146 /** 147 * Translates a node-set into a synthesized boolean. 148 * The boolean value of a node-set is "true" if non-empty 149 * and "false" otherwise. Notice that the 150 * function getFirstNode() is called in translateToDesynthesized(). 151 * 152 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 153 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type)154 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 155 BooleanType type) { 156 final InstructionList il = methodGen.getInstructionList(); 157 FlowList falsel = translateToDesynthesized(classGen, methodGen, type); 158 il.append(ICONST_1); 159 final BranchHandle truec = il.append(new GOTO(null)); 160 falsel.backPatch(il.append(ICONST_0)); 161 truec.setTarget(il.append(NOP)); 162 } 163 164 /** 165 * Translates a node-set into a string. The string value of a node-set is 166 * value of its first element. 167 * 168 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 169 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, StringType type)170 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 171 StringType type) { 172 final InstructionList il = methodGen.getInstructionList(); 173 getFirstNode(classGen, methodGen); 174 il.append(DUP); 175 final BranchHandle falsec = il.append(new IFLT(null)); 176 Type.Node.translateTo(classGen, methodGen, type); 177 final BranchHandle truec = il.append(new GOTO(null)); 178 falsec.setTarget(il.append(POP)); 179 il.append(new PUSH(classGen.getConstantPool(), "")); 180 truec.setTarget(il.append(NOP)); 181 } 182 183 /** 184 * Expects a node-set on the stack and pushes a real. 185 * First the node-set is converted to string, and from string to real. 186 * 187 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 188 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, RealType type)189 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 190 RealType type) { 191 translateTo(classGen, methodGen, Type.String); 192 Type.String.translateTo(classGen, methodGen, Type.Real); 193 } 194 195 /** 196 * Expects a node-set on the stack and pushes a node. 197 * 198 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 199 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, NodeType type)200 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 201 NodeType type) { 202 getFirstNode(classGen, methodGen); 203 } 204 205 /** 206 * Subsume node-set into ObjectType. 207 * 208 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 209 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, ObjectType type)210 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 211 ObjectType type) { 212 methodGen.getInstructionList().append(NOP); 213 } 214 215 /** 216 * Translates a node-set into a non-synthesized boolean. It does not 217 * push a 0 or a 1 but instead returns branchhandle list to be appended 218 * to the false list. 219 * 220 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized 221 */ translateToDesynthesized(ClassGenerator classGen, MethodGenerator methodGen, BooleanType type)222 public FlowList translateToDesynthesized(ClassGenerator classGen, 223 MethodGenerator methodGen, 224 BooleanType type) { 225 final InstructionList il = methodGen.getInstructionList(); 226 getFirstNode(classGen, methodGen); 227 return new FlowList(il.append(new IFLT(null))); 228 } 229 230 /** 231 * Expects a node-set on the stack and pushes a boxed node-set. 232 * Node sets are already boxed so the translation is just a NOP. 233 * 234 * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo 235 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, ReferenceType type)236 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 237 ReferenceType type) { 238 methodGen.getInstructionList().append(NOP); 239 } 240 241 /** 242 * Translates a node-set into the Java type denoted by <code>clazz</code>. 243 * Expects a node-set on the stack and pushes an object of the appropriate 244 * type after coercion. 245 */ translateTo(ClassGenerator classGen, MethodGenerator methodGen, Class clazz)246 public void translateTo(ClassGenerator classGen, MethodGenerator methodGen, 247 Class clazz) { 248 final ConstantPoolGen cpg = classGen.getConstantPool(); 249 final InstructionList il = methodGen.getInstructionList(); 250 final String className = clazz.getName(); 251 252 il.append(methodGen.loadDOM()); 253 il.append(SWAP); 254 255 if (className.equals("org.w3c.dom.Node")) { 256 int index = cpg.addInterfaceMethodref(DOM_INTF, 257 MAKE_NODE, 258 MAKE_NODE_SIG2); 259 il.append(new INVOKEINTERFACE(index, 2)); 260 } 261 else if (className.equals("org.w3c.dom.NodeList") || 262 className.equals("java.lang.Object")) { 263 int index = cpg.addInterfaceMethodref(DOM_INTF, 264 MAKE_NODE_LIST, 265 MAKE_NODE_LIST_SIG2); 266 il.append(new INVOKEINTERFACE(index, 2)); 267 } 268 else if (className.equals("java.lang.String")) { 269 int next = cpg.addInterfaceMethodref(NODE_ITERATOR, 270 "next", "()I"); 271 int index = cpg.addInterfaceMethodref(DOM_INTF, 272 GET_NODE_VALUE, 273 "(I)"+STRING_SIG); 274 275 // Get next node from the iterator 276 il.append(new INVOKEINTERFACE(next, 1)); 277 // Get the node's string value (from the DOM) 278 il.append(new INVOKEINTERFACE(index, 2)); 279 280 } 281 else { 282 ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR, 283 toString(), className); 284 classGen.getParser().reportError(Constants.FATAL, err); 285 } 286 } 287 288 /** 289 * Some type conversions require gettting the first node from the node-set. 290 * This function is defined to avoid code repetition. 291 */ getFirstNode(ClassGenerator classGen, MethodGenerator methodGen)292 private void getFirstNode(ClassGenerator classGen, MethodGenerator methodGen) { 293 final ConstantPoolGen cpg = classGen.getConstantPool(); 294 final InstructionList il = methodGen.getInstructionList(); 295 il.append(new INVOKEINTERFACE(cpg.addInterfaceMethodref(NODE_ITERATOR, 296 NEXT, 297 NEXT_SIG), 1)); 298 } 299 300 /** 301 * Translates an object of this type to its boxed representation. 302 */ translateBox(ClassGenerator classGen, MethodGenerator methodGen)303 public void translateBox(ClassGenerator classGen, 304 MethodGenerator methodGen) { 305 translateTo(classGen, methodGen, Type.Reference); 306 } 307 308 /** 309 * Translates an object of this type to its unboxed representation. 310 */ translateUnBox(ClassGenerator classGen, MethodGenerator methodGen)311 public void translateUnBox(ClassGenerator classGen, 312 MethodGenerator methodGen) { 313 methodGen.getInstructionList().append(NOP); 314 } 315 316 /** 317 * Returns the class name of an internal type's external representation. 318 */ getClassName()319 public String getClassName() { 320 return(NODE_ITERATOR); 321 } 322 323 LOAD(int slot)324 public Instruction LOAD(int slot) { 325 return new ALOAD(slot); 326 } 327 STORE(int slot)328 public Instruction STORE(int slot) { 329 return new ASTORE(slot); 330 } 331 } 332