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: Copy.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.ALOAD; 025 import org.apache.bcel.generic.ASTORE; 026 import org.apache.bcel.generic.BranchHandle; 027 import org.apache.bcel.generic.ConstantPoolGen; 028 import org.apache.bcel.generic.IFEQ; 029 import org.apache.bcel.generic.IFNULL; 030 import org.apache.bcel.generic.ILOAD; 031 import org.apache.bcel.generic.INVOKEINTERFACE; 032 import org.apache.bcel.generic.INVOKEVIRTUAL; 033 import org.apache.bcel.generic.ISTORE; 034 import org.apache.bcel.generic.InstructionHandle; 035 import org.apache.bcel.generic.InstructionList; 036 import org.apache.bcel.generic.LocalVariableGen; 037 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 038 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 039 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 040 import org.apache.xalan.xsltc.compiler.util.Type; 041 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 042 import org.apache.xalan.xsltc.compiler.util.Util; 043 044 /** 045 * @author Jacek Ambroziak 046 * @author Santiago Pericas-Geertsen 047 */ 048 final class Copy extends Instruction { 049 private UseAttributeSets _useSets; 050 051 public void parseContents(Parser parser) { 052 final String useSets = getAttribute("use-attribute-sets"); 053 if (useSets.length() > 0) { 054 if (!Util.isValidQNames(useSets)) { 055 ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, useSets, this); 056 parser.reportError(Constants.ERROR, err); 057 } 058 _useSets = new UseAttributeSets(useSets, parser); 059 } 060 parseChildren(parser); 061 } 062 063 public void display(int indent) { 064 indent(indent); 065 Util.println("Copy"); 066 indent(indent + IndentIncrement); 067 displayContents(indent + IndentIncrement); 068 } 069 070 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 071 if (_useSets != null) { 072 _useSets.typeCheck(stable); 073 } 074 typeCheckContents(stable); 075 return Type.Void; 076 } 077 078 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 079 final ConstantPoolGen cpg = classGen.getConstantPool(); 080 final InstructionList il = methodGen.getInstructionList(); 081 082 final LocalVariableGen name = 083 methodGen.addLocalVariable2("name", 084 Util.getJCRefType(STRING_SIG), 085 null); 086 final LocalVariableGen length = 087 methodGen.addLocalVariable2("length", 088 Util.getJCRefType("I"), 089 null); 090 091 // Get the name of the node to copy and save for later 092 il.append(methodGen.loadDOM()); 093 il.append(methodGen.loadCurrentNode()); 094 il.append(methodGen.loadHandler()); 095 final int cpy = cpg.addInterfaceMethodref(DOM_INTF, 096 "shallowCopy", 097 "(" 098 + NODE_SIG 099 + 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 length.setStart(il.append(new ISTORE(length.getIndex()))); 111 112 // Copy in attribute sets if specified 113 if (_useSets != null) { 114 // If the parent of this element will result in an element being 115 // output then we know that it is safe to copy out the attributes 116 final SyntaxTreeNode parent = getParent(); 117 if ((parent instanceof LiteralElement) || 118 (parent instanceof LiteralElement)) { 119 _useSets.translate(classGen, methodGen); 120 } 121 // If not we have to check to see if the copy will result in an 122 // element being output. 123 else { 124 // check if element; if not skip to translate body 125 il.append(new ILOAD(length.getIndex())); 126 final BranchHandle ifBlock2 = il.append(new IFEQ(null)); 127 // length != 0 -> element -> do attribute sets 128 _useSets.translate(classGen, methodGen); 129 // not an element; root 130 ifBlock2.setTarget(il.append(NOP)); 131 } 132 } 133 134 // Instantiate body of xsl:copy 135 translateContents(classGen, methodGen); 136 137 // Call the output handler's endElement() if we copied an element 138 // (The DOM.shallowCopy() method calls startElement().) 139 length.setEnd(il.append(new ILOAD(length.getIndex()))); 140 final BranchHandle ifBlock3 = il.append(new IFEQ(null)); 141 il.append(methodGen.loadHandler()); 142 name.setEnd(il.append(new ALOAD(name.getIndex()))); 143 il.append(methodGen.endElement()); 144 145 final InstructionHandle end = il.append(NOP); 146 ifBlock1.setTarget(end); 147 ifBlock3.setTarget(end); 148 methodGen.removeLocalVariable(name); 149 methodGen.removeLocalVariable(length); 150 } 151 }