explicitely ordering taxa for test ReferenceDaoHibernateImplTest.testListCoveredTaxa()
[cdmlib.git] / 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.hibernate.Criteria;
17 import org.hibernate.criterion.Order;
18 import org.hibernate.envers.query.AuditEntity;
19 import org.hibernate.envers.query.AuditQuery;
20
21 import eu.etaxonomy.cdm.model.common.CdmBase;
22 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
23 import eu.etaxonomy.cdm.persistence.dao.common.OperationNotSupportedInPriorViewException;
24
25 public class OrderHint {
26
27 public enum SortOrder {
28
29 /**
30 * items are sorted in increasing
31 * order.
32 */
33 ASCENDING("asc"),
34 /**
35 * items are sorted in decreasing
36 * order.
37 */
38 DESCENDING("desc");
39
40 private String hql;
41
42 private SortOrder(String hqlStr){
43 hql = hqlStr;
44 }
45
46 public String toHql(){
47 return hql;
48 }
49 }
50
51 private final String propertyName;
52
53 private final SortOrder sortOrder;
54
55 public static final List<OrderHint> ORDER_BY_ID = Arrays.asList(new OrderHint[]{new OrderHint("id", SortOrder.ASCENDING)});
56
57 public static final List<OrderHint> ORDER_BY_TITLE_CACHE = Arrays.asList(new OrderHint[]{new OrderHint("titleCache", SortOrder.ASCENDING)});
58
59 /**
60 * @param clazz
61 * @return "by titleCache" for all IdentifiableEntitys otherwise "by id"
62 */
63 public static List<OrderHint> defaultOrderHintsFor(Class<? extends CdmBase> clazz) {
64 if (clazz.isAssignableFrom(IdentifiableEntity.class)) {
65 return ORDER_BY_TITLE_CACHE;
66 } else {
67 return ORDER_BY_ID;
68 }
69 }
70
71 public OrderHint(String fieldName, SortOrder sortOrder) {
72 super();
73 this.propertyName = fieldName;
74 this.sortOrder = sortOrder;
75 }
76
77 /**
78 * The property of a bean
79 * @return
80 */
81 public String getPropertyName() {
82 return propertyName;
83 }
84
85 /**
86 * possible sort orders are {@link SortOrder.ASCENDING} or {@link SortOrder.DESCENDING}
87 * @return
88 */
89 public SortOrder getSortOrder() {
90 return sortOrder;
91 }
92
93 public boolean isAscending(){
94 return sortOrder.equals(SortOrder.ASCENDING);
95 }
96
97 /**
98 * FIXME document this
99 *
100 * @param criteria
101 * @param criteriaMap
102 */
103 public void add(Criteria criteria, Map<String, Criteria> criteriaMap) {
104 if(getPropertyName().indexOf(".") != -1) {
105 /**
106 * Here we have to work a bit of magic as currently hibernate will
107 * throw an error if we attempt to join the same association twice.
108 *
109 * http://opensource.atlassian.com/projects/hibernate/browse/HHH-879
110 */
111 Order order;
112
113 String[] assocObjs = getPropertyName().split("\\.");
114 String path = "";
115 Criteria c = criteria;
116 for(int i = 0; i < assocObjs.length - 1; i++) {
117 path = path + assocObjs[i];
118 if(criteriaMap.get(path) == null) {
119 c = c.createCriteria(assocObjs[i]);
120 criteriaMap.put(path, c);
121 } else {
122 c = criteriaMap.get(path);
123 }
124 path = path + '.';
125 }
126 String propname = assocObjs[assocObjs.length - 1];
127 if(isAscending()){
128 c.addOrder(Order.asc(propname));
129 } else {
130 c.addOrder(Order.desc(propname));
131 }
132 } else {
133 if(isAscending()){
134 criteria.addOrder(Order.asc(getPropertyName()));
135 } else {
136 criteria.addOrder(Order.desc(getPropertyName()));
137 }
138 }
139 }
140
141 /**
142 * FIXME document this
143 *
144 * @param query
145 */
146 public void add(AuditQuery query) {
147
148 if(getPropertyName().indexOf('.', 0) >= 0){
149 throw new OperationNotSupportedInPriorViewException("Sorting by related properties is not supported in the history view");
150 } else {
151 if(isAscending()){
152 query.addOrder(AuditEntity.property(getPropertyName()).asc());
153 } else {
154 query.addOrder(AuditEntity.property(getPropertyName()).desc());
155 }
156 }
157 }
158
159 /**
160 * Returns a hql order by clause element which can directly be used in hql queries.
161 *
162 * e.g.: "titleCache ASC"
163 *
164 * @return an hql order by clause element
165 */
166 public String toHql(){
167 return propertyName + " " + sortOrder.toHql();
168 }
169
170 @Override
171 public boolean equals(Object obj) {
172 if (obj == this){
173 return true;
174 }
175 if (obj == null){
176 return false;
177 }
178 if (!OrderHint.class.isAssignableFrom(obj.getClass())){
179 return false;
180 }
181 OrderHint orderHint= (OrderHint)obj;
182 boolean propertyNameEqual = orderHint.getPropertyName().equals(this.getPropertyName());
183 boolean sortOrderEqual = orderHint.getSortOrder().equals(this.getSortOrder());
184 if (! propertyNameEqual || !sortOrderEqual){
185 return false;
186 }
187 return true;
188 }
189
190 @Override
191 public int hashCode() {
192 int hashCode = 7;
193 hashCode = 29 * hashCode + this.getPropertyName().hashCode() * this.getSortOrder().hashCode();
194 return hashCode;
195 }
196 }