/* * Copyright 2001-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * $Id: Copy.java,v 1.11 2004/02/24 03:55:47 zongaro Exp $ */ package com.sun.org.apache.xalan.internal.xsltc.compiler; import com.sun.org.apache.bcel.internal.generic.ALOAD; import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.BranchHandle; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.IFEQ; import com.sun.org.apache.bcel.internal.generic.IFNULL; import com.sun.org.apache.bcel.internal.generic.ILOAD; import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.ISTORE; import com.sun.org.apache.bcel.internal.generic.InstructionHandle; import com.sun.org.apache.bcel.internal.generic.InstructionList; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; /** * @author Jacek Ambroziak * @author Santiago Pericas-Geertsen */ final class Copy extends Instruction { private UseAttributeSets _useSets; public void parseContents(Parser parser) { final String useSets = getAttribute("use-attribute-sets"); if (useSets.length() > 0) { if (!Util.isValidQNames(useSets)) { ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, useSets, this); parser.reportError(Constants.ERROR, err); } _useSets = new UseAttributeSets(useSets, parser); } parseChildren(parser); } public void display(int indent) { indent(indent); Util.println("Copy"); indent(indent + IndentIncrement); displayContents(indent + IndentIncrement); } public Type typeCheck(SymbolTable stable) throws TypeCheckError { if (_useSets != null) { _useSets.typeCheck(stable); } typeCheckContents(stable); return Type.Void; } public void translate(ClassGenerator classGen, MethodGenerator methodGen) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); final LocalVariableGen name = methodGen.addLocalVariable2("name", Util.getJCRefType(STRING_SIG), il.getEnd()); final LocalVariableGen length = methodGen.addLocalVariable2("length", Util.getJCRefType("I"), il.getEnd()); // Get the name of the node to copy and save for later il.append(methodGen.loadDOM()); il.append(methodGen.loadCurrentNode()); il.append(methodGen.loadHandler()); final int cpy = cpg.addInterfaceMethodref(DOM_INTF, "shallowCopy", "(" + NODE_SIG + TRANSLET_OUTPUT_SIG + ")" + STRING_SIG); il.append(new INVOKEINTERFACE(cpy, 3)); il.append(DUP); il.append(new ASTORE(name.getIndex())); final BranchHandle ifBlock1 = il.append(new IFNULL(null)); // Get the length of the node name and save for later il.append(new ALOAD(name.getIndex())); final int lengthMethod = cpg.addMethodref(STRING_CLASS,"length","()I"); il.append(new INVOKEVIRTUAL(lengthMethod)); il.append(new ISTORE(length.getIndex())); // Copy in attribute sets if specified if (_useSets != null) { // If the parent of this element will result in an element being // output then we know that it is safe to copy out the attributes final SyntaxTreeNode parent = getParent(); if ((parent instanceof LiteralElement) || (parent instanceof LiteralElement)) { _useSets.translate(classGen, methodGen); } // If not we have to check to see if the copy will result in an // element being output. else { // check if element; if not skip to translate body il.append(new ILOAD(length.getIndex())); final BranchHandle ifBlock2 = il.append(new IFEQ(null)); // length != 0 -> element -> do attribute sets _useSets.translate(classGen, methodGen); // not an element; root ifBlock2.setTarget(il.append(NOP)); } } // Instantiate body of xsl:copy translateContents(classGen, methodGen); // Call the output handler's endElement() if we copied an element // (The DOM.shallowCopy() method calls startElement().) il.append(new ILOAD(length.getIndex())); final BranchHandle ifBlock3 = il.append(new IFEQ(null)); il.append(methodGen.loadHandler()); il.append(new ALOAD(name.getIndex())); il.append(methodGen.endElement()); final InstructionHandle end = il.append(NOP); ifBlock1.setTarget(end); ifBlock3.setTarget(end); methodGen.removeLocalVariable(name); methodGen.removeLocalVariable(length); } }