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 
  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 
  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 
  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 
  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 }