1515 */
1616package org .springframework .data .neo4j .repository .query ;
1717
18- import java .util .Collection ;
19- import java .util .List ;
20- import java .util .function .Function ;
21- import java .util .function .LongSupplier ;
22- import java .util .stream .Stream ;
23-
2418import org .apiguardian .api .API ;
19+ import org .neo4j .cypherdsl .core .Condition ;
2520import org .springframework .data .domain .Example ;
21+ import org .springframework .data .domain .KeysetScrollPosition ;
22+ import org .springframework .data .domain .OffsetScrollPosition ;
2623import org .springframework .data .domain .Page ;
2724import org .springframework .data .domain .Pageable ;
25+ import org .springframework .data .domain .ScrollPosition ;
2826import org .springframework .data .domain .Sort ;
27+ import org .springframework .data .domain .Window ;
2928import org .springframework .data .neo4j .core .FluentFindOperation ;
3029import org .springframework .data .neo4j .core .mapping .Neo4jMappingContext ;
30+ import org .springframework .data .neo4j .core .mapping .Neo4jPersistentEntity ;
3131import org .springframework .data .repository .query .FluentQuery .FetchableFluentQuery ;
3232import org .springframework .data .support .PageableExecutionUtils ;
3333import org .springframework .lang .Nullable ;
3434
35+ import java .util .Collection ;
36+ import java .util .List ;
37+ import java .util .function .Function ;
38+ import java .util .function .LongSupplier ;
39+ import java .util .stream .Stream ;
40+
3541/**
3642 * Immutable implementation of a {@link FetchableFluentQuery}. All
3743 * methods that return a {@link FetchableFluentQuery} return a new instance, the original instance won't be
@@ -64,7 +70,7 @@ final class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<R> im
6470 Function <Example <S >, Boolean > existsOperation
6571 ) {
6672 this (example , resultType , mappingContext , findOperation , countOperation , existsOperation , Sort .unsorted (),
67- null );
73+ null , null );
6874 }
6975
7076 FetchableFluentQueryByExample (
@@ -75,9 +81,10 @@ final class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<R> im
7581 Function <Example <S >, Long > countOperation ,
7682 Function <Example <S >, Boolean > existsOperation ,
7783 Sort sort ,
84+ @ Nullable Integer limit ,
7885 @ Nullable Collection <String > properties
7986 ) {
80- super (resultType , sort , properties );
87+ super (resultType , sort , limit , properties );
8188 this .mappingContext = mappingContext ;
8289 this .example = example ;
8390 this .findOperation = findOperation ;
@@ -90,7 +97,14 @@ final class FetchableFluentQueryByExample<S, R> extends FluentQuerySupport<R> im
9097 public FetchableFluentQuery <R > sortBy (Sort sort ) {
9198
9299 return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .mappingContext , this .findOperation ,
93- this .countOperation , this .existsOperation , this .sort .and (sort ), this .properties );
100+ this .countOperation , this .existsOperation , this .sort .and (sort ), this .limit , this .properties );
101+ }
102+
103+ @ Override
104+ @ SuppressWarnings ("HiddenField" )
105+ public FetchableFluentQuery <R > limit (int limit ) {
106+ return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .mappingContext , this .findOperation ,
107+ this .countOperation , this .existsOperation , this .sort , limit , this .properties );
94108 }
95109
96110 @ Override
@@ -106,15 +120,15 @@ public <NR> FetchableFluentQuery<NR> as(Class<NR> resultType) {
106120 public FetchableFluentQuery <R > project (Collection <String > properties ) {
107121
108122 return new FetchableFluentQueryByExample <>(this .example , this .resultType , this .mappingContext , this .findOperation ,
109- this .countOperation , this .existsOperation , this .sort , mergeProperties (properties ));
123+ this .countOperation , this .existsOperation , this .sort , this . limit , mergeProperties (properties ));
110124 }
111125
112126 @ Override
113127 public R oneValue () {
114128
115129 return findOperation .find (example .getProbeType ())
116130 .as (resultType )
117- .matching (QueryFragmentsAndParameters .forExample (mappingContext , example , sort ,
131+ .matching (QueryFragmentsAndParameters .forExampleWithSort (mappingContext , example , sort , limit ,
118132 createIncludedFieldsPredicate ()))
119133 .oneValue ();
120134 }
@@ -131,7 +145,7 @@ public List<R> all() {
131145
132146 return findOperation .find (example .getProbeType ())
133147 .as (resultType )
134- .matching (QueryFragmentsAndParameters .forExample (mappingContext , example , sort ,
148+ .matching (QueryFragmentsAndParameters .forExampleWithSort (mappingContext , example , sort , limit ,
135149 createIncludedFieldsPredicate ()))
136150 .all ();
137151 }
@@ -141,14 +155,36 @@ public Page<R> page(Pageable pageable) {
141155
142156 List <R > page = findOperation .find (example .getProbeType ())
143157 .as (resultType )
144- .matching (QueryFragmentsAndParameters .forExample (mappingContext , example , pageable ,
158+ .matching (QueryFragmentsAndParameters .forExampleWithPageable (mappingContext , example , pageable ,
145159 createIncludedFieldsPredicate ()))
146160 .all ();
147161
148162 LongSupplier totalCountSupplier = this ::count ;
149163 return PageableExecutionUtils .getPage (page , pageable , totalCountSupplier );
150164 }
151165
166+ @ Override
167+ public Window <R > scroll (ScrollPosition scrollPosition ) {
168+ Class <S > domainType = this .example .getProbeType ();
169+ Neo4jPersistentEntity <?> entity = mappingContext .getPersistentEntity (domainType );
170+
171+ var skip = scrollPosition .isInitial ()
172+ ? 0
173+ : (scrollPosition instanceof OffsetScrollPosition offsetScrollPosition ) ? offsetScrollPosition .getOffset ()
174+ : 0 ;
175+
176+ Condition condition = scrollPosition instanceof KeysetScrollPosition keysetScrollPosition
177+ ? CypherAdapterUtils .combineKeysetIntoCondition (mappingContext .getPersistentEntity (example .getProbeType ()), keysetScrollPosition , sort , mappingContext .getConversionService ())
178+ : null ;
179+
180+ List <R > rawResult = findOperation .find (domainType )
181+ .as (resultType )
182+ .matching (QueryFragmentsAndParameters .forExampleWithScrollPosition (mappingContext , example , condition , sort , limit == null ? 1 : limit + 1 , skip , scrollPosition , createIncludedFieldsPredicate ()))
183+ .all ();
184+
185+ return scroll (scrollPosition , rawResult , entity );
186+ }
187+
152188 @ Override
153189 public Stream <R > stream () {
154190 return all ().stream ();
0 commit comments