001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements. See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership. The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the  "License");
007     * you may not use this file except in compliance with the License.
008     * You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing, software
013     * distributed under the License is distributed on an "AS IS" BASIS,
014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    /*
019     * $Id: CopyOf.java 468650 2006-10-28 07:03:30Z minchau $
020     */
021    
022    package org.apache.xalan.xsltc.compiler;
023    
024    import org.apache.bcel.generic.ConstantPoolGen;
025    import org.apache.bcel.generic.INVOKEINTERFACE;
026    import org.apache.bcel.generic.INVOKESTATIC;
027    import org.apache.bcel.generic.INVOKEVIRTUAL;
028    import org.apache.bcel.generic.InstructionList;
029    import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
030    import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
031    import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
032    import org.apache.xalan.xsltc.compiler.util.NodeSetType;
033    import org.apache.xalan.xsltc.compiler.util.NodeType;
034    import org.apache.xalan.xsltc.compiler.util.ReferenceType;
035    import org.apache.xalan.xsltc.compiler.util.ResultTreeType;
036    import org.apache.xalan.xsltc.compiler.util.Type;
037    import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
038    import org.apache.xalan.xsltc.compiler.util.Util;
039    
040    /**
041     * @author Jacek Ambroziak
042     * @author Santiago Pericas-Geertsen
043     */
044    final class CopyOf extends Instruction {
045        private Expression _select;
046            
047        public void display(int indent) {
048            indent(indent);
049            Util.println("CopyOf");
050            indent(indent + IndentIncrement);
051            Util.println("select " + _select.toString());
052        }
053    
054        public void parseContents(Parser parser) {
055            _select = parser.parseExpression(this, "select", null);
056            // make sure required attribute(s) have been set
057            if (_select.isDummy()) {
058                reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
059                return;
060            }
061        }
062            
063        public Type typeCheck(SymbolTable stable) throws TypeCheckError {
064            final Type tselect = _select.typeCheck(stable);
065            if (tselect instanceof NodeType ||
066                tselect instanceof NodeSetType ||
067                tselect instanceof ReferenceType ||
068                tselect instanceof ResultTreeType) {
069                // falls through 
070            }
071            else {
072                _select = new CastExpr(_select, Type.String);
073            }
074            return Type.Void;
075        }
076            
077        public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
078            final ConstantPoolGen cpg = classGen.getConstantPool();
079            final InstructionList il = methodGen.getInstructionList();
080            final Type tselect = _select.getType();
081    
082            final String CPY1_SIG = "("+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V";
083            final int cpy1 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY1_SIG);
084    
085            final String CPY2_SIG = "("+NODE_SIG+TRANSLET_OUTPUT_SIG+")V";
086            final int cpy2 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY2_SIG);
087            
088            final String getDoc_SIG = "()"+NODE_SIG;
089            final int getDoc = cpg.addInterfaceMethodref(DOM_INTF, "getDocument", getDoc_SIG);
090    
091    
092            if (tselect instanceof NodeSetType) {
093                il.append(methodGen.loadDOM());
094    
095                // push NodeIterator
096                _select.translate(classGen, methodGen);     
097                _select.startIterator(classGen, methodGen);
098    
099                // 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    }