KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > sf > saxon > sort > SortExpression


1 package net.sf.saxon.sort;
2 import net.sf.saxon.expr.*;
3 import net.sf.saxon.om.EmptyIterator;
4 import net.sf.saxon.om.NamePool;
5 import net.sf.saxon.om.SequenceIterator;
6 import net.sf.saxon.trans.XPathException;
7 import net.sf.saxon.type.ItemType;
8 import net.sf.saxon.value.Cardinality;
9 import net.sf.saxon.value.Value;
10
11 import java.io.PrintStream JavaDoc;
12 import java.util.ArrayList JavaDoc;
13 import java.util.Iterator JavaDoc;
14 import java.util.List JavaDoc;
15
16 /**
17 * Expression equivalent to the imaginary syntax
18  * expr sortby (sort-key)+
19 */

20
21 public class SortExpression extends ComputedExpression {
22
23     private Expression select = null;
24     private SortKeyDefinition[] sortKeys = null;
25     private FixedSortKeyDefinition[] fixedSortKeys = null;
26
27     public SortExpression( Expression select,
28                            SortKeyDefinition[] sortKeys ) {
29         this.select = select;
30         this.sortKeys = sortKeys;
31         boolean fixed = true;
32         for (int i = 0; i < sortKeys.length; i++) {
33             if (!(sortKeys[i] instanceof FixedSortKeyDefinition)) {
34                 fixed = false;
35                 break;
36             };
37             sortKeys[i].setParentExpression(this);
38         }
39         if (fixed) {
40             fixedSortKeys = new FixedSortKeyDefinition[sortKeys.length];
41             System.arraycopy(sortKeys, 0, fixedSortKeys, 0, sortKeys.length);
42         }
43         Iterator children = iterateSubExpressions();
44         while (children.hasNext()) {
45             Expression exp = (Expression)children.next();
46             adoptChildExpression(exp);
47         }
48     }
49
50     /**
51      * Get the immediate sub-expressions of this expression. Default implementation
52      * returns a zero-length array, appropriate for an expression that has no
53      * sub-expressions.
54      * @return an iterator containing the sub-expressions of this expression
55      */

56
57     public Iterator iterateSubExpressions() {
58         List JavaDoc list = new ArrayList JavaDoc(8);
59         list.add(select);
60         for (int i=0; i<sortKeys.length; i++) {
61             list.add(sortKeys[i].getSortKey());
62             Expression e = sortKeys[i].order;
63             if (e != null && !(e instanceof Value)) {
64                 list.add(e);
65             }
66             e = sortKeys[i].caseOrder;
67             if (e != null && !(e instanceof Value)) {
68                 list.add(e);
69             }
70             e = sortKeys[i].dataTypeExpression;
71             if (e != null && !(e instanceof Value)) {
72                 list.add(e);
73             }
74             e = sortKeys[i].language;
75             if (e != null && !(e instanceof Value)) {
76                 list.add(e);
77             }
78             e = sortKeys[i].collationName;
79             if (e != null && !(e instanceof Value)) {
80                 list.add(e);
81             }
82         }
83         return list.iterator();
84     }
85
86     /**
87     * Simplify an expression
88     */

89
90      public Expression simplify(StaticContext env) throws XPathException {
91         select = select.simplify(env);
92         return this;
93     }
94
95     /**
96     * Type-check the expression
97     */

98
99     public Expression typeCheck(StaticContext env, ItemType contextItemType) throws XPathException {
100         select = select.typeCheck(env, contextItemType);
101         return this;
102     }
103
104     /**
105      * Perform optimisation of an expression and its subexpressions.
106      * <p/>
107      * <p>This method is called after all references to functions and variables have been resolved
108      * to the declaration of the function or variable, and after all type checking has been done.</p>
109      *
110      * @param opt the optimizer in use. This provides access to supporting functions; it also allows
111      * different optimization strategies to be used in different circumstances.
112      * @param env the static context of the expression
113      * @param contextItemType the static type of "." at the point where this expression is invoked.
114      * The parameter is set to null if it is known statically that the context item will be undefined.
115      * If the type of the context item is not known statically, the argument is set to
116      * {@link net.sf.saxon.type.Type#ITEM_TYPE}
117      * @return the original expression, rewritten if appropriate to optimize execution
118      * @throws net.sf.saxon.trans.StaticError if an error is discovered during this phase
119      * (typically a type error)
120      */

121
122     public Expression optimize(Optimizer opt, StaticContext env, ItemType contextItemType) throws XPathException {
123         if (Cardinality.allowsMany(select.getCardinality())) {
124             return this;
125         } else {
126             return select;
127         }
128     }
129
130     /**
131      * Offer promotion for this subexpression. The offer will be accepted if the subexpression
132      * is not dependent on the factors (e.g. the context item) identified in the PromotionOffer.
133      * By default the offer is not accepted - this is appropriate in the case of simple expressions
134      * such as constant values and variable references where promotion would give no performance
135      * advantage. This method is always called at compile time.
136      *
137      * @param offer details of the offer, for example the offer to move
138      * expressions that don't depend on the context to an outer level in
139      * the containing expression
140      * @return if the offer is not accepted, return this expression unchanged.
141      * Otherwise return the result of rewriting the expression to promote
142      * this subexpression
143      * @throws net.sf.saxon.trans.XPathException
144      * if any error is detected
145      */

146
147     public Expression promote(PromotionOffer offer) throws XPathException {
148         Expression exp = offer.accept(this);
149         if (exp!=null) {
150             return exp;
151         } else {
152             select = doPromotion(select, offer);
153             for (int i=0; i<sortKeys.length; i++) {
154                 sortKeys[i].setSortKey((sortKeys[i].getSortKey().promote(offer)));
155                 if (sortKeys[i].caseOrder != null) {
156                     sortKeys[i].caseOrder = sortKeys[i].caseOrder.promote(offer);
157                 }
158                 if (sortKeys[i].dataTypeExpression != null) {
159                     sortKeys[i].dataTypeExpression = sortKeys[i].dataTypeExpression.promote(offer);
160                 }
161                 if (sortKeys[i].language != null) {
162                     sortKeys[i].language = sortKeys[i].language.promote(offer);
163                 }
164                 if (sortKeys[i].collationName != null) {
165                     sortKeys[i].collationName = sortKeys[i].collationName.promote(offer);
166                 }
167             }
168             return this;
169         }
170     }
171
172     /**
173      * Test whether a given expression is one of the sort keys
174      */

175
176     public boolean isSortKey(Expression child) {
177         for (int i=0; i<sortKeys.length; i++) {
178             Expression exp = sortKeys[i].getSortKey();
179             if (exp == child) {
180                 return true;
181             }
182         }
183         return false;
184     }
185
186     /**
187     * Determine the static cardinality
188     */

189
190     public int computeCardinality() {
191         return select.getCardinality();
192     }
193
194     /**
195     * Determine the data type of the items returned by the expression, if possible
196     * @return a value such as Type.STRING, Type.BOOLEAN, Type.NUMBER, Type.NODE,
197     * or Type.ITEM (meaning not known in advance)
198     */

199
200     public ItemType getItemType() {
201         return select.getItemType();
202     }
203     /**
204     * Get the static properties of this expression (other than its type). The result is
205     * bit-significant. These properties are used for optimizations. In general, if
206     * property bit is set, it is true, but if it is unset, the value is unknown.
207     */

208
209     public int computeSpecialProperties() {
210         int props = 0;
211         if ((select.getSpecialProperties() & StaticProperty.CONTEXT_DOCUMENT_NODESET) != 0) {
212             props |= StaticProperty.CONTEXT_DOCUMENT_NODESET;
213         }
214         if ((select.getSpecialProperties() & StaticProperty.SINGLE_DOCUMENT_NODESET) != 0) {
215             props |= StaticProperty.SINGLE_DOCUMENT_NODESET;
216         }
217         if ((select.getSpecialProperties() & StaticProperty.NON_CREATIVE) != 0) {
218             props |= StaticProperty.NON_CREATIVE;
219         }
220         return props;
221     }
222
223     /**
224     * Enumerate the results of the expression
225     */

226
227     public SequenceIterator iterate(XPathContext context) throws XPathException {
228
229         SequenceIterator iter = select.iterate(context);
230         if (iter instanceof EmptyIterator) {
231             return iter;
232         }
233         XPathContext xpc = context.newMinorContext();
234         xpc.setOrigin(this);
235
236         FixedSortKeyDefinition[] reducedSortKeys;
237         if (fixedSortKeys != null) {
238             reducedSortKeys = fixedSortKeys;
239         } else {
240             reducedSortKeys = new FixedSortKeyDefinition[sortKeys.length];
241             for (int s=0; s<sortKeys.length; s++) {
242                 reducedSortKeys[s] = sortKeys[s].reduce(xpc);
243             }
244         }
245         iter = new SortedIterator( xpc,
246                                     iter,
247                                     reducedSortKeys);
248         return iter;
249     }
250
251     public void display(int level, NamePool pool, PrintStream JavaDoc out) {
252         out.println(ExpressionTool.indent(level) + "sort");
253         select.display(level+1, pool, out);
254     }
255 }
256
257
258
259
260
261 //
262
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
263
// you may not use this file except in compliance with the License. You may obtain a copy of the
264
// License at http://www.mozilla.org/MPL/
265
//
266
// Software distributed under the License is distributed on an "AS IS" basis,
267
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
268
// See the License for the specific language governing rights and limitations under the License.
269
//
270
// The Original Code is: all this file.
271
//
272
// The Initial Developer of the Original Code is Michael H. Kay
273
//
274
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
275
//
276
// Contributor(s): none.
277
//
278
Popular Tags