KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > xsltc > compiler > ForEach


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: ForEach.java,v 1.19 2004/02/16 22:24:29 minchau Exp $
18  */

19
20 package org.apache.xalan.xsltc.compiler;
21
22 import java.util.Enumeration JavaDoc;
23 import java.util.Vector JavaDoc;
24
25 import org.apache.bcel.generic.BranchHandle;
26 import org.apache.bcel.generic.ConstantPoolGen;
27 import org.apache.bcel.generic.GOTO;
28 import org.apache.bcel.generic.IFGT;
29 import org.apache.bcel.generic.InstructionHandle;
30 import org.apache.bcel.generic.InstructionList;
31 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
32 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
33 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
34 import org.apache.xalan.xsltc.compiler.util.NodeSetType;
35 import org.apache.xalan.xsltc.compiler.util.NodeType;
36 import org.apache.xalan.xsltc.compiler.util.ReferenceType;
37 import org.apache.xalan.xsltc.compiler.util.ResultTreeType;
38 import org.apache.xalan.xsltc.compiler.util.Type;
39 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
40 import org.apache.xalan.xsltc.compiler.util.Util;
41
42 /**
43  * @author Jacek Ambroziak
44  * @author Santiago Pericas-Geertsen
45  * @author Morten Jorgensen
46  */

47 final class ForEach extends Instruction {
48
49     private Expression _select;
50     private Type _type;
51
52     public void display(int indent) {
53     indent(indent);
54     Util.println("ForEach");
55     indent(indent + IndentIncrement);
56     Util.println("select " + _select.toString());
57     displayContents(indent + IndentIncrement);
58     }
59         
60     public void parseContents(Parser parser) {
61     _select = parser.parseExpression(this, "select", null);
62
63     parseChildren(parser);
64
65         // make sure required attribute(s) have been set
66
if (_select.isDummy()) {
67         reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "select");
68         }
69     }
70     
71     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
72     _type = _select.typeCheck(stable);
73
74     if (_type instanceof ReferenceType || _type instanceof NodeType) {
75         _select = new CastExpr(_select, Type.NodeSet);
76         typeCheckContents(stable);
77         return Type.Void;
78     }
79     if (_type instanceof NodeSetType||_type instanceof ResultTreeType) {
80         typeCheckContents(stable);
81         return Type.Void;
82     }
83     throw new TypeCheckError(this);
84     }
85
86     public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
87     final ConstantPoolGen cpg = classGen.getConstantPool();
88     final InstructionList il = methodGen.getInstructionList();
89
90     // Save current node and current iterator on the stack
91
il.append(methodGen.loadCurrentNode());
92     il.append(methodGen.loadIterator());
93         
94     // Collect sort objects associated with this instruction
95
final Vector JavaDoc sortObjects = new Vector JavaDoc();
96     Enumeration JavaDoc children = elements();
97     while (children.hasMoreElements()) {
98         final Object JavaDoc child = children.nextElement();
99         if (child instanceof Sort) {
100         sortObjects.addElement(child);
101         }
102     }
103
104     if ((_type != null) && (_type instanceof ResultTreeType)) {
105         // Store existing DOM on stack - must be restored when loop is done
106
il.append(methodGen.loadDOM());
107
108         // <xsl:sort> cannot be applied to a result tree - issue warning
109
if (sortObjects.size() > 0) {
110         ErrorMsg msg = new ErrorMsg(ErrorMsg.RESULT_TREE_SORT_ERR,this);
111         getParser().reportError(WARNING, msg);
112         }
113
114         // Put the result tree on the stack (DOM)
115
_select.translate(classGen, methodGen);
116         // Get an iterator for the whole DOM - excluding the root node
117
_type.translateTo(classGen, methodGen, Type.NodeSet);
118         // Store the result tree as the default DOM
119
il.append(SWAP);
120         il.append(methodGen.storeDOM());
121     }
122     else {
123         // Compile node iterator
124
if (sortObjects.size() > 0) {
125         Sort.translateSortIterator(classGen, methodGen,
126                        _select, sortObjects);
127         }
128         else {
129         _select.translate(classGen, methodGen);
130         }
131
132         if (_type instanceof ReferenceType == false) {
133                 il.append(methodGen.loadContextNode());
134                 il.append(methodGen.setStartNode());
135         }
136     }
137
138
139     // Overwrite current iterator
140
il.append(methodGen.storeIterator());
141
142     // Give local variables (if any) default values before starting loop
143
initializeVariables(classGen, methodGen);
144
145     final BranchHandle nextNode = il.append(new GOTO(null));
146     final InstructionHandle loop = il.append(NOP);
147
148     translateContents(classGen, methodGen);
149             
150     nextNode.setTarget(il.append(methodGen.loadIterator()));
151     il.append(methodGen.nextNode());
152     il.append(DUP);
153     il.append(methodGen.storeCurrentNode());
154     il.append(new IFGT(loop));
155
156     // Restore current DOM (if result tree was used instead for this loop)
157
if ((_type != null) && (_type instanceof ResultTreeType)) {
158         il.append(methodGen.storeDOM());
159     }
160
161     // Restore current node and current iterator from the stack
162
il.append(methodGen.storeIterator());
163     il.append(methodGen.storeCurrentNode());
164     }
165
166     /**
167      * The code that is generated by nested for-each loops can appear to some
168      * JVMs as if it is accessing un-initialized variables. We must add some
169      * code that pushes the default variable value on the stack and pops it
170      * into the variable slot. This is done by the Variable.initialize()
171      * method. The code that we compile for this loop looks like this:
172      *
173      * initialize iterator
174      * initialize variables <-- HERE!!!
175      * goto Iterate
176      * Loop: :
177      * : (code for <xsl:for-each> contents)
178      * :
179      * Iterate: node = iterator.next();
180      * if (node != END) goto Loop
181      */

182     public void initializeVariables(ClassGenerator classGen,
183                    MethodGenerator methodGen) {
184     final int n = elementCount();
185     for (int i = 0; i < n; i++) {
186         final Object JavaDoc child = getContents().elementAt(i);
187         if (child instanceof Variable) {
188         Variable var = (Variable)child;
189         var.initialize(classGen, methodGen);
190         }
191     }
192     }
193
194 }
195
Popular Tags