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.ALOAD;
  25 import com.sun.org.apache.bcel.internal.generic.ASTORE;
  26 import com.sun.org.apache.bcel.internal.generic.BranchHandle;
  27 import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  28 import com.sun.org.apache.bcel.internal.generic.IFEQ;
  29 import com.sun.org.apache.bcel.internal.generic.IFNULL;
  30 import com.sun.org.apache.bcel.internal.generic.ILOAD;
  31 import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  32 import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  33 import com.sun.org.apache.bcel.internal.generic.ISTORE;
  34 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
  35 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  36 import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
  37 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  38 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  39 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  40 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  41 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  42 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  43 
  44 /**
  45  * @author Jacek Ambroziak
  46  * @author Santiago Pericas-Geertsen
  47  */
  48 final class Copy extends Instruction {
  49     private UseAttributeSets _useSets;
  50 
  51     public void parseContents(Parser parser) {
  52         final String useSets = getAttribute("use-attribute-sets");
  53         if (useSets.length() > 0) {
  54             if (!Util.isValidQNames(useSets)) {
  55                 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, useSets, this);
  56                 parser.reportError(Constants.ERROR, err);
  57             }
  58             _useSets = new UseAttributeSets(useSets, parser);
  59         }
  60         parseChildren(parser);
  61     }
  62 
  63     public void display(int indent) {
  64         indent(indent);
  65         Util.println("Copy");
  66         indent(indent + IndentIncrement);
  67         displayContents(indent + IndentIncrement);
  68     }
  69 
  70     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  71         if (_useSets != null) {
  72             _useSets.typeCheck(stable);
  73         }
  74         typeCheckContents(stable);
  75         return Type.Void;
  76     }
  77 
  78     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  79         final ConstantPoolGen cpg = classGen.getConstantPool();
  80         final InstructionList il = methodGen.getInstructionList();
  81 
  82         final LocalVariableGen name =
  83             methodGen.addLocalVariable2("name",
  84                                         Util.getJCRefType(STRING_SIG),
  85                                         null);
  86         final LocalVariableGen length =
  87             methodGen.addLocalVariable2("length",
  88                                         Util.getJCRefType("I"),
  89                                         null);
  90 
  91         // Get the name of the node to copy and save for later
  92         il.append(methodGen.loadDOM());
  93         il.append(methodGen.loadCurrentNode());
  94         il.append(methodGen.loadHandler());
  95         final int cpy = cpg.addInterfaceMethodref(DOM_INTF,
  96                                                   "shallowCopy",
  97                                                   "("
  98                                                   + NODE_SIG
  99                                                   + TRANSLET_OUTPUT_SIG
 100                                                   + ")" + STRING_SIG);
 101         il.append(new INVOKEINTERFACE(cpy, 3));
 102         il.append(DUP);
 103         name.setStart(il.append(new ASTORE(name.getIndex())));
 104         final BranchHandle ifBlock1 = il.append(new IFNULL(null));
 105 
 106         // Get the length of the node name and save for later
 107         il.append(new ALOAD(name.getIndex()));
 108         final int lengthMethod = cpg.addMethodref(STRING_CLASS,"length","()I");
 109         il.append(new INVOKEVIRTUAL(lengthMethod));
 110         il.append(DUP);
 111         length.setStart(il.append(new ISTORE(length.getIndex())));
 112 
 113         // Ignore attribute sets if current node is ROOT. DOM.shallowCopy()
 114         // returns "" for ROOT, so skip attribute sets if length == 0
 115         final BranchHandle ifBlock4 = il.append(new IFEQ(null));
 116 
 117         // Copy in attribute sets if specified
 118         if (_useSets != null) {
 119             // If the parent of this element will result in an element being
 120             // output then we know that it is safe to copy out the attributes
 121             final SyntaxTreeNode parent = getParent();
 122             if ((parent instanceof LiteralElement) ||
 123                 (parent instanceof LiteralElement)) {
 124                 _useSets.translate(classGen, methodGen);
 125             }
 126             // If not we have to check to see if the copy will result in an
 127             // element being output.
 128             else {
 129                 // check if element; if not skip to translate body
 130                 il.append(new ILOAD(length.getIndex()));
 131                 final BranchHandle ifBlock2 = il.append(new IFEQ(null));
 132                 // length != 0 -> element -> do attribute sets
 133                 _useSets.translate(classGen, methodGen);
 134                 // not an element; root
 135                 ifBlock2.setTarget(il.append(NOP));
 136             }
 137         }
 138 
 139         // Instantiate body of xsl:copy
 140         ifBlock4.setTarget(il.append(NOP));
 141         translateContents(classGen, methodGen);
 142 
 143         // Call the output handler's endElement() if we copied an element
 144         // (The DOM.shallowCopy() method calls startElement().)
 145         length.setEnd(il.append(new ILOAD(length.getIndex())));
 146         final BranchHandle ifBlock3 = il.append(new IFEQ(null));
 147         il.append(methodGen.loadHandler());
 148         name.setEnd(il.append(new ALOAD(name.getIndex())));
 149         il.append(methodGen.endElement());
 150 
 151         final InstructionHandle end = il.append(NOP);
 152         ifBlock1.setTarget(end);
 153         ifBlock3.setTarget(end);
 154         methodGen.removeLocalVariable(name);
 155         methodGen.removeLocalVariable(length);
 156     }
 157 }