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