|
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 il.getEnd()); |
|
88 final LocalVariableGen length = |
|
89 methodGen.addLocalVariable2("length", |
|
90 Util.getJCRefType("I"), |
|
91 il.getEnd()); |
|
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 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 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 il.append(new ILOAD(length.getIndex())); |
|
148 final BranchHandle ifBlock3 = il.append(new IFEQ(null)); |
|
149 il.append(methodGen.loadHandler()); |
|
150 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 } |