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