KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > query > Ordering


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.query;
21
22 import java.io.PrintWriter JavaDoc;
23 import java.io.Serializable JavaDoc;
24 import java.io.StringWriter JavaDoc;
25 import java.util.Collections JavaDoc;
26 import java.util.Comparator JavaDoc;
27 import java.util.List JavaDoc;
28
29 import org.apache.commons.collections.ComparatorUtils;
30 import org.apache.cayenne.exp.Expression;
31 import org.apache.cayenne.util.ConversionUtil;
32 import org.apache.cayenne.util.Util;
33 import org.apache.cayenne.util.XMLEncoder;
34 import org.apache.cayenne.util.XMLSerializable;
35
36 /**
37  * Defines object sorting criteria, used either for in-memory sorting of object lists or
38  * as a specification for building <em>ORDER BY</em> clause of a SelectQuery query. Note
39  * that in case of in-memory sorting, Ordering can be used with any JavaBeans, not just
40  * DataObjects.
41  *
42  * @author Andrus Adamchik
43  * @author Craig Miskell
44  */

45 public class Ordering implements Comparator JavaDoc, Serializable JavaDoc, XMLSerializable {
46
47     /**
48      * Symbolic representation of ascending ordering criterion.
49      */

50     public static final boolean ASC = true;
51
52     /**
53      * Symbolic representation of descending ordering criterion.
54      */

55     public static final boolean DESC = false;
56
57     protected String JavaDoc sortSpecString;
58     protected transient Expression sortSpec;
59     protected boolean ascending;
60     protected boolean caseInsensitive;
61
62     /**
63      * Orders a given list of objects, using a List of Orderings applied according the
64      * default iteration order of the Orderings list. I.e. each Ordering with lower index
65      * is more significant than any other Ordering with higer index. List being ordered is
66      * modified in place.
67      */

68     public static void orderList(List JavaDoc objects, List JavaDoc orderings) {
69         Collections.sort(objects, ComparatorUtils.chainedComparator(orderings));
70     }
71
72     public Ordering() {
73     }
74
75     public Ordering(String JavaDoc sortPathSpec, boolean ascending) {
76         this(sortPathSpec, ascending, false);
77     }
78
79     public Ordering(String JavaDoc sortPathSpec, boolean ascending, boolean caseInsensitive) {
80         setSortSpecString(sortPathSpec);
81         this.ascending = ascending;
82         this.caseInsensitive = caseInsensitive;
83     }
84
85     public Ordering(Expression sortExpression, boolean ascending) {
86         this(sortExpression, ascending, false);
87     }
88
89     public Ordering(Expression sortExpression, boolean ascending, boolean caseInsensitive) {
90         setSortSpec(sortExpression);
91         this.ascending = ascending;
92         this.caseInsensitive = caseInsensitive;
93     }
94
95     /**
96      * Sets sortSpec to be an expression represented by string argument.
97      *
98      * @since 1.1
99      */

100     public void setSortSpecString(String JavaDoc sortSpecString) {
101         if (!Util.nullSafeEquals(this.sortSpecString, sortSpecString)) {
102             this.sortSpecString = sortSpecString;
103             this.sortSpec = null;
104         }
105     }
106
107     /**
108      * Returns sortSpec string representation.
109      *
110      * @since 1.1
111      */

112     public String JavaDoc getSortSpecString() {
113         return sortSpecString;
114     }
115
116     /** Returns true if sorting is done in ascending order. */
117     public boolean isAscending() {
118         return ascending;
119     }
120
121     /** Sets <code>ascending</code> property of this Ordering. */
122     public void setAscending(boolean ascending) {
123         this.ascending = ascending;
124     }
125
126     /** Returns true if the sorting is case insensitive */
127     public boolean isCaseInsensitive() {
128         return caseInsensitive;
129     }
130
131     /** Sets <code>caseInsensitive</code> property of this Ordering. */
132     public void setCaseInsensitive(boolean caseInsensitive) {
133         this.caseInsensitive = caseInsensitive;
134     }
135
136     /**
137      * Returns the expression defining a ordering Java Bean property.
138      */

139     public Expression getSortSpec() {
140         if (sortSpecString == null) {
141             return null;
142         }
143
144         // compile on demand
145
if (sortSpec == null) {
146             sortSpec = Expression.fromString(sortSpecString);
147         }
148
149         return sortSpec;
150     }
151
152     /**
153      * Sets the expression defining a ordering Java Bean property.
154      */

155     public void setSortSpec(Expression sortSpec) {
156         this.sortSpec = sortSpec;
157         this.sortSpecString = (sortSpec != null) ? sortSpec.toString() : null;
158     }
159
160     /**
161      * Orders the given list of objects according to the ordering that this object
162      * specifies. List is modified in-place.
163      *
164      * @param objects a List of objects to be sorted
165      */

166     public void orderList(List JavaDoc objects) {
167         Collections.sort(objects, this);
168     }
169
170     /**
171      * Comparable interface implementation. Can compare two Java Beans based on the stored
172      * expression.
173      */

174     public int compare(Object JavaDoc o1, Object JavaDoc o2) {
175         Expression exp = getSortSpec();
176         Object JavaDoc value1 = exp.evaluate(o1);
177         Object JavaDoc value2 = exp.evaluate(o2);
178
179         // nulls first policy... maybe make this configurable as some DB do
180
if (value1 == null) {
181             return (value2 == null) ? 0 : -1;
182         }
183         else if (value2 == null) {
184             return 1;
185         }
186
187         if (this.caseInsensitive) {
188             // TODO: to upper case should probably be defined as a separate expression
189
// type
190
value1 = ConversionUtil.toUpperCase(value1);
191             value2 = ConversionUtil.toUpperCase(value2);
192         }
193
194         int compareResult = ConversionUtil.toComparable(value1).compareTo(
195                 ConversionUtil.toComparable(value2));
196         return (ascending) ? compareResult : -compareResult;
197     }
198
199     /**
200      * Encodes itself as a query ordering.
201      *
202      * @since 1.1
203      */

204     public void encodeAsXML(XMLEncoder encoder) {
205         encoder.print("<ordering");
206
207         if (!ascending) {
208             encoder.print(" descending=\"true\"");
209         }
210
211         if (caseInsensitive) {
212             encoder.print(" ignore-case=\"true\"");
213         }
214
215         encoder.print(">");
216         if (getSortSpec() != null) {
217             getSortSpec().encodeAsXML(encoder);
218         }
219         encoder.println("</ordering>");
220     }
221
222     public String JavaDoc toString() {
223         StringWriter JavaDoc buffer = new StringWriter JavaDoc();
224         PrintWriter JavaDoc pw = new PrintWriter JavaDoc(buffer);
225         XMLEncoder encoder = new XMLEncoder(pw);
226         encodeAsXML(encoder);
227         pw.close();
228         buffer.flush();
229         return buffer.toString();
230     }
231 }
232
Popular Tags