/src/main/java/org/hibernate/shards/criteria/ExitOperationsCriteriaCollector.java

https://github.com/donnchadh/hibernate-shards · Java · 192 lines · 89 code · 26 blank · 77 comment · 21 complexity · d310020ff84e9fb4726f539e2ef40f11 MD5 · raw file

  1. /**
  2. * Copyright (C) 2007 Google Inc.
  3. *
  4. * This library is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. * Lesser General Public License for more details.
  12. * You should have received a copy of the GNU Lesser General Public
  13. * License along with this library; if not, write to the Free Software
  14. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  15. */
  16. package org.hibernate.shards.criteria;
  17. import org.apache.commons.logging.Log;
  18. import org.apache.commons.logging.LogFactory;
  19. import org.hibernate.criterion.AggregateProjection;
  20. import org.hibernate.criterion.Distinct;
  21. import org.hibernate.criterion.Order;
  22. import org.hibernate.criterion.Projection;
  23. import org.hibernate.criterion.RowCountProjection;
  24. import org.hibernate.engine.SessionFactoryImplementor;
  25. import org.hibernate.shards.strategy.exit.AvgResultsExitOperation;
  26. import org.hibernate.shards.strategy.exit.DistinctExitOperation;
  27. import org.hibernate.shards.strategy.exit.ExitOperationsCollector;
  28. import org.hibernate.shards.strategy.exit.FirstResultExitOperation;
  29. import org.hibernate.shards.strategy.exit.MaxResultsExitOperation;
  30. import org.hibernate.shards.strategy.exit.OrderExitOperation;
  31. import org.hibernate.shards.strategy.exit.ProjectionExitOperationFactory;
  32. import org.hibernate.shards.util.Lists;
  33. import java.util.List;
  34. /**
  35. * Implements the ExitOperationsCollector interface for Critierias
  36. *
  37. * @author Maulik Shah
  38. */
  39. public class ExitOperationsCriteriaCollector implements ExitOperationsCollector {
  40. // maximum number of results requested by the client
  41. private Integer maxResults = null;
  42. // index of the first result requested by the client
  43. private Integer firstResult = null;
  44. // Distinct operation applied to the Criteria
  45. private Distinct distinct = null;
  46. // Average Projection operation applied to the Criteria
  47. private AggregateProjection avgProjection = null;
  48. // Aggregate Projecton operation applied to the Criteria
  49. private AggregateProjection aggregateProjection = null;
  50. // Row Count Projection operation applied to the Criteria
  51. private RowCountProjection rowCountProjection;
  52. // The Session Factory Implementor with which the Criteria is associated
  53. private SessionFactoryImplementor sessionFactoryImplementor;
  54. // Order operations applied to the Criteria
  55. private List<Order> orders = Lists.newArrayList();
  56. // Our friendly neighborhood logger
  57. private final Log log = LogFactory.getLog(getClass());
  58. /**
  59. * Sets the maximum number of results requested by the client
  60. *
  61. * @param maxResults maximum number of results requested by the client
  62. * @return this
  63. */
  64. public ExitOperationsCollector setMaxResults(int maxResults) {
  65. this.maxResults = maxResults;
  66. return this;
  67. }
  68. /**
  69. * Sets the index of the first result requested by the client
  70. *
  71. * @param firstResult index of the first result requested by the client
  72. * @return this
  73. */
  74. public ExitOperationsCollector setFirstResult(int firstResult) {
  75. this.firstResult = firstResult;
  76. return this;
  77. }
  78. /**
  79. * Adds the given projection.
  80. *
  81. * @param projection the projection to add
  82. * @return this
  83. */
  84. public ExitOperationsCollector addProjection(Projection projection) {
  85. if (projection instanceof Distinct) {
  86. this.distinct = (Distinct)projection;
  87. // TODO(maulik) Distinct doesn't work yet
  88. log.error("Distinct is not ready yet");
  89. throw new UnsupportedOperationException();
  90. } else if(projection instanceof RowCountProjection) {
  91. this.rowCountProjection = (RowCountProjection) projection;
  92. } else if(projection instanceof AggregateProjection) {
  93. if (projection.toString().toLowerCase().startsWith("avg")) {
  94. this.avgProjection = (AggregateProjection) projection;
  95. } else {
  96. this.aggregateProjection = (AggregateProjection) projection;
  97. }
  98. } else {
  99. log.error("Adding an unsupported Projection: " + projection.getClass().getName());
  100. throw new UnsupportedOperationException();
  101. }
  102. return this;
  103. }
  104. /**
  105. * Add the given Order
  106. *
  107. * @param order the order to add
  108. * @return this
  109. */
  110. public ExitOperationsCollector addOrder(Order order) {
  111. this.orders.add(order);
  112. return this;
  113. }
  114. public List<Object> apply(List<Object> result) {
  115. /**
  116. * Herein lies the glory
  117. *
  118. * hibernate has done as much as it can, we're going to have to deal with
  119. * the rest in memory.
  120. *
  121. * The heirarchy of operations is this so far:
  122. * Distinct
  123. * Order
  124. * FirstResult
  125. * MaxResult
  126. * RowCount
  127. * Average
  128. * Min/Max/Sum
  129. */
  130. // ordering of the following operations *really* matters!
  131. if (distinct != null) {
  132. result = new DistinctExitOperation(distinct).apply(result);
  133. }
  134. for(Order order : orders) {
  135. result = new OrderExitOperation(order).apply(result);
  136. }
  137. if (firstResult != null) {
  138. result = new FirstResultExitOperation(firstResult).apply(result);
  139. }
  140. if (maxResults != null) {
  141. result = new MaxResultsExitOperation(maxResults).apply(result);
  142. }
  143. ProjectionExitOperationFactory factory =
  144. ProjectionExitOperationFactory.getFactory();
  145. if (rowCountProjection != null) {
  146. result = factory.getProjectionExitOperation(rowCountProjection, sessionFactoryImplementor).apply(result);
  147. }
  148. if (avgProjection != null) {
  149. result = new AvgResultsExitOperation().apply(result);
  150. }
  151. // min, max, sum
  152. if (aggregateProjection != null) {
  153. result = factory.getProjectionExitOperation(aggregateProjection, sessionFactoryImplementor).apply(result);
  154. }
  155. return result;
  156. }
  157. /**
  158. * Sets the session factory implementor
  159. * @param sessionFactoryImplementor the session factory implementor to set
  160. */
  161. public void setSessionFactory(SessionFactoryImplementor sessionFactoryImplementor) {
  162. this.sessionFactoryImplementor = sessionFactoryImplementor;
  163. }
  164. }