KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > style > XSLChoose


1 package net.sf.saxon.style;
2 import net.sf.saxon.expr.Expression;
3 import net.sf.saxon.expr.ExpressionTool;
4 import net.sf.saxon.instruct.Choose;
5 import net.sf.saxon.instruct.Executable;
6 import net.sf.saxon.instruct.TraceWrapper;
7 import net.sf.saxon.om.AttributeCollection;
8 import net.sf.saxon.om.Axis;
9 import net.sf.saxon.om.AxisIterator;
10 import net.sf.saxon.om.NodeInfo;
11 import net.sf.saxon.trans.XPathException;
12 import net.sf.saxon.type.ItemType;
13 import net.sf.saxon.value.BooleanValue;
14 import net.sf.saxon.value.EmptySequence;
15
16 /**
17 * An xsl:choose elements in the stylesheet. <br>
18 */

19
20 public class XSLChoose extends StyleElement {
21
22     private StyleElement otherwise;
23     private int numberOfWhens = 0;
24
25     /**
26     * Determine whether this node is an instruction.
27     * @return true - it is an instruction
28     */

29
30     public boolean isInstruction() {
31         return true;
32     }
33
34     /**
35      * Determine the type of item returned by this instruction (only relevant if
36      * it is an instruction).
37      * @return the item type returned
38      */

39
40     protected ItemType getReturnedItemType() {
41         return getCommonChildItemType();
42     }
43
44     public void prepareAttributes() throws XPathException {
45         AttributeCollection atts = getAttributeList();
46         for (int a=0; a<atts.getLength(); a++) {
47             int nc = atts.getNameCode(a);
48             checkUnknownAttribute(nc);
49         }
50     }
51
52     public void validate() throws XPathException {
53         checkWithinTemplate();
54
55         AxisIterator kids = iterateAxis(Axis.CHILD);
56         while(true) {
57             NodeInfo curr = (NodeInfo)kids.next();
58             if (curr == null) {
59                 break;
60             }
61             if (curr instanceof XSLWhen) {
62                 if (otherwise!=null) {
63                     compileError("xsl:otherwise must come last", "XTSE0010");
64                 }
65                 numberOfWhens++;
66             } else if (curr instanceof XSLOtherwise) {
67                 if (otherwise!=null) {
68                     compileError("Only one xsl:otherwise allowed in an xsl:choose", "XTSE0010");
69                 } else {
70                     otherwise = (StyleElement)curr;
71                 }
72             } else {
73                 compileError("Only xsl:when and xsl:otherwise are allowed here", "XTSE0010");
74             }
75         }
76
77         if (numberOfWhens==0) {
78             compileError("xsl:choose must contain at least one xsl:when", "XTSE0010");
79         }
80     }
81
82     /**
83     * Mark tail-recursive calls on templates and functions.
84     */

85
86     public void markTailCalls() {
87         AxisIterator kids = iterateAxis(Axis.CHILD);
88         while(true) {
89             NodeInfo curr = (NodeInfo)kids.next();
90             if (curr == null) {
91                 return;
92             }
93             if (curr instanceof StyleElement) {
94                 ((StyleElement)curr).markTailCalls();
95             }
96         }
97     }
98
99
100     public Expression compile(Executable exec) throws XPathException {
101
102         int entries = numberOfWhens + (otherwise==null ? 0 : 1);
103         Expression[] conditions = new Expression[entries];
104         Expression[] actions = new Expression[entries];
105
106         int w = 0;
107         AxisIterator kids = iterateAxis(Axis.CHILD);
108         while(true) {
109             NodeInfo curr = (NodeInfo)kids.next();
110             if (curr == null) {
111                 break;
112             }
113             if (curr instanceof XSLWhen) {
114                 conditions[w] = ((XSLWhen)curr).getCondition();
115                 Expression b = ((XSLWhen)curr).compileSequenceConstructor(
116                         exec, curr.iterateAxis(Axis.CHILD), true);
117                 if (b == null) {
118                     b = EmptySequence.getInstance();
119                 }
120                 try {
121                     b = b.simplify(((XSLWhen)curr).getStaticContext());
122                     actions[w] = b;
123                 } catch (XPathException e) {
124                     compileError(e);
125                 }
126
127                 if (getConfiguration().getTraceListener() != null) {
128                     TraceWrapper trace = makeTraceInstruction((XSLWhen)curr, actions[w]);
129                     trace.setParentExpression((XSLWhen)curr);
130                     actions[w] = trace;
131                 }
132
133                 // Optimize for constant conditions (true or false)
134
if (conditions[w] instanceof BooleanValue) {
135                     if (((BooleanValue)conditions[w]).getBooleanValue()) {
136                         // constant true: truncate the tests here
137
entries = w+1;
138                         break;
139                     } else {
140                         // constant false: omit this test
141
w--;
142                         entries--;
143                     }
144                 }
145                 w++;
146             } else if (curr instanceof XSLOtherwise) {
147                 conditions[w] = BooleanValue.TRUE;
148                 Expression b = ((XSLOtherwise)curr).compileSequenceConstructor(
149                         exec, curr.iterateAxis(Axis.CHILD), true);
150                 if (b == null) {
151                     b = EmptySequence.getInstance();
152                 }
153                 try {
154                     b = b.simplify(((XSLOtherwise)curr).getStaticContext());
155                     actions[w] = b;
156                 } catch (XPathException e) {
157                     compileError(e);
158                 }
159                 if (getConfiguration().getTraceListener() != null) {
160                     TraceWrapper trace = makeTraceInstruction((XSLOtherwise)curr, actions[w]);
161                     trace.setParentExpression((XSLOtherwise)curr);
162                     actions[w] = trace;
163                 }
164                 w++;
165             } else {
166                 new AssertionError JavaDoc("Expected xsl:when or xsl:otherwise");
167             }
168         }
169
170         if (conditions.length != entries) {
171             // we've optimized some entries away
172
if (entries==0) {
173                 return null; // return a no-op
174
}
175             if (entries==1 && (conditions[0] instanceof BooleanValue)) {
176                 if (((BooleanValue)conditions[0]).getBooleanValue()) {
177                     // only one condition left, and it's known to be true: return the corresponding action
178
return actions[0];
179                 } else {
180                     // but if it's false, return a no-op
181
return null;
182                 }
183             }
184             Expression[] conditions2 = new Expression[entries];
185             System.arraycopy(conditions, 0, conditions2, 0, entries);
186             Expression[] actions2 = new Expression[entries];
187             System.arraycopy(actions, 0, actions2, 0, entries);
188             conditions = conditions2;
189             actions = actions2;
190         }
191
192         Choose ch = new Choose(conditions, actions);
193         ExpressionTool.makeParentReferences(ch);
194         return ch;
195     }
196
197 }
198
199 //
200
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
201
// you may not use this file except in compliance with the License. You may obtain a copy of the
202
// License at http://www.mozilla.org/MPL/
203
//
204
// Software distributed under the License is distributed on an "AS IS" basis,
205
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
206
// See the License for the specific language governing rights and limitations under the License.
207
//
208
// The Original Code is: all this file.
209
//
210
// The Initial Developer of the Original Code is Michael H. Kay.
211
//
212
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
213
//
214
// Contributor(s):
215
// Portions marked "e.g." are from Edwin Glaser (edwin@pannenleiter.de)
216
//
217
Popular Tags