KickJava   Java API By Example, From Geeks To Geeks.

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


1 package net.sf.saxon.sort;
2 import net.sf.saxon.expr.Expression;
3 import net.sf.saxon.expr.XPathContext;
4 import net.sf.saxon.expr.Container;
5 import net.sf.saxon.instruct.Executable;
6 import net.sf.saxon.trans.DynamicError;
7 import net.sf.saxon.trans.XPathException;
8 import net.sf.saxon.value.EmptySequence;
9 import net.sf.saxon.value.StringValue;
10
11 import java.io.Serializable JavaDoc;
12 import java.util.Comparator JavaDoc;
13
14 /**
15 * A SortKeyDefinition defines one component of a sort key. <BR>
16 *
17 * Note that most attributes defining the sort key can be attribute value templates,
18 * and can therefore vary from one invocation to another. We hold them as expressions. As
19 * soon as they are all known (which in general is only at run-time), the SortKeyDefinition
20 * is replaced by a FixedSortKeyDefinition in which all these values are fixed.
21 */

22
23 // TODO: optimise also for the case where the attributes depend only on global variables
24
// or parameters, in which case the same Comparator can be used for the duration of a
25
// transformation.
26

27 // TODO: at present the SortKeyDefinition is evaluated to obtain a Comparator, which can
28
// be used to compare two sort keys. It would be more efficient to use a Collator to
29
// obtain collation keys for all the items to be sorted, as these can be compared more
30
// efficiently.
31

