1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.bremersee.pagebuilder;
18
19 import static java.util.Objects.requireNonNullElse;
20
21 import java.util.Arrays;
22 import java.util.Comparator;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.Objects;
26 import java.util.Spliterator;
27 import java.util.Spliterators;
28 import java.util.function.Function;
29 import java.util.function.Predicate;
30 import java.util.stream.Collectors;
31 import java.util.stream.Stream;
32 import java.util.stream.StreamSupport;
33 import org.bremersee.comparator.ComparatorBuilder;
34 import org.bremersee.comparator.ValueComparator;
35 import org.bremersee.comparator.model.SortOrder;
36 import org.bremersee.comparator.model.SortOrderItem;
37 import org.bremersee.comparator.spring.mapper.SortMapper;
38 import org.springframework.data.domain.Page;
39 import org.springframework.data.domain.PageImpl;
40 import org.springframework.data.domain.PageRequest;
41 import org.springframework.data.domain.Pageable;
42 import org.springframework.data.domain.Sort;
43 import org.springframework.util.ObjectUtils;
44
45
46
47
48
49
50
51
52 public class PageBuilder<S, T> {
53
54 private Stream<? extends S> sourceEntries;
55
56 private Predicate<S> sourceFilter;
57
58 private Function<SortOrderItem, Comparator<?>> sourceSortFn;
59
60 private Integer pageNumber;
61
62 private Integer pageSize;
63
64 private List<SortOrderItem> sort;
65
66 private SortTarget sortTarget;
67
68 private Function<S, T> converter;
69
70 private Predicate<T> targetFilter;
71
72 private Function<SortOrderItem, Comparator<?>> targetSortFn;
73
74
75
76
77 public PageBuilder() {
78 sourceFilter = sourceEntry -> true;
79
80 sourceSortFn = cf -> (Comparator<S>) new ValueComparator(cf);
81
82 converter = e -> (T) e;
83 targetFilter = targetEntry -> true;
84
85 targetSortFn = cf -> (Comparator<T>) new ValueComparator(cf);
86 }
87
88
89
90
91
92
93
94 public PageBuilder<S, T> sourceEntries(Stream<? extends S> entries) {
95 if (!Objects.isNull(entries)) {
96 this.sourceEntries = entries;
97 }
98 return this;
99 }
100
101
102
103
104
105
106
107 public PageBuilder<S, T> sourceEntries(Iterable<? extends S> entries) {
108 if (!Objects.isNull(entries)) {
109 this.sourceEntries = StreamSupport.stream(entries.spliterator(), false);
110 }
111 return this;
112 }
113
114
115
116
117
118
119
120 public PageBuilder<S, T> sourceEntries(Iterator<? extends S> entries) {
121 if (!Objects.isNull(entries)) {
122 this.sourceEntries = StreamSupport.stream(Spliterators
123 .spliteratorUnknownSize(entries, Spliterator.ORDERED), false);
124 }
125 return this;
126 }
127
128
129
130
131
132
133
134 public PageBuilder<S, T> sourceFilter(Predicate<S> sourceFilter) {
135 if (!Objects.isNull(sourceFilter)) {
136 this.sourceFilter = sourceFilter;
137 }
138 return this;
139 }
140
141
142
143
144
145
146
147 public PageBuilder<S, T> sourceSortFn(
148 Function<SortOrderItem, Comparator<?>> sourceSortFn) {
149 if (!Objects.isNull(sourceSortFn)) {
150 this.sourceSortFn = sourceSortFn;
151 }
152 return this;
153 }
154
155
156
157
158
159
160
161 public PageBuilder<S, T> pageable(Pageable pageable) {
162 return pageable(pageable, SortTarget.TARGET_ENTRIES);
163 }
164
165
166
167
168
169
170
171
172 public PageBuilder<S, T> pageable(Pageable pageable, SortTarget sortTarget) {
173 if (!Objects.isNull(pageable)) {
174 return pageable(
175 pageable.getPageNumber(),
176 pageable.getPageSize(),
177 sortTarget,
178 SortMapper.defaultSortMapper().fromSort(pageable.getSort()).getItems());
179 }
180 return this;
181 }
182
183
184
185
186
187
188
189
190
191 public PageBuilder<S, T> pageable(
192 Integer pageNumber,
193 Integer pageSize,
194 SortOrderItem... sort) {
195 return pageable(
196 pageNumber,
197 pageSize,
198 SortTarget.TARGET_ENTRIES,
199 Objects.isNull(sort) ? null : Arrays.asList(sort));
200 }
201
202
203
204
205
206
207
208
209
210 public PageBuilder<S, T> pageable(
211 Integer pageNumber,
212 Integer pageSize,
213 List<SortOrderItem> sort) {
214 return pageable(pageNumber, pageSize, SortTarget.TARGET_ENTRIES, sort);
215 }
216
217
218
219
220
221
222
223
224
225
226 public PageBuilder<S, T> pageable(
227 Integer pageNumber,
228 Integer pageSize,
229 SortTarget sortTarget,
230 SortOrderItem... sort) {
231 return pageable(
232 pageNumber,
233 pageSize,
234 sortTarget,
235 Objects.isNull(sort) ? null : Arrays.asList(sort));
236 }
237
238
239
240
241
242
243
244
245
246
247 public PageBuilder<S, T> pageable(
248 Integer pageNumber,
249 Integer pageSize,
250 SortTarget sortTarget,
251 List<SortOrderItem> sort) {
252
253 Pageable pageable = PageRequest.of(pageNumber, pageSize);
254 this.pageNumber = pageable.getPageNumber();
255 this.pageSize = pageable.getPageSize();
256 this.sort = sort;
257 if (ObjectUtils.isEmpty(this.sort)) {
258 this.sortTarget = null;
259 } else {
260 this.sortTarget = requireNonNullElse(sortTarget, SortTarget.TARGET_ENTRIES);
261 }
262 return this;
263 }
264
265
266
267
268
269
270
271 public PageBuilder<S, T> converter(Function<S, T> converter) {
272 if (!Objects.isNull(converter)) {
273 this.converter = converter;
274 }
275 return this;
276 }
277
278
279
280
281
282
283
284 public PageBuilder<S, T> targetFilter(Predicate<T> targetFilter) {
285 if (!Objects.isNull(targetFilter)) {
286 this.targetFilter = targetFilter;
287 }
288 return this;
289 }
290
291
292
293
294
295
296
297 public PageBuilder<S, T> targetSortFn(
298 Function<SortOrderItem, Comparator<?>> targetSortFn) {
299 if (!Objects.isNull(targetSortFn)) {
300 this.targetSortFn = targetSortFn;
301 }
302 return this;
303 }
304
305
306
307
308
309
310 public Page<T> build() {
311
312 final List<S> source = ((Stream<S>) requireNonNullElse(this.sourceEntries, Stream.empty()))
313 .filter(sourceFilter)
314 .collect(Collectors.toList());
315 if (SortTarget.SOURCE_ENTRIES.equals(sortTarget) && !ObjectUtils.isEmpty(sort)) {
316 source.sort(ComparatorBuilder.newInstance()
317 .addAll(sort, sourceSortFn)
318 .build());
319 }
320 final List<T> target = source.stream()
321 .map(converter)
322 .filter(targetFilter)
323 .collect(Collectors.toList());
324 final Sort pageSort;
325 if (SortTarget.TARGET_ENTRIES.equals(sortTarget) && !ObjectUtils.isEmpty(sort)) {
326 target.sort(ComparatorBuilder.newInstance()
327 .addAll(sort, targetSortFn)
328 .build());
329 pageSort = SortMapper.defaultSortMapper().toSort(new SortOrder(sort));
330 } else {
331 pageSort = Sort.unsorted();
332 }
333
334 int number = requireNonNullElse(pageNumber, 0);
335 int size = requireNonNullElse(pageSize, Integer.MAX_VALUE);
336 final Pageable pageable = PageRequest.of(number, size, pageSort);
337 final List<T> content = target.stream()
338 .skip(pageable.getOffset())
339 .limit(pageable.getPageSize())
340 .toList();
341 return new PageImpl<>(content, pageable, target.size());
342 }
343
344
345
346
347 public enum SortTarget {
348
349
350
351 SOURCE_ENTRIES,
352
353
354
355 TARGET_ENTRIES
356 }
357 }