KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > icl > saxon > sort > SortKeyDefinition


1 package com.icl.saxon.sort;
2 import com.icl.saxon.*;
3 import com.icl.saxon.om.Name;
4
5 import com.icl.saxon.expr.*;
6 import javax.xml.transform.TransformerException JavaDoc;
7
8 /**
9 * A SortKeyDefinition defines one component of a sort key. <BR>
10 *
11 * Note that most attributes defining the sort key can be attribute value templates,
12 * and can therefore vary from one invocation to another. We hold them as expressions,
13 * but optimise for the case where the attributes are all fixed strings: in this case
14 * we can use the same Comparer object each time.
15 *
16 */

17
18
19 public class SortKeyDefinition {
20
21     private Expression sortKey;
22     private Expression order;
23     private Expression dataType;
24     private Expression caseOrder;
25     private Expression language;
26     private StaticContext staticContext;
27
28     private Comparer comparer = null;
29
30     /**
31     * Set the expression used as the sort key
32     */

33
34     public void setSortKey(Expression exp) {
35         sortKey = exp;
36     }
37
38     /**
39     * Set the order. This is supplied as an expression which must evaluate to "ascending"
40     * or "descending". If the order is fixed, supply e.g. new StringValue("ascending").
41     * Default is "ascending".
42     */

43
44     public void setOrder(Expression exp) {
45         order = exp;
46     }
47
48     /**
49     * Set the data type. This is supplied as an expression which must evaluate to "text",
50     * "number", or a QName. If the data type is fixed, supply e.g. new StringValue("text").
51     * Default is "text".
52     */

53
54     public void setDataType(Expression exp) {
55         dataType = exp;
56     }
57
58     /**
59     * Set the case order. This is supplied as an expression which must evaluate to "upper-first"
60     * or "lower-first" or "#default". If the order is fixed, supply e.g. new StringValue("lower-first").
61     * Default is "#default".
62     */

63
64     public void setCaseOrder(Expression exp) {
65         caseOrder = exp;
66     }
67
68     /**
69     * Set the language. This is supplied as an expression which evaluate to the language name.
70     * If the order is fixed, supply e.g. new StringValue("de").
71     * Default is "en".
72     */

73
74     public void setLanguage(Expression exp) {
75         language = exp;
76     }
77
78     /**
79     * Set the static context. This is used only for resolving any QName supplied in the data-type
80     * property.
81     */

82
83     public void setStaticContext(StaticContext sc) {
84         staticContext = sc;
85     }
86
87
88     public Expression getSortKey() {
89         return sortKey;
90     }
91
92     public Expression getOrder() {
93         return (order==null ? new StringValue("ascending") : order);
94     }
95
96     public Expression getDataType() {
97         return (dataType==null ? new StringValue("text") : dataType);
98     }
99     
100     public Expression getCaseOrder() {
101         return (caseOrder==null ? new StringValue("#default") : caseOrder);
102     }
103
104     public Expression getLanguage() {
105         return (language==null ? new StringValue("en") : language);
106     }
107
108     /**
109     * If possible, use the same comparer every time
110     */

111
112     public void bindComparer() throws XPathException {
113         if ((dataType instanceof StringValue) &&
114                 (order instanceof StringValue) &&
115                 (caseOrder instanceof StringValue) &&
116                 (language instanceof StringValue)) {
117             comparer = makeComparer(null);
118         }
119     }
120
121     /**
122     * Get a Comparer which can be used to compare two values according to this sort key.
123     */

124
125     public Comparer getComparer(Context context) throws XPathException {
126         if (comparer==null) {
127             return makeComparer(context);
128         } else {
129             return comparer;
130             // note, we can't save it for later use, because the context might be different next time
131
}
132     }
133
134     /**
135     * Create a Comparer which can be used to compare two values according to this sort key.
136     */

137
138     private Comparer makeComparer(Context context) throws XPathException {
139
140         Comparer comp;
141         boolean isAscending;
142
143         String JavaDoc orderAtt;
144         if (order==null) {
145             orderAtt="ascending";
146         } else {
147             orderAtt = order.evaluateAsString(context);
148         }
149         
150         if (orderAtt.equals("ascending")) {
151             isAscending = true;
152         } else if (orderAtt.equals("descending")) {
153             isAscending = false;
154         } else {
155             throw new XPathException("order must be ascending or descending");
156         }
157
158         String JavaDoc dataTypeURI;
159         String JavaDoc dataTypeLocalName;
160
161         String JavaDoc dataTypeAtt;
162         if (dataType==null) {
163             dataTypeAtt = "text";
164         } else {
165             dataTypeAtt = dataType.evaluateAsString(context);
166         }
167         
168         if (dataTypeAtt.equals("text")) {
169             dataTypeURI = null;
170             dataTypeLocalName = null;
171         } else if (dataTypeAtt.equals("number")) {
172             dataTypeURI = null;
173             dataTypeLocalName = null;
174         } else {
175             String JavaDoc prefix = Name.getPrefix(dataTypeAtt);
176             if (prefix.equals("")) {
177                 throw new XPathException("data-type must be text, number, or a prefixed name");
178             }
179             
180             dataTypeURI = staticContext.getURIForPrefix(prefix);
181             dataTypeLocalName = Name.getLocalName(dataTypeAtt);
182         }
183
184         int caseOrderValue;
185         String JavaDoc caseOrderAtt;
186         if (caseOrder==null) {
187             caseOrderAtt = "#default";
188         } else {
189             caseOrderAtt = caseOrder.evaluateAsString(context);
190         }
191         
192         if (caseOrderAtt.equals("#default")) {
193             caseOrderValue = TextComparer.DEFAULT_CASE_ORDER;
194         } else if (caseOrderAtt.equals("lower-first")) {
195             caseOrderValue = TextComparer.LOWERCASE_FIRST;
196         } else if (caseOrderAtt.equals("upper-first")) {
197             caseOrderValue = TextComparer.UPPERCASE_FIRST;
198         } else {
199             throw new XPathException("case-order must be lower-first or upper-first");
200         }
201
202
203
204         if (dataTypeAtt.equals("text")) {
205             if (language==null) {
206                 comp = new StringComparer();
207             } else {
208                 String JavaDoc langValue = language.evaluateAsString(context);
209                 String JavaDoc userClassName = "com.icl.saxon.sort.Compare_";
210                 for (int i=0; i<langValue.length(); i++) {
211                     if (Character.isLetter(langValue.charAt(i))) {
212                         userClassName += langValue.charAt(i);
213                     }
214                 }
215                 try {
216                     comp = loadComparer(userClassName);
217                 } catch (Exception JavaDoc err) {
218                     //System.err.println("Warning: no comparer " + userClassName + " found; using default");
219
comp = new Compare_en();
220                 }
221             }
222             
223         } else if (dataTypeAtt.equals("number")) {
224             comp = new DoubleComparer();
225         } else {
226             try {
227                 comp = loadComparer(dataTypeLocalName);
228             } catch (Exception JavaDoc err) {
229                 System.err.println("Warning: no comparer " + dataTypeLocalName + " found; using default");
230                 comp = new StringComparer();
231             }
232         }
233
234         comp = comp.setDataType(dataTypeURI, dataTypeLocalName);
235         comp = comp.setOrder(isAscending);
236         if (comp instanceof TextComparer) {
237             comp = ((TextComparer)comp).setCaseOrder(caseOrderValue);
238         }
239
240
241         return comp;
242     }
243
244     /**
245     * Load a named Comparer class and check it is OK.
246     */

247
248     private static TextComparer loadComparer (String JavaDoc className) throws XPathException
249     {
250         try {
251             return (TextComparer)Loader.getInstance(className);
252         } catch (ClassCastException JavaDoc e) {
253             throw new XPathException("Failed to load TextComparer " + className +
254                             ": it does not implement the TextComparer interface");
255         } catch (TransformerException JavaDoc err) {
256             if (err instanceof XPathException) {
257                 throw (XPathException)err;
258             } else {
259                 throw new XPathException(err);
260             }
261         }
262     }
263
264 }
265     
266
267 //
268
// The contents of this file are subject to the Mozilla Public License Version 1.0 (the "License");
269
// you may not use this file except in compliance with the License. You may obtain a copy of the
270
// License at http://www.mozilla.org/MPL/
271
//
272
// Software distributed under the License is distributed on an "AS IS" basis,
273
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
274
// See the License for the specific language governing rights and limitations under the License.
275
//
276
// The Original Code is: all this file.
277
//
278
// The Initial Developer of the Original Code is
279
// Michael Kay of International Computers Limited (mhkay@iclway.co.uk).
280
//
281
// Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved.
282
//
283
// Contributor(s): none.
284
//
285
Popular Tags