001 // Copyright 2008 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.hibernate;
016
017 import org.apache.tapestry5.grid.GridDataSource;
018 import org.apache.tapestry5.grid.SortConstraint;
019 import org.apache.tapestry5.ioc.internal.util.Defense;
020 import org.hibernate.Criteria;
021 import org.hibernate.Session;
022 import org.hibernate.criterion.Order;
023 import org.hibernate.criterion.Projections;
024
025 import java.util.List;
026
027 /**
028 * A simple implementation of {@link org.apache.tapestry5.grid.GridDataSource} based on a Hibernate Session and a known
029 * entity class. This implementation does support multiple {@link org.apache.tapestry5.grid.SortConstraint sort
030 * constraints}; however it assumes a direct mapping from sort constraint property to Hibernate property.
031 * <p/>
032 * This class is <em>not</em> thread-safe; it maintains internal state.
033 * <p/>
034 * Typically, an instance of this object is created fresh as needed (that is, it is not stored between requests).
035 */
036 public class HibernateGridDataSource implements GridDataSource
037 {
038 private final Session session;
039
040 private final Class entityType;
041
042 private int startIndex;
043
044 private List preparedResults;
045
046 public HibernateGridDataSource(Session session, Class entityType)
047 {
048 Defense.notNull(session, "session");
049 Defense.notNull(entityType, "entityType");
050
051 this.session = session;
052 this.entityType = entityType;
053 }
054
055 /**
056 * Returns the total number of rows for the configured entity type.
057 */
058 public int getAvailableRows()
059 {
060 Criteria criteria = session.createCriteria(entityType);
061
062 applyAdditionalConstraints(criteria);
063
064 criteria.setProjection(Projections.rowCount());
065
066 Integer result = (Integer) criteria.uniqueResult();
067
068 return result;
069 }
070
071 /**
072 * Prepares the results, performing a query (applying the sort results, and the provided start and end index). The
073 * results can later be obtained from {@link #getRowValue(int)} }.
074 *
075 * @param startIndex index, from zero, of the first item to be retrieved
076 * @param endIndex index, from zero, of the last item to be retrieved
077 * @param sortConstraints zero or more constraints used to set the order of the returned values
078 */
079 public void prepare(int startIndex, int endIndex, List<SortConstraint> sortConstraints)
080 {
081 Defense.notNull(sortConstraints, "sortConstraints");
082
083 // We just assume that the property names in the SortContraint match the Hibernate
084 // properties.
085
086 Criteria crit = session.createCriteria(entityType);
087
088 crit.setFirstResult(startIndex).setMaxResults(endIndex - startIndex + 1);
089
090 for (SortConstraint constraint : sortConstraints)
091 {
092
093 String propertyName = constraint.getPropertyModel().getPropertyName();
094
095 switch (constraint.getColumnSort())
096 {
097
098 case ASCENDING:
099
100 crit.addOrder(Order.asc(propertyName));
101 break;
102
103 case DESCENDING:
104 crit.addOrder(Order.desc(propertyName));
105 break;
106
107 default:
108 }
109 }
110
111 applyAdditionalConstraints(crit);
112
113 this.startIndex = startIndex;
114
115 preparedResults = crit.list();
116 }
117
118 /**
119 * Invoked after the main criteria has been set up (firstResult, maxResults and any sort contraints). This gives
120 * subclasses a chance to apply additional constraints before the list of results is obtained from the criteria.
121 * This implementation does nothing and may be overridden.
122 */
123 protected void applyAdditionalConstraints(Criteria crit)
124 {
125 }
126
127 /**
128 * Returns a row value at the given index (which must be within the range defined by the call to {@link
129 * #prepare(int, int, java.util.List)} ).
130 *
131 * @param index of object
132 * @return object at that index
133 */
134 public Object getRowValue(int index)
135 {
136 return preparedResults.get(index - startIndex);
137 }
138
139 /**
140 * Returns the entity type, as provided via the constructor.
141 */
142 public Class getRowType()
143 {
144 return entityType;
145 }
146 }