1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: Copy.java,v 1.11 2004/02/24 03:55:47 zongaro Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler;
  20. import com.sun.org.apache.bcel.internal.generic.ALOAD;
  21. import com.sun.org.apache.bcel.internal.generic.ASTORE;
  22. import com.sun.org.apache.bcel.internal.generic.BranchHandle;
  23. import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen;
  24. import com.sun.org.apache.bcel.internal.generic.IFEQ;
  25. import com.sun.org.apache.bcel.internal.generic.IFNULL;
  26. import com.sun.org.apache.bcel.internal.generic.ILOAD;
  27. import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE;
  28. import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL;
  29. import com.sun.org.apache.bcel.internal.generic.ISTORE;
  30. import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
  31. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  32. import com.sun.org.apache.bcel.internal.generic.LocalVariableGen;
  33. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  34. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  35. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  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. * @author Jacek Ambroziak
  41. * @author Santiago Pericas-Geertsen
  42. */
  43. final class Copy extends Instruction {
  44. private UseAttributeSets _useSets;
  45. public void parseContents(Parser parser) {
  46. final String useSets = getAttribute("use-attribute-sets");
  47. if (useSets.length() > 0) {
  48. if (!Util.isValidQNames(useSets)) {
  49. ErrorMsg err = new ErrorMsg(ErrorMsg.INVALID_QNAME_ERR, useSets, this);
  50. parser.reportError(Constants.ERROR, err);
  51. }
  52. _useSets = new UseAttributeSets(useSets, parser);
  53. }
  54. parseChildren(parser);
  55. }
  56. public void display(int indent) {
  57. indent(indent);
  58. Util.println("Copy");
  59. indent(indent + IndentIncrement);
  60. displayContents(indent + IndentIncrement);
  61. }
  62. public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  63. if (_useSets != null) {
  64. _useSets.typeCheck(stable);
  65. }
  66. typeCheckContents(stable);
  67. return Type.Void;
  68. }
  69. public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  70. final ConstantPoolGen cpg = classGen.getConstantPool();
  71. final InstructionList il = methodGen.getInstructionList();
  72. final LocalVariableGen name =
  73. methodGen.addLocalVariable2("name",
  74. Util.getJCRefType(STRING_SIG),
  75. il.getEnd());
  76. final LocalVariableGen length =
  77. methodGen.addLocalVariable2("length",
  78. Util.getJCRefType("I"),
  79. il.getEnd());
  80. // Get the name of the node to copy and save for later
  81. il.append(methodGen.loadDOM());
  82. il.append(methodGen.loadCurrentNode());
  83. il.append(methodGen.loadHandler());
  84. final int cpy = cpg.addInterfaceMethodref(DOM_INTF,
  85. "shallowCopy",
  86. "("
  87. + NODE_SIG
  88. + TRANSLET_OUTPUT_SIG
  89. + ")" + STRING_SIG);
  90. il.append(new INVOKEINTERFACE(cpy, 3));
  91. il.append(DUP);
  92. il.append(new ASTORE(name.getIndex()));
  93. final BranchHandle ifBlock1 = il.append(new IFNULL(null));
  94. // Get the length of the node name and save for later
  95. il.append(new ALOAD(name.getIndex()));
  96. final int lengthMethod = cpg.addMethodref(STRING_CLASS,"length","()I");
  97. il.append(new INVOKEVIRTUAL(lengthMethod));
  98. il.append(new ISTORE(length.getIndex()));
  99. // Copy in attribute sets if specified
  100. if (_useSets != null) {
  101. // If the parent of this element will result in an element being
  102. // output then we know that it is safe to copy out the attributes
  103. final SyntaxTreeNode parent = getParent();
  104. if ((parent instanceof LiteralElement) ||
  105. (parent instanceof LiteralElement)) {
  106. _useSets.translate(classGen, methodGen);
  107. }
  108. // If not we have to check to see if the copy will result in an
  109. // element being output.
  110. else {
  111. // check if element; if not skip to translate body
  112. il.append(new ILOAD(length.getIndex()));
  113. final BranchHandle ifBlock2 = il.append(new IFEQ(null));
  114. // length != 0 -> element -> do attribute sets
  115. _useSets.translate(classGen, methodGen);
  116. // not an element; root
  117. ifBlock2.setTarget(il.append(NOP));
  118. }
  119. }
  120. // Instantiate body of xsl:copy
  121. translateContents(classGen, methodGen);
  122. // Call the output handler's endElement() if we copied an element
  123. // (The DOM.shallowCopy() method calls startElement().)
  124. il.append(new ILOAD(length.getIndex()));
  125. final BranchHandle ifBlock3 = il.append(new IFEQ(null));
  126. il.append(methodGen.loadHandler());
  127. il.append(new ALOAD(name.getIndex()));
  128. il.append(methodGen.endElement());
  129. final InstructionHandle end = il.append(NOP);
  130. ifBlock1.setTarget(end);
  131. ifBlock3.setTarget(end);
  132. methodGen.removeLocalVariable(name);
  133. methodGen.removeLocalVariable(length);
  134. }
  135. }