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: CopyOf.java,v 1.2.4.1 2005/09/01 12:16:22 pvedula Exp $
  22  */
  23 
  24 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  25 
  26 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  27 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  28 import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC;
  29 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  30 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  33 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  34 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeSetType;
  35 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeType;
  36 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ReferenceType;
  37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType;
  38 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  39 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  40 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  41 
  42 /**
  43  * @author Jacek Ambroziak
  44  * @author Santiago Pericas-Geertsen
  45  */
  46 final class CopyOf extends Instruction {
  47     private Expression _select;
  48 
  49     public void display(int indent) {
  50         indent(indent);
  51         Util.println("CopyOf");
  52         indent(indent + IndentIncrement);
  53         Util.println("select " + _select.toString());
  54     }
  55 
  56     public void parseContents(Parser parser) {
  57         _select = parser.parseExpression(this, "select", null);
  58         // make sure required attribute(s) have been set
  59         if (_select.isDummy()) {
  60             reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
  61             return;
  62         }
  63     }
  64 
  65     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  66         final Type tselect = _select.typeCheck(stable);
  67         if (tselect instanceof NodeType ||
  68             tselect instanceof NodeSetType ||
  69             tselect instanceof ReferenceType ||
  70             tselect instanceof ResultTreeType) {
  71             // falls through
  72         }
  73         else {
  74             _select = new CastExpr(_select, Type.String);
  75         }
  76         return Type.Void;
  77     }
  78 
  79     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  80         final ConstantPoolGen cpg = classGen.getConstantPool();
  81         final InstructionList il = methodGen.getInstructionList();
  82         final Type tselect = _select.getType();
  83 
  84         final String CPY1_SIG = "("+NODE_ITERATOR_SIG+TRANSLET_OUTPUT_SIG+")V";
  85         final int cpy1 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY1_SIG);
  86 
  87         final String CPY2_SIG = "("+NODE_SIG+TRANSLET_OUTPUT_SIG+")V";
  88         final int cpy2 = cpg.addInterfaceMethodref(DOM_INTF, "copy", CPY2_SIG);
  89 
  90         final String getDoc_SIG = "()"+NODE_SIG;
  91         final int getDoc = cpg.addInterfaceMethodref(DOM_INTF, "getDocument", getDoc_SIG);
  92 
  93 
  94         if (tselect instanceof NodeSetType) {
  95             il.append(methodGen.loadDOM());
  96 
  97             // push NodeIterator
  98             _select.translate(classGen, methodGen);
  99             _select.startIterator(classGen, methodGen);
 100 
 101             // call copy from the DOM 'library'
 102             il.append(methodGen.loadHandler());
 103             il.append(new INVOKEINTERFACE(cpy1, 3));
 104         }
 105         else if (tselect instanceof NodeType) {
 106             il.append(methodGen.loadDOM());
 107             _select.translate(classGen, methodGen);
 108             il.append(methodGen.loadHandler());
 109             il.append(new INVOKEINTERFACE(cpy2, 3));
 110         }
 111         else if (tselect instanceof ResultTreeType) {
 112             _select.translate(classGen, methodGen);
 113             // We want the whole tree, so we start with the root node
 114             il.append(DUP); //need a pointer to the DOM ;
 115             il.append(new INVOKEINTERFACE(getDoc,1)); //ICONST_0);
 116             il.append(methodGen.loadHandler());
 117             il.append(new INVOKEINTERFACE(cpy2, 3));
 118         }
 119         else if (tselect instanceof ReferenceType) {
 120             _select.translate(classGen, methodGen);
 121             il.append(methodGen.loadHandler());
 122             il.append(methodGen.loadCurrentNode());
 123             il.append(methodGen.loadDOM());
 124             final int copy = cpg.addMethodref(BASIS_LIBRARY_CLASS, "copy",
 125                                               "("
 126                                               + OBJECT_SIG
 127                                               + TRANSLET_OUTPUT_SIG
 128                                               + NODE_SIG
 129                                               + DOM_INTF_SIG
 130                                               + ")V");
 131             il.append(new INVOKESTATIC(copy));
 132         }
 133         else {
 134             il.append(classGen.loadTranslet());
 135             _select.translate(classGen, methodGen);
 136             il.append(methodGen.loadHandler());
 137             il.append(new INVOKEVIRTUAL(cpg.addMethodref(TRANSLET_CLASS,
 138                                                          CHARACTERSW,
 139                                                          CHARACTERSW_SIG)));
 140         }
 141 
 142     }
 143 }