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