Revision eec2d79d
Added by Andreas Müller over 8 years ago
cdmlib-persistence/src/main/java/eu/etaxonomy/cdm/persistence/query/OrderHint.java | ||
---|---|---|
1 |
/** |
|
2 |
* Copyright (C) 2009 EDIT |
|
3 |
* European Distributed Institute of Taxonomy |
|
4 |
* http://www.e-taxonomy.eu |
|
5 |
* |
|
6 |
* The contents of this file are subject to the Mozilla Public License Version 1.1 |
|
7 |
* See LICENSE.TXT at the top of this package for the full license terms. |
|
8 |
*/ |
|
9 |
|
|
10 |
package eu.etaxonomy.cdm.persistence.query; |
|
11 |
|
|
12 |
import java.util.Arrays; |
|
13 |
import java.util.List; |
|
14 |
import java.util.Map; |
|
15 |
|
|
16 |
import org.apache.log4j.Logger; |
|
17 |
import org.apache.lucene.search.SortField; |
|
18 |
import org.hibernate.Criteria; |
|
19 |
import org.hibernate.criterion.Order; |
|
20 |
import org.hibernate.envers.query.AuditEntity; |
|
21 |
import org.hibernate.envers.query.AuditQuery; |
|
22 |
|
|
23 |
import eu.etaxonomy.cdm.hibernate.search.NomenclaturalSortOrderBrigde; |
|
24 |
import eu.etaxonomy.cdm.model.common.CdmBase; |
|
25 |
import eu.etaxonomy.cdm.model.common.IdentifiableEntity; |
|
26 |
import eu.etaxonomy.cdm.persistence.dao.common.OperationNotSupportedInPriorViewException; |
|
27 |
|
|
28 |
public class OrderHint { |
|
29 |
|
|
30 |
public enum SortOrder { |
|
31 |
|
|
32 |
/** |
|
33 |
* items are sorted in increasing |
|
34 |
* order. |
|
35 |
*/ |
|
36 |
ASCENDING("asc"), |
|
37 |
/** |
|
38 |
* items are sorted in decreasing |
|
39 |
* order. |
|
40 |
*/ |
|
41 |
DESCENDING("desc"); |
|
42 |
|
|
43 |
private String hql; |
|
44 |
|
|
45 |
private SortOrder(String hqlStr){ |
|
46 |
hql = hqlStr; |
|
47 |
} |
|
48 |
|
|
49 |
public String toHql(){ |
|
50 |
return hql; |
|
51 |
} |
|
52 |
} |
|
53 |
|
|
54 |
public static final Logger logger = Logger.getLogger(OrderHint.class); |
|
55 |
|
|
56 |
private final String propertyName; |
|
57 |
|
|
58 |
private final SortOrder sortOrder; |
|
59 |
|
|
60 |
public final String LUCENE_SCORE = "LUCENE_SCORE"; |
|
61 |
|
|
62 |
public static final List<OrderHint> ORDER_BY_ID = Arrays.asList(new OrderHint[]{new OrderHint("id", SortOrder.ASCENDING)}); |
|
63 |
|
|
64 |
public static final List<OrderHint> ORDER_BY_TITLE_CACHE = Arrays.asList(new OrderHint[]{new OrderHint("titleCache", SortOrder.ASCENDING)}); |
|
65 |
|
|
66 |
public static final List<OrderHint> NOMENCLATURAL_SORT_ORDER = Arrays.asList(new OrderHint[]{new OrderHint(NomenclaturalSortOrderBrigde.NAME_SORT_FIELD_NAME, SortOrder.ASCENDING)}); |
|
67 |
|
|
68 |
/** |
|
69 |
* @param clazz |
|
70 |
* @return "by titleCache" for all IdentifiableEntitys otherwise "by id" |
|
71 |
*/ |
|
72 |
public static List<OrderHint> defaultOrderHintsFor(Class<? extends CdmBase> clazz) { |
|
73 |
if (clazz.isAssignableFrom(IdentifiableEntity.class)) { |
|
74 |
return ORDER_BY_TITLE_CACHE; |
|
75 |
} else { |
|
76 |
return ORDER_BY_ID; |
|
77 |
} |
|
78 |
} |
|
79 |
|
|
80 |
public OrderHint(String fieldName, SortOrder sortOrder) { |
|
81 |
super(); |
|
82 |
this.propertyName = fieldName; |
|
83 |
this.sortOrder = sortOrder; |
|
84 |
} |
|
85 |
|
|
86 |
/** |
|
87 |
* The property of a bean |
|
88 |
* @return |
|
89 |
*/ |
|
90 |
public String getPropertyName() { |
|
91 |
return propertyName; |
|
92 |
} |
|
93 |
|
|
94 |
/** |
|
95 |
* possible sort orders are {@link SortOrder.ASCENDING} or {@link SortOrder.DESCENDING} |
|
96 |
* @return |
|
97 |
*/ |
|
98 |
public SortOrder getSortOrder() { |
|
99 |
return sortOrder; |
|
100 |
} |
|
101 |
|
|
102 |
public boolean isAscending(){ |
|
103 |
return sortOrder.equals(SortOrder.ASCENDING); |
|
104 |
} |
|
105 |
|
|
106 |
/** |
|
107 |
* FIXME document this |
|
108 |
* |
|
109 |
* @param criteria |
|
110 |
* @param criteriaMap |
|
111 |
*/ |
|
112 |
public void add(Criteria criteria, Map<String, Criteria> criteriaMap) { |
|
113 |
if(getPropertyName().indexOf(".") != -1) { |
|
114 |
/** |
|
115 |
* Here we have to work a bit of magic as currently hibernate will |
|
116 |
* throw an error if we attempt to join the same association twice. |
|
117 |
* |
|
118 |
* http://opensource.atlassian.com/projects/hibernate/browse/HHH-879 |
|
119 |
*/ |
|
120 |
Order order; |
|
121 |
|
|
122 |
String[] assocObjs = getPropertyName().split("\\."); |
|
123 |
String path = ""; |
|
124 |
Criteria c = criteria; |
|
125 |
for(int i = 0; i < assocObjs.length - 1; i++) { |
|
126 |
path = path + assocObjs[i]; |
|
127 |
if(criteriaMap.get(path) == null) { |
|
128 |
c = c.createCriteria(assocObjs[i]); |
|
129 |
criteriaMap.put(path, c); |
|
130 |
} else { |
|
131 |
c = criteriaMap.get(path); |
|
132 |
} |
|
133 |
path = path + '.'; |
|
134 |
} |
|
135 |
String propname = assocObjs[assocObjs.length - 1]; |
|
136 |
if(isAscending()){ |
|
137 |
c.addOrder(Order.asc(propname)); |
|
138 |
} else { |
|
139 |
c.addOrder(Order.desc(propname)); |
|
140 |
} |
|
141 |
} else { |
|
142 |
if(isAscending()){ |
|
143 |
criteria.addOrder(Order.asc(getPropertyName())); |
|
144 |
} else { |
|
145 |
criteria.addOrder(Order.desc(getPropertyName())); |
|
146 |
} |
|
147 |
} |
|
148 |
} |
|
149 |
|
|
150 |
/** |
|
151 |
* FIXME document this |
|
152 |
* |
|
153 |
* @param query |
|
154 |
*/ |
|
155 |
public void add(AuditQuery query) { |
|
156 |
|
|
157 |
if(getPropertyName().indexOf('.', 0) >= 0){ |
|
158 |
throw new OperationNotSupportedInPriorViewException("Sorting by related properties is not supported in the history view"); |
|
159 |
} else { |
|
160 |
if(isAscending()){ |
|
161 |
query.addOrder(AuditEntity.property(getPropertyName()).asc()); |
|
162 |
} else { |
|
163 |
query.addOrder(AuditEntity.property(getPropertyName()).desc()); |
|
164 |
} |
|
165 |
} |
|
166 |
} |
|
167 |
|
|
168 |
/** |
|
169 |
* Returns a hql order by clause element which can directly be used in hql queries. |
|
170 |
* |
|
171 |
* e.g.: "titleCache ASC" |
|
172 |
* |
|
173 |
* @return an hql order by clause element |
|
174 |
*/ |
|
175 |
public String toHql(){ |
|
176 |
if(propertyName.equals(LUCENE_SCORE)){ |
|
177 |
logger.error("LUCENE_SCORE not allowed in hql query"); |
|
178 |
} |
|
179 |
return propertyName + " " + sortOrder.toHql(); |
|
180 |
} |
|
181 |
|
|
182 |
/** |
|
183 |
* @return a Lucene {@link SortField} for the Lucene field type <code>Sting</code> |
|
184 |
*/ |
|
185 |
public SortField toSortField() { |
|
186 |
if(propertyName.equals(LUCENE_SCORE)){ |
|
187 |
return SortField.FIELD_SCORE; |
|
188 |
} |
|
189 |
return new SortField(propertyName, SortField.STRING, sortOrder.equals(SortOrder.DESCENDING)); |
|
190 |
} |
|
191 |
|
|
192 |
@Override |
|
193 |
public boolean equals(Object obj) { |
|
194 |
if (obj == this){ |
|
195 |
return true; |
|
196 |
} |
|
197 |
if (obj == null){ |
|
198 |
return false; |
|
199 |
} |
|
200 |
if (!OrderHint.class.isAssignableFrom(obj.getClass())){ |
|
201 |
return false; |
|
202 |
} |
|
203 |
OrderHint orderHint= (OrderHint)obj; |
|
204 |
boolean propertyNameEqual = orderHint.getPropertyName().equals(this.getPropertyName()); |
|
205 |
boolean sortOrderEqual = orderHint.getSortOrder().equals(this.getSortOrder()); |
|
206 |
if (! propertyNameEqual || !sortOrderEqual){ |
|
207 |
return false; |
|
208 |
} |
|
209 |
return true; |
|
210 |
} |
|
211 |
|
|
212 |
@Override |
|
213 |
public int hashCode() { |
|
214 |
int hashCode = 7; |
|
215 |
hashCode = 29 * hashCode + this.getPropertyName().hashCode() * this.getSortOrder().hashCode(); |
|
216 |
return hashCode; |
|
217 |
} |
|
218 |
} |
|
1 |
/** |
|
2 |
* Copyright (C) 2009 EDIT |
|
3 |
* European Distributed Institute of Taxonomy |
|
4 |
* http://www.e-taxonomy.eu |
|
5 |
* |
|
6 |
* The contents of this file are subject to the Mozilla Public License Version 1.1 |
|
7 |
* See LICENSE.TXT at the top of this package for the full license terms. |
|
8 |
*/ |
|
9 |
|
|
10 |
package eu.etaxonomy.cdm.persistence.query; |
|
11 |
|
|
12 |
import java.util.Arrays; |
|
13 |
import java.util.List; |
|
14 |
import java.util.Map; |
|
15 |
|
|
16 |
import org.apache.log4j.Logger; |
|
17 |
import org.apache.lucene.search.SortField; |
|
18 |
import org.hibernate.Criteria; |
|
19 |
import org.hibernate.criterion.Order; |
|
20 |
import org.hibernate.envers.query.AuditEntity; |
|
21 |
import org.hibernate.envers.query.AuditQuery; |
|
22 |
|
|
23 |
import eu.etaxonomy.cdm.hibernate.search.NomenclaturalSortOrderBrigde; |
|
24 |
import eu.etaxonomy.cdm.model.common.CdmBase; |
|
25 |
import eu.etaxonomy.cdm.model.common.IdentifiableEntity; |
|
26 |
import eu.etaxonomy.cdm.persistence.dao.common.OperationNotSupportedInPriorViewException; |
|
27 |
|
|
28 |
public class OrderHint { |
|
29 |
|
|
30 |
public enum SortOrder { |
|
31 |
|
|
32 |
/** |
|
33 |
* items are sorted in increasing |
|
34 |
* order. |
|
35 |
*/ |
|
36 |
ASCENDING("asc"), |
|
37 |
/** |
|
38 |
* items are sorted in decreasing |
|
39 |
* order. |
|
40 |
*/ |
|
41 |
DESCENDING("desc"); |
|
42 |
|
|
43 |
private String hql; |
|
44 |
|
|
45 |
private SortOrder(String hqlStr){ |
|
46 |
hql = hqlStr; |
|
47 |
} |
|
48 |
|
|
49 |
public String toHql(){ |
|
50 |
return hql; |
|
51 |
} |
|
52 |
} |
|
53 |
|
|
54 |
public static final Logger logger = Logger.getLogger(OrderHint.class); |
|
55 |
|
|
56 |
private final String propertyName; |
|
57 |
|
|
58 |
private final SortOrder sortOrder; |
|
59 |
|
|
60 |
public final String LUCENE_SCORE = "LUCENE_SCORE"; |
|
61 |
|
|
62 |
public static final List<OrderHint> ORDER_BY_ID = Arrays.asList(new OrderHint[]{new OrderHint("id", SortOrder.ASCENDING)}); |
|
63 |
|
|
64 |
public static final List<OrderHint> ORDER_BY_TITLE_CACHE = Arrays.asList(new OrderHint[]{new OrderHint("titleCache", SortOrder.ASCENDING)}); |
|
65 |
|
|
66 |
public static final List<OrderHint> NOMENCLATURAL_SORT_ORDER = Arrays.asList(new OrderHint[]{new OrderHint(NomenclaturalSortOrderBrigde.NAME_SORT_FIELD_NAME, SortOrder.ASCENDING)}); |
|
67 |
|
|
68 |
/** |
|
69 |
* @param clazz |
|
70 |
* @return "by titleCache" for all IdentifiableEntitys otherwise "by id" |
|
71 |
*/ |
|
72 |
public static List<OrderHint> defaultOrderHintsFor(Class<? extends CdmBase> clazz) { |
|
73 |
if (clazz.isAssignableFrom(IdentifiableEntity.class)) { |
|
74 |
return ORDER_BY_TITLE_CACHE; |
|
75 |
} else { |
|
76 |
return ORDER_BY_ID; |
|
77 |
} |
|
78 |
} |
|
79 |
|
|
80 |
public OrderHint(String fieldName, SortOrder sortOrder) { |
|
81 |
super(); |
|
82 |
this.propertyName = fieldName; |
|
83 |
this.sortOrder = sortOrder; |
|
84 |
} |
|
85 |
|
|
86 |
/** |
|
87 |
* The property of a bean |
|
88 |
* @return |
|
89 |
*/ |
|
90 |
public String getPropertyName() { |
|
91 |
return propertyName; |
|
92 |
} |
|
93 |
|
|
94 |
/** |
|
95 |
* possible sort orders are {@link SortOrder.ASCENDING} or {@link SortOrder.DESCENDING} |
|
96 |
* @return |
|
97 |
*/ |
|
98 |
public SortOrder getSortOrder() { |
|
99 |
return sortOrder; |
|
100 |
} |
|
101 |
|
|
102 |
public boolean isAscending(){ |
|
103 |
return sortOrder.equals(SortOrder.ASCENDING); |
|
104 |
} |
|
105 |
|
|
106 |
/** |
|
107 |
* FIXME document this |
|
108 |
* |
|
109 |
* @param criteria |
|
110 |
* @param criteriaMap |
|
111 |
*/ |
|
112 |
public void add(Criteria criteria, Map<String, Criteria> criteriaMap) { |
|
113 |
if(getPropertyName().indexOf(".") != -1) { |
|
114 |
/** |
|
115 |
* Here we have to work a bit of magic as currently hibernate will |
|
116 |
* throw an error if we attempt to join the same association twice. |
|
117 |
* |
|
118 |
* http://opensource.atlassian.com/projects/hibernate/browse/HHH-879 |
|
119 |
*/ |
|
120 |
Order order; |
|
121 |
|
|
122 |
String[] assocObjs = getPropertyName().split("\\."); |
|
123 |
String path = ""; |
|
124 |
Criteria c = criteria; |
|
125 |
for(int i = 0; i < assocObjs.length - 1; i++) { |
|
126 |
path = path + assocObjs[i]; |
|
127 |
if(criteriaMap.get(path) == null) { |
|
128 |
c = c.createCriteria(assocObjs[i]); |
|
129 |
criteriaMap.put(path, c); |
|
130 |
} else { |
|
131 |
c = criteriaMap.get(path); |
|
132 |
} |
|
133 |
path = path + '.'; |
|
134 |
} |
|
135 |
String propname = assocObjs[assocObjs.length - 1]; |
|
136 |
if(isAscending()){ |
|
137 |
c.addOrder(Order.asc(propname)); |
|
138 |
} else { |
|
139 |
c.addOrder(Order.desc(propname)); |
|
140 |
} |
|
141 |
} else { |
|
142 |
if(isAscending()){ |
|
143 |
criteria.addOrder(Order.asc(getPropertyName())); |
|
144 |
} else { |
|
145 |
criteria.addOrder(Order.desc(getPropertyName())); |
|
146 |
} |
|
147 |
} |
|
148 |
} |
|
149 |
|
|
150 |
/** |
|
151 |
* FIXME document this |
|
152 |
* |
|
153 |
* @param query |
|
154 |
*/ |
|
155 |
public void add(AuditQuery query) { |
|
156 |
|
|
157 |
if(getPropertyName().indexOf('.', 0) >= 0){ |
|
158 |
throw new OperationNotSupportedInPriorViewException("Sorting by related properties is not supported in the history view"); |
|
159 |
} else { |
|
160 |
if(isAscending()){ |
|
161 |
query.addOrder(AuditEntity.property(getPropertyName()).asc()); |
|
162 |
} else { |
|
163 |
query.addOrder(AuditEntity.property(getPropertyName()).desc()); |
|
164 |
} |
|
165 |
} |
|
166 |
} |
|
167 |
|
|
168 |
/** |
|
169 |
* Returns a hql order by clause element which can directly be used in hql queries. |
|
170 |
* |
|
171 |
* e.g.: "titleCache ASC" |
|
172 |
* |
|
173 |
* @return an hql order by clause element |
|
174 |
*/ |
|
175 |
public String toHql(){ |
|
176 |
if(propertyName.equals(LUCENE_SCORE)){ |
|
177 |
logger.error("LUCENE_SCORE not allowed in hql query"); |
|
178 |
} |
|
179 |
return propertyName + " " + sortOrder.toHql(); |
|
180 |
} |
|
181 |
|
|
182 |
/** |
|
183 |
* @return a Lucene {@link SortField} for the Lucene field type <code>Sting</code> |
|
184 |
*/ |
|
185 |
public SortField toSortField() { |
|
186 |
if(propertyName.equals(LUCENE_SCORE)){ |
|
187 |
return SortField.FIELD_SCORE; |
|
188 |
} |
|
189 |
return new SortField(propertyName, SortField.Type.STRING, sortOrder.equals(SortOrder.DESCENDING)); |
|
190 |
} |
|
191 |
|
|
192 |
@Override |
|
193 |
public boolean equals(Object obj) { |
|
194 |
if (obj == this){ |
|
195 |
return true; |
|
196 |
} |
|
197 |
if (obj == null){ |
|
198 |
return false; |
|
199 |
} |
|
200 |
if (!OrderHint.class.isAssignableFrom(obj.getClass())){ |
|
201 |
return false; |
|
202 |
} |
|
203 |
OrderHint orderHint= (OrderHint)obj; |
|
204 |
boolean propertyNameEqual = orderHint.getPropertyName().equals(this.getPropertyName()); |
|
205 |
boolean sortOrderEqual = orderHint.getSortOrder().equals(this.getSortOrder()); |
|
206 |
if (! propertyNameEqual || !sortOrderEqual){ |
|
207 |
return false; |
|
208 |
} |
|
209 |
return true; |
|
210 |
} |
|
211 |
|
|
212 |
@Override |
|
213 |
public int hashCode() { |
|
214 |
int hashCode = 7; |
|
215 |
hashCode = 29 * hashCode + this.getPropertyName().hashCode() * this.getSortOrder().hashCode(); |
|
216 |
return hashCode; |
|
217 |
} |
|
218 |
} |
Also available in: Unified diff
Fix issues after rebase #4716