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 }