45
45
import org .springframework .data .util .TypeInformation ;
46
46
import org .springframework .graphql .data .GraphQlArgumentBinder ;
47
47
import org .springframework .graphql .data .GraphQlRepository ;
48
+ import org .springframework .graphql .data .pagination .CursorEncoder ;
48
49
import org .springframework .graphql .data .pagination .CursorStrategy ;
49
50
import org .springframework .graphql .data .query .AutoRegistrationRuntimeWiringConfigurer .DataFetcherFactory ;
50
51
import org .springframework .graphql .execution .RuntimeWiringConfigurer ;
@@ -165,6 +166,7 @@ protected Collection<String> buildPropertyPaths(DataFetchingFieldSelectionSet se
165
166
}
166
167
167
168
protected ScrollSubrange buildScrollSubrange (DataFetchingEnvironment environment ) {
169
+ Assert .state (this .cursorStrategy != null , "Expected CursorStrategy" );
168
170
return RepositoryUtils .buildScrollSubrange (environment , this .cursorStrategy );
169
171
}
170
172
@@ -234,7 +236,10 @@ public static RuntimeWiringConfigurer autoRegistrationConfigurer(
234
236
for (QueryByExampleExecutor <?> executor : executors ) {
235
237
String typeName = RepositoryUtils .getGraphQlTypeName (executor );
236
238
if (typeName != null ) {
237
- Builder <?, ?> builder = customize (executor , builder (executor ));
239
+ Builder <?, ?> builder = customize (executor , builder (executor )
240
+ .cursorStrategy (cursorStrategy )
241
+ .defaultScrollSubrange (defaultScrollSubrange ));
242
+
238
243
factories .put (typeName , new DataFetcherFactory () {
239
244
@ Override
240
245
public DataFetcher <?> single () {
@@ -248,7 +253,7 @@ public DataFetcher<?> many() {
248
253
249
254
@ Override
250
255
public DataFetcher <?> scrollable () {
251
- return builder .scrollable (cursorStrategy , defaultScrollSubrange );
256
+ return builder .scrollable ();
252
257
}
253
258
});
254
259
}
@@ -257,7 +262,10 @@ public DataFetcher<?> scrollable() {
257
262
for (ReactiveQueryByExampleExecutor <?> executor : reactiveExecutors ) {
258
263
String typeName = RepositoryUtils .getGraphQlTypeName (executor );
259
264
if (typeName != null ) {
260
- ReactiveBuilder <?, ?> builder = customize (executor , builder (executor ));
265
+ ReactiveBuilder <?, ?> builder = customize (executor , builder (executor )
266
+ .cursorStrategy (cursorStrategy )
267
+ .defaultScrollSubrange (defaultScrollSubrange ));
268
+
261
269
factories .put (typeName , new DataFetcherFactory () {
262
270
@ Override
263
271
public DataFetcher <?> single () {
@@ -271,7 +279,7 @@ public DataFetcher<?> many() {
271
279
272
280
@ Override
273
281
public DataFetcher <?> scrollable () {
274
- return builder .scrollable (cursorStrategy , defaultScrollSubrange );
282
+ return builder .scrollable ();
275
283
}
276
284
});
277
285
}
@@ -356,17 +364,28 @@ public static class Builder<T, R> {
356
364
357
365
private final Class <R > resultType ;
358
366
367
+ @ Nullable
368
+ private final CursorStrategy <ScrollPosition > cursorStrategy ;
369
+
370
+ @ Nullable
371
+ private final ScrollSubrange defaultSubrange ;
372
+
359
373
private final Sort sort ;
360
374
361
375
@ SuppressWarnings ("unchecked" )
362
376
Builder (QueryByExampleExecutor <T > executor , Class <R > domainType ) {
363
- this (executor , TypeInformation .of ((Class <T >) domainType ), domainType , Sort .unsorted ());
377
+ this (executor , TypeInformation .of ((Class <T >) domainType ), domainType , null , null , Sort .unsorted ());
364
378
}
365
379
366
- Builder (QueryByExampleExecutor <T > executor , TypeInformation <T > domainType , Class <R > resultType , Sort sort ) {
380
+ Builder (QueryByExampleExecutor <T > executor , TypeInformation <T > domainType , Class <R > resultType ,
381
+ @ Nullable CursorStrategy <ScrollPosition > cursorStrategy , @ Nullable ScrollSubrange defaultSubrange ,
382
+ Sort sort ) {
383
+
367
384
this .executor = executor ;
368
385
this .domainType = domainType ;
369
386
this .resultType = resultType ;
387
+ this .cursorStrategy = cursorStrategy ;
388
+ this .defaultSubrange = defaultSubrange ;
370
389
this .sort = sort ;
371
390
}
372
391
@@ -381,7 +400,36 @@ public static class Builder<T, R> {
381
400
*/
382
401
public <P > Builder <T , P > projectAs (Class <P > projectionType ) {
383
402
Assert .notNull (projectionType , "Projection type must not be null" );
384
- return new Builder <>(this .executor , this .domainType , projectionType , this .sort );
403
+ return new Builder <>(this .executor , this .domainType ,
404
+ projectionType , this .cursorStrategy , this .defaultSubrange , this .sort );
405
+ }
406
+
407
+ /**
408
+ * Configure strategy for decoding a cursor from a paginated request.
409
+ * <p>By default, this is {@link ScrollPositionCursorStrategy} with
410
+ * {@link CursorEncoder#base64()} encoding.
411
+ * @param cursorStrategy the strategy to use
412
+ * @return a new {@link Builder} instance with all previously configured
413
+ * options and {@code Sort} applied
414
+ * @since 1.2
415
+ */
416
+ public Builder <T , R > cursorStrategy (@ Nullable CursorStrategy <ScrollPosition > cursorStrategy ) {
417
+ return new Builder <>(this .executor , this .domainType ,
418
+ this .resultType , cursorStrategy , this .defaultSubrange , this .sort );
419
+ }
420
+
421
+ /**
422
+ * Configure a {@link ScrollSubrange} to use when a paginated request does
423
+ * not specify a cursor and/or a count of items.
424
+ * <p>By default, this is {@link OffsetScrollPosition#initial()} with a
425
+ * count of 20.
426
+ * @return a new {@link Builder} instance with all previously configured
427
+ * options and {@code Sort} applied
428
+ * @since 1.2
429
+ */
430
+ public Builder <T , R > defaultScrollSubrange (@ Nullable ScrollSubrange defaultSubrange ) {
431
+ return new Builder <>(this .executor , this .domainType ,
432
+ this .resultType , this .cursorStrategy , defaultSubrange , this .sort );
385
433
}
386
434
387
435
/**
@@ -392,7 +440,8 @@ public <P> Builder<T, P> projectAs(Class<P> projectionType) {
392
440
*/
393
441
public Builder <T , R > sortBy (Sort sort ) {
394
442
Assert .notNull (sort , "Sort must not be null" );
395
- return new Builder <>(this .executor , this .domainType , this .resultType , sort );
443
+ return new Builder <>(this .executor , this .domainType ,
444
+ this .resultType , this .cursorStrategy , this .defaultSubrange , sort );
396
445
}
397
446
398
447
/**
@@ -414,11 +463,12 @@ public DataFetcher<Iterable<R>> many() {
414
463
* {@link org.springframework.data.domain.Window}.
415
464
* @since 1.2
416
465
*/
417
- public DataFetcher <Iterable <R >> scrollable (
418
- CursorStrategy <ScrollPosition > cursorStrategy , ScrollSubrange defaultScrollSubrange ) {
419
-
466
+ public DataFetcher <Iterable <R >> scrollable () {
420
467
return new ScrollableEntityFetcher <>(
421
- this .executor , this .domainType , this .resultType , cursorStrategy , defaultScrollSubrange , this .sort );
468
+ this .executor , this .domainType , this .resultType ,
469
+ (this .cursorStrategy != null ? this .cursorStrategy : RepositoryUtils .defaultCursorStrategy ()),
470
+ (this .defaultSubrange != null ? this .defaultSubrange : RepositoryUtils .defaultScrollSubrange ()),
471
+ this .sort );
422
472
}
423
473
424
474
}
@@ -460,20 +510,29 @@ public static class ReactiveBuilder<T, R> {
460
510
461
511
private final Class <R > resultType ;
462
512
513
+ @ Nullable
514
+ private final CursorStrategy <ScrollPosition > cursorStrategy ;
515
+
516
+ @ Nullable
517
+ private final ScrollSubrange defaultSubrange ;
518
+
463
519
private final Sort sort ;
464
520
465
521
@ SuppressWarnings ("unchecked" )
466
522
ReactiveBuilder (ReactiveQueryByExampleExecutor <T > executor , Class <R > domainType ) {
467
- this (executor , TypeInformation .of ((Class <T >) domainType ), domainType , Sort .unsorted ());
523
+ this (executor , TypeInformation .of ((Class <T >) domainType ), domainType , null , null , Sort .unsorted ());
468
524
}
469
525
470
526
ReactiveBuilder (
471
- ReactiveQueryByExampleExecutor <T > executor , TypeInformation <T > domainType ,
472
- Class <R > resultType , Sort sort ) {
527
+ ReactiveQueryByExampleExecutor <T > executor , TypeInformation <T > domainType , Class <R > resultType ,
528
+ @ Nullable CursorStrategy <ScrollPosition > cursorStrategy , @ Nullable ScrollSubrange defaultSubrange ,
529
+ Sort sort ) {
473
530
474
531
this .executor = executor ;
475
532
this .domainType = domainType ;
476
533
this .resultType = resultType ;
534
+ this .cursorStrategy = cursorStrategy ;
535
+ this .defaultSubrange = defaultSubrange ;
477
536
this .sort = sort ;
478
537
}
479
538
@@ -488,7 +547,36 @@ public static class ReactiveBuilder<T, R> {
488
547
*/
489
548
public <P > ReactiveBuilder <T , P > projectAs (Class <P > projectionType ) {
490
549
Assert .notNull (projectionType , "Projection type must not be null" );
491
- return new ReactiveBuilder <>(this .executor , this .domainType , projectionType , this .sort );
550
+ return new ReactiveBuilder <>(this .executor , this .domainType ,
551
+ projectionType , this .cursorStrategy , this .defaultSubrange , this .sort );
552
+ }
553
+
554
+ /**
555
+ * Configure strategy for decoding a cursor from a paginated request.
556
+ * <p>By default, this is {@link ScrollPositionCursorStrategy} with
557
+ * {@link CursorEncoder#base64()} encoding.
558
+ * @param cursorStrategy the strategy to use
559
+ * @return a new {@link Builder} instance with all previously configured
560
+ * options and {@code Sort} applied
561
+ * @since 1.2
562
+ */
563
+ public ReactiveBuilder <T , R > cursorStrategy (@ Nullable CursorStrategy <ScrollPosition > cursorStrategy ) {
564
+ return new ReactiveBuilder <>(this .executor , this .domainType ,
565
+ this .resultType , cursorStrategy , this .defaultSubrange , this .sort );
566
+ }
567
+
568
+ /**
569
+ * Configure a {@link ScrollSubrange} to use when a paginated request does
570
+ * not specify a cursor and/or a count of items.
571
+ * <p>By default, this is {@link OffsetScrollPosition#initial()} with a
572
+ * count of 20.
573
+ * @return a new {@link Builder} instance with all previously configured
574
+ * options and {@code Sort} applied
575
+ * @since 1.2
576
+ */
577
+ public ReactiveBuilder <T , R > defaultScrollSubrange (@ Nullable ScrollSubrange defaultSubrange ) {
578
+ return new ReactiveBuilder <>(this .executor , this .domainType ,
579
+ this .resultType , this .cursorStrategy , defaultSubrange , this .sort );
492
580
}
493
581
494
582
/**
@@ -499,7 +587,8 @@ public <P> ReactiveBuilder<T, P> projectAs(Class<P> projectionType) {
499
587
*/
500
588
public ReactiveBuilder <T , R > sortBy (Sort sort ) {
501
589
Assert .notNull (sort , "Sort must not be null" );
502
- return new ReactiveBuilder <>(this .executor , this .domainType , this .resultType , sort );
590
+ return new ReactiveBuilder <>(this .executor , this .domainType ,
591
+ this .resultType , this .cursorStrategy , this .defaultSubrange , sort );
503
592
}
504
593
505
594
/**
@@ -521,11 +610,12 @@ public DataFetcher<Flux<R>> many() {
521
610
* {@link org.springframework.data.domain.Window}.
522
611
* @since 1.2
523
612
*/
524
- public DataFetcher <Mono <Iterable <R >>> scrollable (
525
- CursorStrategy <ScrollPosition > cursorStrategy , ScrollSubrange defaultScrollSubrange ) {
526
-
613
+ public DataFetcher <Mono <Iterable <R >>> scrollable () {
527
614
return new ReactiveScrollableEntityFetcher <>(
528
- this .executor , this .domainType , this .resultType , cursorStrategy , defaultScrollSubrange , this .sort );
615
+ this .executor , this .domainType , this .resultType ,
616
+ (this .cursorStrategy != null ? this .cursorStrategy : RepositoryUtils .defaultCursorStrategy ()),
617
+ (this .defaultSubrange != null ? this .defaultSubrange : RepositoryUtils .defaultScrollSubrange ()),
618
+ this .sort );
529
619
}
530
620
531
621
}
0 commit comments