1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: NodeType.java,v 1.12 2004/02/16 22:26:45 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler.util;
  20. import com.sun.org.apache.bcel.internal.generic.BranchHandle;
  21. import com.sun.org.apache.bcel.internal.generic.CHECKCAST;
  22. import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  23. import com.sun.org.apache.bcel.internal.generic.GETFIELD;
  24. import com.sun.org.apache.bcel.internal.generic.GOTO;
  25. import com.sun.org.apache.bcel.internal.generic.IFEQ;
  26. import com.sun.org.apache.bcel.internal.generic.ILOAD;
  27. import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  28. import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL;
  29. import com.sun.org.apache.bcel.internal.generic.ISTORE;
  30. import com.sun.org.apache.bcel.internal.generic.Instruction;
  31. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  32. import com.sun.org.apache.bcel.internal.generic.NEW;
  33. import com.sun.org.apache.bcel.internal.generic.PUSH;
  34. import com.sun.org.apache.xalan.internal.xsltc.compiler.Constants;
  35. import com.sun.org.apache.xalan.internal.xsltc.compiler.FlowList;
  36. import com.sun.org.apache.xalan.internal.xsltc.compiler.NodeTest;
  37. /**
  38. * @author Jacek Ambroziak
  39. * @author Santiago Pericas-Geertsen
  40. */
  41. public final class NodeType extends Type {
  42. private final int _type;
  43. protected NodeType() {
  44. this(NodeTest.ANODE);
  45. }
  46. protected NodeType(int type) {
  47. _type = type;
  48. }
  49. public int getType() {
  50. return _type;
  51. }
  52. public String toString() {
  53. return "node-type";
  54. }
  55. public boolean identicalTo(Type other) {
  56. return other instanceof NodeType;
  57. }
  58. public int hashCode() {
  59. return _type;
  60. }
  61. public String toSignature() {
  62. return "I";
  63. }
  64. public com.sun.org.apache.bcel.internal.generic.Type toJCType() {
  65. return com.sun.org.apache.bcel.internal.generic.Type.INT;
  66. }
  67. /**
  68. * Translates a node into an object of internal type <code>type</code>.
  69. * The translation to int is undefined since nodes are always converted
  70. * to reals in arithmetic expressions.
  71. *
  72. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  73. */
  74. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  75. Type type) {
  76. if (type == Type.String) {
  77. translateTo(classGen, methodGen, (StringType) type);
  78. }
  79. else if (type == Type.Boolean) {
  80. translateTo(classGen, methodGen, (BooleanType) type);
  81. }
  82. else if (type == Type.Real) {
  83. translateTo(classGen, methodGen, (RealType) type);
  84. }
  85. else if (type == Type.NodeSet) {
  86. translateTo(classGen, methodGen, (NodeSetType) type);
  87. }
  88. else if (type == Type.Reference) {
  89. translateTo(classGen, methodGen, (ReferenceType) type);
  90. }
  91. else if (type == Type.Object) {
  92. translateTo(classGen, methodGen, (ObjectType) type);
  93. }
  94. else {
  95. ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
  96. toString(), type.toString());
  97. classGen.getParser().reportError(Constants.FATAL, err);
  98. }
  99. }
  100. /**
  101. * Expects a node on the stack and pushes its string value.
  102. *
  103. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  104. */
  105. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  106. StringType type) {
  107. final ConstantPoolGen cpg = classGen.getConstantPool();
  108. final InstructionList il = methodGen.getInstructionList();
  109. switch (_type) {
  110. case NodeTest.ROOT:
  111. case NodeTest.ELEMENT:
  112. il.append(methodGen.loadDOM());
  113. il.append(SWAP); // dom ref must be below node index
  114. int index = cpg.addInterfaceMethodref(DOM_INTF,
  115. GET_ELEMENT_VALUE,
  116. GET_ELEMENT_VALUE_SIG);
  117. il.append(new INVOKEINTERFACE(index, 2));
  118. break;
  119. case NodeTest.ANODE:
  120. case NodeTest.COMMENT:
  121. case NodeTest.ATTRIBUTE:
  122. case NodeTest.PI:
  123. il.append(methodGen.loadDOM());
  124. il.append(SWAP); // dom ref must be below node index
  125. index = cpg.addInterfaceMethodref(DOM_INTF,
  126. GET_NODE_VALUE,
  127. GET_NODE_VALUE_SIG);
  128. il.append(new INVOKEINTERFACE(index, 2));
  129. break;
  130. default:
  131. ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
  132. toString(), type.toString());
  133. classGen.getParser().reportError(Constants.FATAL, err);
  134. break;
  135. }
  136. }
  137. /**
  138. * Translates a node into a synthesized boolean.
  139. * If the expression is "@attr",
  140. * then "true" is pushed iff "attr" is an attribute of the current node.
  141. * If the expression is ".", the result is always "true".
  142. *
  143. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  144. */
  145. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  146. BooleanType type) {
  147. final InstructionList il = methodGen.getInstructionList();
  148. FlowList falsel = translateToDesynthesized(classGen, methodGen, type);
  149. il.append(ICONST_1);
  150. final BranchHandle truec = il.append(new GOTO(null));
  151. falsel.backPatch(il.append(ICONST_0));
  152. truec.setTarget(il.append(NOP));
  153. }
  154. /**
  155. * Expects a node on the stack and pushes a real.
  156. * First the node is converted to string, and from string to real.
  157. *
  158. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  159. */
  160. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  161. RealType type) {
  162. translateTo(classGen, methodGen, Type.String);
  163. Type.String.translateTo(classGen, methodGen, Type.Real);
  164. }
  165. /**
  166. * Expects a node on the stack and pushes a singleton node-set. Singleton
  167. * iterators are already started after construction.
  168. *
  169. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  170. */
  171. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  172. NodeSetType type) {
  173. ConstantPoolGen cpg = classGen.getConstantPool();
  174. InstructionList il = methodGen.getInstructionList();
  175. // Create a new instance of SingletonIterator
  176. il.append(new NEW(cpg.addClass(SINGLETON_ITERATOR)));
  177. il.append(DUP_X1);
  178. il.append(SWAP);
  179. final int init = cpg.addMethodref(SINGLETON_ITERATOR, "<init>",
  180. "(" + NODE_SIG +")V");
  181. il.append(new INVOKESPECIAL(init));
  182. }
  183. /**
  184. * Subsume Node into ObjectType.
  185. *
  186. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  187. */
  188. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  189. ObjectType type) {
  190. methodGen.getInstructionList().append(NOP);
  191. }
  192. /**
  193. * Translates a node into a non-synthesized boolean. It does not push a
  194. * 0 or a 1 but instead returns branchhandle list to be appended to the
  195. * false list.
  196. *
  197. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateToDesynthesized
  198. */
  199. public FlowList translateToDesynthesized(ClassGenerator classGen,
  200. MethodGenerator methodGen,
  201. BooleanType type) {
  202. final InstructionList il = methodGen.getInstructionList();
  203. return new FlowList(il.append(new IFEQ(null)));
  204. }
  205. /**
  206. * Expects a node on the stack and pushes a boxed node. Boxed nodes
  207. * are represented by an instance of <code>com.sun.org.apache.xalan.internal.xsltc.dom.Node</code>.
  208. *
  209. * @see com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type#translateTo
  210. */
  211. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  212. ReferenceType type) {
  213. final ConstantPoolGen cpg = classGen.getConstantPool();
  214. final InstructionList il = methodGen.getInstructionList();
  215. il.append(new NEW(cpg.addClass(RUNTIME_NODE_CLASS)));
  216. il.append(DUP_X1);
  217. il.append(SWAP);
  218. il.append(new PUSH(cpg, _type));
  219. il.append(new INVOKESPECIAL(cpg.addMethodref(RUNTIME_NODE_CLASS,
  220. "<init>", "(II)V")));
  221. }
  222. /**
  223. * Translates a node into the Java type denoted by <code>clazz</code>.
  224. * Expects a node on the stack and pushes an object of the appropriate
  225. * type after coercion.
  226. */
  227. public void translateTo(ClassGenerator classGen, MethodGenerator methodGen,
  228. Class clazz) {
  229. final ConstantPoolGen cpg = classGen.getConstantPool();
  230. final InstructionList il = methodGen.getInstructionList();
  231. String className = clazz.getName();
  232. if (className.equals("java.lang.String")) {
  233. translateTo(classGen, methodGen, Type.String);
  234. return;
  235. }
  236. il.append(methodGen.loadDOM());
  237. il.append(SWAP); // dom ref must be below node index
  238. if (className.equals("org.w3c.dom.Node") ||
  239. className.equals("java.lang.Object")) {
  240. int index = cpg.addInterfaceMethodref(DOM_INTF,
  241. MAKE_NODE,
  242. MAKE_NODE_SIG);
  243. il.append(new INVOKEINTERFACE(index, 2));
  244. }
  245. else if (className.equals("org.w3c.dom.NodeList")) {
  246. int index = cpg.addInterfaceMethodref(DOM_INTF,
  247. MAKE_NODE_LIST,
  248. MAKE_NODE_LIST_SIG);
  249. il.append(new INVOKEINTERFACE(index, 2));
  250. }
  251. else {
  252. ErrorMsg err = new ErrorMsg(ErrorMsg.DATA_CONVERSION_ERR,
  253. toString(), className);
  254. classGen.getParser().reportError(Constants.FATAL, err);
  255. }
  256. }
  257. /**
  258. * Translates an object of this type to its boxed representation.
  259. */
  260. public void translateBox(ClassGenerator classGen,
  261. MethodGenerator methodGen) {
  262. translateTo(classGen, methodGen, Type.Reference);
  263. }
  264. /**
  265. * Translates an object of this type to its unboxed representation.
  266. */
  267. public void translateUnBox(ClassGenerator classGen,
  268. MethodGenerator methodGen) {
  269. final ConstantPoolGen cpg = classGen.getConstantPool();
  270. final InstructionList il = methodGen.getInstructionList();
  271. il.append(new CHECKCAST(cpg.addClass(RUNTIME_NODE_CLASS)));
  272. il.append(new GETFIELD(cpg.addFieldref(RUNTIME_NODE_CLASS,
  273. NODE_FIELD,
  274. NODE_FIELD_SIG)));
  275. }
  276. /**
  277. * Returns the class name of an internal type's external representation.
  278. */
  279. public String getClassName() {
  280. return(RUNTIME_NODE_CLASS);
  281. }
  282. public Instruction LOAD(int slot) {
  283. return new ILOAD(slot);
  284. }
  285. public Instruction STORE(int slot) {
  286. return new ISTORE(slot);
  287. }
  288. }