32
33 public class SortKeyDefinition implements Serializable JavaDoc {
34
35     private static StringValue defaultOrder = new StringValue("ascending");
36     private static StringValue defaultCaseOrder = new StringValue("#default");
37     private static StringValue defaultLanguage = StringValue.EMPTY_STRING;
38
39     protected Expression sortKey;
40     protected Expression order = defaultOrder;
41     protected Expression dataTypeExpression = EmptySequence.getInstance();
42                                         // used when the type is not known till run-time
43
protected Expression caseOrder = defaultCaseOrder;
44     protected Expression language = defaultLanguage;
45     protected Expression collationName = null;
46     protected Comparator JavaDoc collation; // usually a Collator, but not always
47
protected boolean emptyFirst = true;
48                             // used only in XQuery at present
49
protected Container parentExpression;
50
51     // Note, the "collation" defines the collating sequence for the sort key. The
52
// "comparer" is what is actually used to do comparisons, after taking into account
53
// ascending/descending, caseOrder, etc.
54

55     // The comparer is transient because a RuleBasedCollator is not serializable. This means that
56
// when a stylesheet is compiled, the comparer is discarded, which means a new comparer will be
57
// constructed for each sort at run-time.
58

59     public void setParentExpression(Container container) {
60         parentExpression = container;
61     }
62
63     public Container getParentExpression() {
64         return parentExpression;
65     }
66
67     /**
68     * Set the expression used as the sort key
69     */

70
71     public void setSortKey(Expression exp) {
72         sortKey = exp;
73     }
74
75     /**
76     * Get the expression used as the sort key
77     */

78
79     public Expression getSortKey() {
80         return sortKey;
81     }
82
83
84     /**
85     * Set the order. This is supplied as an expression which must evaluate to "ascending"
86     * or "descending". If the order is fixed, supply e.g. new StringValue("ascending").
87     * Default is "ascending".
88     */

89
90     public void setOrder(Expression exp) {
91         order = exp;
92     }
93
94     public Expression getOrder() {
95         return order;
96     }
97
98     /**
99     * Set the data type. This is supplied as an expression which must evaluate to "text",
100     * "number", or a QName. If the data type is fixed, the valus should be supplied using
101     * setDataType() and not via this method.
102     */

103
104     public void setDataTypeExpression(Expression exp) {
105         dataTypeExpression = exp;
106     }
107
108     public Expression getDataTypeExpression() {
109         return dataTypeExpression;
110     }
111     /**
112     * Set the case order. This is supplied as an expression which must evaluate to "upper-first"
113     * or "lower-first" or "#default". If the order is fixed, supply e.g. new StringValue("lower-first").
114     * Default is "#default".
115     */

116
117     public void setCaseOrder(Expression exp) {
118         caseOrder = exp;
119     }
120
121     public Expression getCaseOrder() {
122         return caseOrder;
123     }
124
125     /**
126     * Set the language. This is supplied as an expression which evaluates to the language name.
127     * If the order is fixed, supply e.g. new StringValue("de").
128     */

129
130     public void setLanguage(Expression exp) {
131         language = exp;
132     }
133
134     public Expression getLanguage() {
135         return language;
136     }
137
138     /**
139     * Set the collation.
140     */

141
142     public void setCollationName(Expression collationName) {
143         this.collationName = collationName;
144     }
145
146     public Expression getCollationName() {
147         return collationName;
148     }
149
150     public void setCollation(Comparator JavaDoc collation) {
151         this.collation = collation;
152     }
153
154     public Comparator JavaDoc getCollation() {
155         return collation;
156     }
157
158     /**
159      * Set whether empty sequence comes before other values or after them
160      * @param emptyFirst true if () is considered lower than any other value
161      */

162
163     public void setEmptyFirst(boolean emptyFirst) {
164         this.emptyFirst = emptyFirst;
165     }
166
167     public boolean getEmptyFirst() {
168         return emptyFirst;
169     }
170
171     public SortKeyDefinition simplify(Executable exec) throws XPathException {
172
173         if (order instanceof StringValue &&
174                 (dataTypeExpression == null || dataTypeExpression instanceof StringValue) &&
175                 caseOrder instanceof StringValue &&
176                 language instanceof StringValue &&
177                 collation != null) {
178
179             FixedSortKeyDefinition fskd = new FixedSortKeyDefinition();
180             fskd.setSortKey(sortKey);
181             fskd.setOrder(order);
182             fskd.setDataTypeExpression(dataTypeExpression);
183             fskd.setCaseOrder(caseOrder);
184             fskd.setLanguage(language);
185             fskd.setEmptyFirst(emptyFirst);
186             fskd.collation = collation;
187             fskd.bindComparer(exec.getConfiguration());
188             return fskd;
189         } else {
190             return this;
191         }
192     }
193
194     /**
195      * Evaluate any aspects of the sort definition that were specified as AVTs, for example
196      * ascending/descending, language, case-order, data-type. This is done at the start of each
197      * sort. A FixedSortKeyDefinition is a SortKeyDefinition in which these properties are all
198      * known values.
199     */

200
201     public FixedSortKeyDefinition reduce(XPathContext context) throws XPathException {
202
203         FixedSortKeyDefinition sknew = new FixedSortKeyDefinition();
204
205         Expression sortKey2 = sortKey;
206
207         sknew.setSortKey(sortKey2);
208         sknew.setOrder((StringValue)order.evaluateItem(context));
209         sknew.setDataTypeExpression((StringValue)dataTypeExpression.evaluateItem(context));
210         sknew.setCaseOrder((StringValue)caseOrder.evaluateItem(context));
211         sknew.setLanguage((StringValue)language.evaluateItem(context));
212         if (collation == null && collationName != null) {
213             String JavaDoc cname = collationName.evaluateItem(context).getStringValue();
214             Comparator JavaDoc comp = context.getCollation(cname);
215             if (comp == null) {
216                 throw new DynamicError("Collation " + cname + " is not recognized");
217             }
218             sknew.setCollation(comp);
219         }
220         if (collation != null) {
221             sknew.setCollation(collation);
222         }
223         sknew.setEmptyFirst(emptyFirst);
224         sknew.bindComparer(context);
225         return sknew;
226     }
227
228
229 }
230
231
232 //
233
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
234
// you may not use this file except in compliance with the License. You may obtain a copy of the
235
// License at http://www.mozilla.org/MPL/
236
//
237
// Software distributed under the License is distributed on an "AS IS" basis,
238
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
239
// See the License for the specific language governing rights and limitations under the License.
240
//
241
// The Original Code is: all this file.
242
//
243
// The Initial Developer of the Original Code is Michael H. Kay.
244
//
245
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
246
//
247
// Contributor(s): none.
248
//
249
Popular Tags