001 package net.databinder.models.hib;
002
003 /*
004 * Databinder: a simple bridge from Wicket to Hibernate
005 * Copyright (C) 2006 Nathan Hamblen nathan@technically.us
006
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * You should have received a copy of the GNU Lesser General Public
018 * License along with this library; if not, write to the Free Software
019 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
020 */
021
022 import java.io.Serializable;
023
024 import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortState;
025 import org.apache.wicket.extensions.markup.html.repeater.data.sort.ISortStateLocator;
026 import org.apache.wicket.extensions.markup.html.repeater.util.SingleSortState;
027 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
028 import org.hibernate.Criteria;
029 import org.hibernate.criterion.CriteriaSpecification;
030 import org.hibernate.criterion.Order;
031
032 /**
033 * <h1>CriteriaSorter</h1>
034 * <i>Copyright (C) 2008 The Scripps Research Institute</i>
035 * <p>A Criteria based sorter suitable for adding to a HibernateProvider</p>
036 * * <pre>
037 * // a default sort by name, ascending and case insensitive:
038 * CriteriaSorter sorter = new CriteriaSorter("name",true,false);
039 * IDataProvider provider = new DatabinderProvider(objectClass, criteriaBuilder, sorter);
040 * </pre>
041 * * @author Mark Southern (southern at scripps dot edu)
042 */
043 public class CriteriaSorter implements ISortStateLocator, CriteriaBuilder, Serializable {
044
045 private SingleSortState sortState;
046
047 private String defaultProperty = null;
048
049 boolean asc, cased;
050
051 public CriteriaSorter() {
052 this(null, true, true);
053 }
054
055 public CriteriaSorter(String defaultProperty) {
056 this(defaultProperty, true, true);
057 }
058
059 public CriteriaSorter(String defaultProperty, boolean asc) {
060 this(defaultProperty, asc, true);
061 }
062
063 /**
064 * @param defaultProperty - property for a default sort before any is set
065 * @param asc - sort ascending/descending
066 * @param cased - sort cased/case insensitive
067 */
068 public CriteriaSorter(String defaultProperty, boolean asc, boolean cased) {
069 sortState = new SingleSortState();
070 this.defaultProperty = defaultProperty;
071 this.asc = asc;
072 this.cased = cased;
073 }
074
075 public void build(Criteria criteria) {
076 SortParam sort = sortState.getSort();
077 String property;
078 if (sort != null && sort.getProperty() != null) {
079 property = sort.getProperty();
080 asc = sort.isAscending();
081 }
082 else {
083 property = defaultProperty;
084 }
085 if (property != null) {
086 if (property.contains(".")) {
087 // for 'dot' properties we need to add aliases
088 // e.g. for the property 'orderbook.order.item.name' we need to add an aliases for 'order' and 'order.item'
089 String path[] = property.split("\\.");
090 for (int ii = 0; ii < path.length - 1; ii++) {
091 StringBuffer sb = new StringBuffer();
092 for (int jj = 0; jj <= ii; jj++) {
093 if (sb.length() > 0)
094 sb.append(".");
095 sb.append(path[jj]);
096 }
097 criteria.createAlias(sb.toString(), path[ii], CriteriaSpecification.LEFT_JOIN);
098 }
099 // when we have a 'dot' property we want to sort by the sub tables field
100 // e.g. for the property 'orderbook.order.item.name' we need to sort by 'item.name'
101 if (path.length > 1)
102 property = String.format("%s.%s", path[path.length - 2], path[path.length - 1]);
103 else
104 property = path[path.length - 1];
105 }
106 Order order = asc ? Order.asc(property) : Order.desc(property);
107 order = cased ? order : order.ignoreCase();
108 criteria.addOrder(order);
109 }
110 }
111
112 public ISortState getSortState() {
113 return sortState;
114 }
115
116 public void setSortState(ISortState state) {
117 sortState = (SingleSortState) state;
118 }
119 }