1 /*
2  * reserved comment block
3  * DO NOT REMOVE OR ALTER!
4  */
5 /*
6  * Licensed to the Apache Software Foundation (ASF) under one or more
7  * contributor license agreements.  See the NOTICE file distributed with
8  * this work for additional information regarding copyright ownership.
9  * The ASF licenses this file to You under the Apache License, Version 2.0
10  * (the "License"); you may not use this file except in compliance with
11  * the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  */
21 
22 package com.sun.org.apache.xalan.internal.xsltc.compiler;
23 
24 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
25 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
26 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
27 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
28 import com.sun.org.apache.bcel.internal.generic.InstructionList;
29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeSetType;
33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeType;
34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType;
35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType;
36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
38 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
39 
40 /**
41  * @author Jacek Ambroziak
42  * @author Santiago Pericas-Geertsen
43  */
44 final class CopyOf extends Instruction {
45     private Expression _select;
46 
display(int indent)47     public void display(int indent) {
48         indent(indent);
49         Util.println("CopyOf");
50         indent(indent + IndentIncrement);
51         Util.println("select " + _select.toString());
52     }
53 
parseContents(Parser parser)54     public void parseContents(Parser parser) {
55         _select = parser.parseExpression(this, "select", null);
56         // make sure required attribute(s) have been set
57         if (_select.isDummy()) {
58             reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
59             return;
60         }
61     }
62 
typeCheck(SymbolTable stable)63     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
64         final Type tselect = _select.typeCheck(stable);
65         if (tselect instanceof NodeType ||
66             tselect instanceof NodeSetType ||
67             tselect instanceof ReferenceType ||
68             tselect instanceof ResultTreeType) {
69             // falls through
70         }
71         else {
72             _select = new CastExpr(_select, Type.String);
73         }
74         return Type.Void;
75     }
76 
translate(ClassGenerator classGen, MethodGenerator methodGen)77     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
78         final ConstantPoolGen cpg = classGen.getConstantPool();
79         final InstructionList il = methodGen.getInstructionList();
80         final Type tselect = _select.getType();
81 
82         final String CPY1_SIG = "("+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V";
83         final int cpy1 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY1_SIG);
84 
85         final String CPY2_SIG = "("+NODE_SIG+TRANSLET_OUTPUT_SIG+")V";
86         final int cpy2 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY2_SIG);
87 
88         final String getDoc_SIG = "()"+NODE_SIG;
89         final int getDoc = cpg.addInterfaceMethodref(DOM_INTF, "getDocument", getDoc_SIG);
90 
91 
92         if (tselect instanceof NodeSetType) {
93             il.append(methodGen.loadDOM());
94 
95             // push NodeIterator
96             _select.translate(classGen, methodGen);
97             _select.startIterator(classGen, methodGen);
98 
99             // call copy from the DOM 'library'
100             il.append(methodGen.loadHandler());
101             il.append(new INVOKEINTERFACE(cpy1, 3));
102         }
103         else if (tselect instanceof NodeType) {
104             il.append(methodGen.loadDOM());
105             _select.translate(classGen, methodGen);
106             il.append(methodGen.loadHandler());
107             il.append(new INVOKEINTERFACE(cpy2, 3));
108         }
109         else if (tselect instanceof ResultTreeType) {
110             _select.translate(classGen, methodGen);
111             // We want the whole tree, so we start with the root node
112             il.append(DUP); //need a pointer to the DOM ;
113             il.append(new INVOKEINTERFACE(getDoc,1)); //ICONST_0);
114             il.append(methodGen.loadHandler());
115             il.append(new INVOKEINTERFACE(cpy2, 3));
116         }
117         else if (tselect instanceof ReferenceType) {
118             _select.translate(classGen, methodGen);
119             il.append(methodGen.loadHandler());
120             il.append(methodGen.loadCurrentNode());
121             il.append(methodGen.loadDOM());
122             final int copy = cpg.addMethodref(BASIS_LIBRARY_CLASS, "copy",
123                                               "("
124                                               + OBJECT_SIG
125                                               + TRANSLET_OUTPUT_SIG
126                                               + NODE_SIG
127                                               + DOM_INTF_SIG
128                                               + ")V");
129             il.append(new INVOKESTATIC(copy));
130         }
131         else {
132             il.append(classGen.loadTranslet());
133             _select.translate(classGen, methodGen);
134             il.append(methodGen.loadHandler());
135             il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
136                                                          CHARACTERSW,
137                                                          CHARACTERSW_SIG)));
138         }
139 
140     }
141 }
142