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