PageRenderTime 41ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/query/src/main/java/org/infinispan/query/dsl/embedded/impl/BaseEmbeddedQuery.java

http://github.com/infinispan/infinispan
Java | 178 lines | 120 code | 23 blank | 35 comment | 22 complexity | 31def10e908922f4b5fcb472fabeea21 MD5 | raw file
Possible License(s): Apache-2.0, LGPL-2.1
  1. package org.infinispan.query.dsl.embedded.impl;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.Collections;
  5. import java.util.Comparator;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.PriorityQueue;
  9. import org.infinispan.AdvancedCache;
  10. import org.infinispan.commons.util.CloseableIterator;
  11. import org.infinispan.objectfilter.ObjectFilter;
  12. import org.infinispan.query.dsl.QueryFactory;
  13. import org.infinispan.query.dsl.impl.BaseQuery;
  14. /**
  15. * Base class for embedded-mode query implementations. Subclasses need to implement {@link #getIterator()} and {@link
  16. * #getComparator()} methods and this class will take care of sorting (fully in-memory).
  17. *
  18. * @author anistor@redhat.com
  19. * @since 8.0
  20. */
  21. abstract class BaseEmbeddedQuery extends BaseQuery {
  22. /**
  23. * Initial capacity of the collection used for collecting results when performing internal sorting.
  24. */
  25. private static final int INITIAL_CAPACITY = 1000;
  26. protected final AdvancedCache<?, ?> cache;
  27. /**
  28. * The cached results, lazily evaluated.
  29. */
  30. private List<Object> results;
  31. /**
  32. * The total number of results matching the query, ignoring pagination. This is lazily evaluated.
  33. */
  34. private int resultSize;
  35. protected BaseEmbeddedQuery(QueryFactory queryFactory, AdvancedCache<?, ?> cache, String jpaQuery, Map<String, Object> namedParameters,
  36. String[] projection, long startOffset, int maxResults) {
  37. super(queryFactory, jpaQuery, namedParameters, projection, startOffset, maxResults);
  38. this.cache = cache;
  39. }
  40. @Override
  41. public void resetQuery() {
  42. results = null;
  43. }
  44. @Override
  45. public <T> List<T> list() {
  46. if (results == null) {
  47. results = listInternal();
  48. }
  49. return (List<T>) results;
  50. }
  51. private List<Object> listInternal() {
  52. List<Object> results;
  53. CloseableIterator<ObjectFilter.FilterResult> iterator = getIterator();
  54. if (!iterator.hasNext()) {
  55. return Collections.emptyList();
  56. }
  57. Comparator<Comparable[]> comparator = getComparator();
  58. if (comparator == null) {
  59. // collect unsorted results and get the requested page if any was specified
  60. try {
  61. if (iterator.hasNext()) {
  62. results = new ArrayList<>(INITIAL_CAPACITY);
  63. while (iterator.hasNext()) {
  64. ObjectFilter.FilterResult entry = iterator.next();
  65. resultSize++;
  66. if (resultSize > startOffset && (maxResults == -1 || results.size() < maxResults)) {
  67. results.add(projection != null ? entry.getProjection() : entry.getInstance());
  68. }
  69. }
  70. } else {
  71. results = Collections.emptyList();
  72. }
  73. } finally {
  74. try {
  75. iterator.close();
  76. } catch (Exception e) {
  77. // exception ignored
  78. }
  79. }
  80. } else {
  81. // collect and sort results, in reverse order for now
  82. PriorityQueue<ObjectFilter.FilterResult> filterResults = new PriorityQueue<>(INITIAL_CAPACITY, new ReverseFilterResultComparator(comparator));
  83. try {
  84. while (iterator.hasNext()) {
  85. ObjectFilter.FilterResult entry = iterator.next();
  86. resultSize++;
  87. filterResults.add(entry);
  88. if (maxResults != -1 && filterResults.size() > startOffset + maxResults) {
  89. // remove the head, which is actually the highest result
  90. filterResults.remove();
  91. }
  92. }
  93. } finally {
  94. try {
  95. iterator.close();
  96. } catch (Exception e) {
  97. // exception ignored
  98. }
  99. }
  100. // collect and reverse
  101. if (filterResults.size() > startOffset) {
  102. Object[] res = new Object[filterResults.size() - startOffset];
  103. int i = filterResults.size();
  104. while (i-- > startOffset) {
  105. ObjectFilter.FilterResult r = filterResults.remove();
  106. res[i - startOffset] = projection != null ? r.getProjection() : r.getInstance();
  107. }
  108. results = Arrays.asList(res);
  109. } else {
  110. results = Collections.emptyList();
  111. }
  112. }
  113. return results;
  114. }
  115. /**
  116. * Create a comparator to be used for ordering the results returned by {@link #getIterator()}.
  117. *
  118. * @return the comparator or {@code null} if no sorting needs to be applied
  119. */
  120. protected abstract Comparator<Comparable[]> getComparator();
  121. /**
  122. * Create an iterator over the results of the query, in no particular order. Ordering will be provided if {@link
  123. * #getComparator()} returns a non-null {@link Comparator}.
  124. */
  125. protected abstract CloseableIterator<ObjectFilter.FilterResult> getIterator();
  126. @Override
  127. public int getResultSize() {
  128. list();
  129. return resultSize;
  130. }
  131. @Override
  132. public String toString() {
  133. return "BaseEmbeddedQuery{" +
  134. "jpaQuery=" + jpaQuery +
  135. ", namedParameters=" + namedParameters +
  136. ", projection=" + Arrays.toString(projection) +
  137. ", startOffset=" + startOffset +
  138. ", maxResults=" + maxResults +
  139. '}';
  140. }
  141. /**
  142. * Compares two {@link ObjectFilter.FilterResult} objects based on a given {@link Comparator} and reverses the
  143. * result.
  144. */
  145. private static class ReverseFilterResultComparator implements Comparator<ObjectFilter.FilterResult> {
  146. private final Comparator<Comparable[]> comparator;
  147. private ReverseFilterResultComparator(Comparator<Comparable[]> comparator) {
  148. this.comparator = comparator;
  149. }
  150. @Override
  151. public int compare(ObjectFilter.FilterResult o1, ObjectFilter.FilterResult o2) {
  152. return -comparator.compare(o1.getSortProjection(), o2.getSortProjection());
  153. }
  154. }
  155. }