Skip to content

Commit

Permalink
GH-2726 - Provide conversion service in FluentQuery...
Browse files Browse the repository at this point in the history
  • Loading branch information
meistermeier committed Jun 7, 2023
1 parent 1e6e62c commit 14665e1
Show file tree
Hide file tree
Showing 12 changed files with 204 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
package org.springframework.data.neo4j.repository.query;

import org.apiguardian.api.API;
import org.neo4j.cypherdsl.core.Condition;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
Expand Down Expand Up @@ -171,9 +173,13 @@ public Window<R> scroll(ScrollPosition scrollPosition) {
: (scrollPosition instanceof OffsetScrollPosition offsetScrollPosition) ? offsetScrollPosition.getOffset()
: 0;

Condition condition = scrollPosition instanceof KeysetScrollPosition keysetScrollPosition
? CypherAdapterUtils.combineKeysetIntoCondition(mappingContext.getPersistentEntity(example.getProbeType()), keysetScrollPosition, sort, mappingContext.getConversionService())
: null;

List<R> rawResult = findOperation.find(domainType)
.as(resultType)
.matching(QueryFragmentsAndParameters.forExampleWithScroll(mappingContext, example, sort, limit == null ? 1 : limit + 1, skip, scrollPosition, createIncludedFieldsPredicate()))
.matching(QueryFragmentsAndParameters.forExampleWithScroll(mappingContext, example, condition, sort, limit == null ? 1 : limit + 1, skip, scrollPosition, createIncludedFieldsPredicate()))
.all();

return scroll(scrollPosition, rawResult, entity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@

import org.apiguardian.api.API;
import org.neo4j.cypherdsl.core.Cypher;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Window;
import org.springframework.data.neo4j.core.FluentFindOperation;
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.core.mapping.Neo4jPersistentEntity;
import org.springframework.data.repository.query.FluentQuery.FetchableFluentQuery;
import org.springframework.data.support.PageableExecutionUtils;
Expand Down Expand Up @@ -60,19 +62,23 @@ final class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<R>

private final Function<Predicate, Boolean> existsOperation;

private final Neo4jMappingContext mappingContext;

FetchableFluentQueryByPredicate(
Predicate predicate,
Neo4jMappingContext mappingContext,
Neo4jPersistentEntity<S> metaData,
Class<R> resultType,
FluentFindOperation findOperation,
Function<Predicate, Long> countOperation,
Function<Predicate, Boolean> existsOperation
) {
this(predicate, metaData, resultType, findOperation, countOperation, existsOperation, Sort.unsorted(), null, null);
this(predicate, mappingContext, metaData, resultType, findOperation, countOperation, existsOperation, Sort.unsorted(), null, null);
}

FetchableFluentQueryByPredicate(
Predicate predicate,
Neo4jMappingContext mappingContext,
Neo4jPersistentEntity<S> metaData,
Class<R> resultType,
FluentFindOperation findOperation,
Expand All @@ -84,6 +90,7 @@ final class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<R>
) {
super(resultType, sort, limit, properties);
this.predicate = predicate;
this.mappingContext = mappingContext;
this.metaData = metaData;
this.findOperation = findOperation;
this.countOperation = countOperation;
Expand All @@ -94,30 +101,30 @@ final class FetchableFluentQueryByPredicate<S, R> extends FluentQuerySupport<R>
@SuppressWarnings("HiddenField")
public FetchableFluentQuery<R> sortBy(Sort sort) {

return new FetchableFluentQueryByPredicate<>(this.predicate, this.metaData, this.resultType, this.findOperation,
return new FetchableFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, this.resultType, this.findOperation,
this.countOperation, this.existsOperation, this.sort.and(sort), this.limit, this.properties);
}

@Override
@SuppressWarnings("HiddenField")
public FetchableFluentQuery<R> limit(int limit) {
return new FetchableFluentQueryByPredicate<>(this.predicate, this.metaData, this.resultType, this.findOperation,
return new FetchableFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, this.resultType, this.findOperation,
this.countOperation, this.existsOperation, this.sort, limit, this.properties);
}

@Override
@SuppressWarnings("HiddenField")
public <NR> FetchableFluentQuery<NR> as(Class<NR> resultType) {

return new FetchableFluentQueryByPredicate<>(this.predicate, this.metaData, resultType, this.findOperation,
return new FetchableFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, resultType, this.findOperation,
this.countOperation, this.existsOperation);
}

@Override
@SuppressWarnings("HiddenField")
public FetchableFluentQuery<R> project(Collection<String> properties) {

return new FetchableFluentQueryByPredicate<>(this.predicate, this.metaData, this.resultType, this.findOperation,
return new FetchableFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, this.resultType, this.findOperation,
this.countOperation, this.existsOperation, this.sort, this.limit, mergeProperties(properties));
}

Expand Down Expand Up @@ -176,10 +183,13 @@ public Page<R> page(Pageable pageable) {
public Window<R> scroll(ScrollPosition scrollPosition) {

QueryFragmentsAndParameters queryFragmentsAndParameters = QueryFragmentsAndParameters.forConditionWithScrollPosition(metaData,
Cypher.adapt(predicate).asCondition(),
scrollPosition, sort,
limit == null ? 1 : limit + 1,
createIncludedFieldsPredicate());
Cypher.adapt(predicate).asCondition(),
(scrollPosition instanceof KeysetScrollPosition keysetScrollPosition
? CypherAdapterUtils.combineKeysetIntoCondition(metaData, keysetScrollPosition, sort, mappingContext.getConversionService())
: null),
scrollPosition, sort,
limit == null ? 1 : limit + 1,
createIncludedFieldsPredicate());

List<R> rawResult = findOperation.find(metaData.getType())
.as(resultType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
import java.util.stream.Collectors;

import org.apache.commons.logging.LogFactory;
import org.neo4j.driver.Value;
import org.neo4j.driver.Values;
import org.neo4j.driver.types.MapAccessor;
import org.neo4j.driver.types.TypeSystem;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,23 +192,23 @@ static QueryFragmentsAndParameters forExample(Neo4jMappingContext mappingContext
}

static QueryFragmentsAndParameters forExample(Neo4jMappingContext mappingContext, Example<?> example, Sort sort, @Nullable Integer limit, @Nullable java.util.function.Predicate<PropertyFilter.RelaxedPropertyPath> includeField) {
return QueryFragmentsAndParameters.forExample(mappingContext, example, null, sort, limit, null, null, includeField);
return QueryFragmentsAndParameters.forExample(mappingContext, example, null, null, sort, limit, null, null, includeField);
}

static QueryFragmentsAndParameters forExample(Neo4jMappingContext mappingContext, Example<?> example, Sort sort, @Nullable Integer limit, @Nullable Long skip, @Nullable java.util.function.Predicate<PropertyFilter.RelaxedPropertyPath> includeField) {
return QueryFragmentsAndParameters.forExample(mappingContext, example, null, sort, limit, skip, null, includeField);
return QueryFragmentsAndParameters.forExample(mappingContext, example, null, null, sort, limit, skip, null, includeField);
}

static QueryFragmentsAndParameters forExampleWithScroll(Neo4jMappingContext mappingContext, Example<?> example, Sort sort, @Nullable Integer limit, @Nullable Long skip, ScrollPosition scrollPosition, @Nullable java.util.function.Predicate<PropertyFilter.RelaxedPropertyPath> includeField) {
return QueryFragmentsAndParameters.forExample(mappingContext, example, null, sort, limit, skip, scrollPosition, includeField);
static QueryFragmentsAndParameters forExampleWithScroll(Neo4jMappingContext mappingContext, Example<?> example, @Nullable Condition keysetScrollPositionCondition, Sort sort, @Nullable Integer limit, @Nullable Long skip, ScrollPosition scrollPosition, @Nullable java.util.function.Predicate<PropertyFilter.RelaxedPropertyPath> includeField) {
return QueryFragmentsAndParameters.forExample(mappingContext, example, keysetScrollPositionCondition, null, sort, limit, skip, scrollPosition, includeField);
}

static QueryFragmentsAndParameters forExample(Neo4jMappingContext mappingContext, Example<?> example, Pageable pageable) {
return QueryFragmentsAndParameters.forExample(mappingContext, example, pageable, null);
}

static QueryFragmentsAndParameters forExample(Neo4jMappingContext mappingContext, Example<?> example, Pageable pageable, @Nullable java.util.function.Predicate<PropertyFilter.RelaxedPropertyPath> includeField) {
return QueryFragmentsAndParameters.forExample(mappingContext, example, pageable, null, null, null, null, includeField);
return QueryFragmentsAndParameters.forExample(mappingContext, example, null, pageable, null, null, null, null, includeField);
}

/**
Expand Down Expand Up @@ -257,6 +257,7 @@ static QueryFragmentsAndParameters forCondition(Neo4jPersistentEntity<?> entityM

static QueryFragmentsAndParameters forConditionWithScrollPosition(Neo4jPersistentEntity<?> entityMetaData,
Condition condition,
@Nullable Condition keysetCondition,
ScrollPosition scrollPosition,
@Nullable Sort sort,
@Nullable Integer limit,
Expand All @@ -274,7 +275,7 @@ static QueryFragmentsAndParameters forConditionWithScrollPosition(Neo4jPersisten

if (scrollPosition instanceof KeysetScrollPosition keysetScrollPosition) {
if (!scrollPosition.isInitial()) {
condition = condition.and(CypherAdapterUtils.combineKeysetIntoCondition(entityMetaData, keysetScrollPosition, sort));
condition = condition.and(keysetCondition);
}
QueryFragmentsAndParameters queryFragmentsAndParameters = getQueryFragmentsAndParameters(entityMetaData, null,
sort, limit, skip, Collections.emptyMap(), condition, includeField, null);
Expand Down Expand Up @@ -312,6 +313,7 @@ private static void adaptPageable(
}

static QueryFragmentsAndParameters forExample(Neo4jMappingContext mappingContext, Example<?> example,
@Nullable Condition keysetScrollPositionCondition,
@Nullable Pageable pageable, @Nullable Sort sort, @Nullable Integer limit,
@Nullable Long skip, @Nullable ScrollPosition scrollPosition,
java.util.function.Predicate<PropertyFilter.RelaxedPropertyPath> includeField) {
Expand All @@ -324,7 +326,7 @@ static QueryFragmentsAndParameters forExample(Neo4jMappingContext mappingContext
if (scrollPosition instanceof KeysetScrollPosition keysetScrollPosition) {

if (!keysetScrollPosition.isInitial()) {
condition = condition.and(CypherAdapterUtils.combineKeysetIntoCondition(persistentEntity, keysetScrollPosition, sort));
condition = condition.and(keysetScrollPositionCondition);
}
QueryFragmentsAndParameters queryFragmentsAndParameters = getQueryFragmentsAndParameters(persistentEntity, pageable,
sort, limit, skip, parameters, condition, includeField, propertyPathWrappers);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import org.springframework.data.domain.Sort;
import org.springframework.data.neo4j.core.FluentFindOperation;
import org.springframework.data.neo4j.core.Neo4jOperations;
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.core.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.repository.support.CypherdslConditionExecutor;
import org.springframework.data.neo4j.repository.support.Neo4jEntityInformation;
Expand Down Expand Up @@ -65,9 +66,15 @@ public final class QuerydslNeo4jPredicateExecutor<T> implements QuerydslPredicat
*/
private final Neo4jPersistentEntity<T> metaData;

public QuerydslNeo4jPredicateExecutor(Neo4jEntityInformation<T, Object> entityInformation,
Neo4jOperations neo4jOperations) {
/**
* Mapping context
*/
private final Neo4jMappingContext mappingContext;

public QuerydslNeo4jPredicateExecutor(Neo4jMappingContext mappingContext, Neo4jEntityInformation<T, Object> entityInformation,
Neo4jOperations neo4jOperations) {

this.mappingContext = mappingContext;
this.delegate = new CypherdslConditionExecutorImpl<>(entityInformation, neo4jOperations);
this.neo4jOperations = neo4jOperations;
this.metaData = entityInformation.getEntityMetaData();
Expand Down Expand Up @@ -134,7 +141,7 @@ public <S extends T, R> R findBy(Predicate predicate, Function<FetchableFluentQu
if (this.neo4jOperations instanceof FluentFindOperation ops) {
@SuppressWarnings("unchecked") // defaultResultType will be a supertype of S and at this stage, the same.
FetchableFluentQuery<S> fluentQuery =
(FetchableFluentQuery<S>) new FetchableFluentQueryByPredicate<>(predicate, metaData, metaData.getType(),
(FetchableFluentQuery<S>) new FetchableFluentQueryByPredicate<>(predicate, mappingContext, metaData, metaData.getType(),
ops, this::count, this::exists);
return queryFunction.apply(fluentQuery);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.springframework.data.neo4j.repository.query;

import org.neo4j.cypherdsl.core.Condition;
import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.OffsetScrollPosition;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Window;
Expand Down Expand Up @@ -172,9 +174,13 @@ public Mono<Window<R>> scroll(ScrollPosition scrollPosition) {
: (scrollPosition instanceof OffsetScrollPosition offsetScrollPosition) ? offsetScrollPosition.getOffset()
: 0;

Condition condition = scrollPosition instanceof KeysetScrollPosition keysetScrollPosition
? CypherAdapterUtils.combineKeysetIntoCondition(mappingContext.getPersistentEntity(example.getProbeType()), keysetScrollPosition, sort, mappingContext.getConversionService())
: null;

return findOperation.find(domainType)
.as(resultType)
.matching(QueryFragmentsAndParameters.forExampleWithScroll(mappingContext, example, sort, limit == null ? 1 : limit + 1, skip, scrollPosition, createIncludedFieldsPredicate()))
.matching(QueryFragmentsAndParameters.forExampleWithScroll(mappingContext, example, condition, sort, limit == null ? 1 : limit + 1, skip, scrollPosition, createIncludedFieldsPredicate()))
.all()
.collectList()
.map(rawResult -> scroll(scrollPosition, rawResult, entity));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
*/
package org.springframework.data.neo4j.repository.query;

import org.springframework.data.domain.KeysetScrollPosition;
import org.springframework.data.domain.ScrollPosition;
import org.springframework.data.domain.Window;
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand Down Expand Up @@ -59,19 +61,23 @@

private final Function<Predicate, Mono<Boolean>> existsOperation;

private final Neo4jMappingContext mappingContext;

ReactiveFluentQueryByPredicate(
Predicate predicate,
Neo4jMappingContext mappingContext,
Neo4jPersistentEntity<S> metaData,
Class<R> resultType,
ReactiveFluentFindOperation findOperation,
Function<Predicate, Mono<Long>> countOperation,
Function<Predicate, Mono<Boolean>> existsOperation
) {
this(predicate, metaData, resultType, findOperation, countOperation, existsOperation, Sort.unsorted(), null, null);
this(predicate, mappingContext, metaData, resultType, findOperation, countOperation, existsOperation, Sort.unsorted(), null, null);
}

ReactiveFluentQueryByPredicate(
Predicate predicate,
Neo4jMappingContext mappingContext,
Neo4jPersistentEntity<S> metaData,
Class<R> resultType,
ReactiveFluentFindOperation findOperation,
Expand All @@ -83,6 +89,7 @@
) {
super(resultType, sort, limit, properties);
this.predicate = predicate;
this.mappingContext = mappingContext;
this.metaData = metaData;
this.findOperation = findOperation;
this.countOperation = countOperation;
Expand All @@ -93,30 +100,30 @@
@SuppressWarnings("HiddenField")
public ReactiveFluentQuery<R> sortBy(Sort sort) {

return new ReactiveFluentQueryByPredicate<>(this.predicate, this.metaData, this.resultType, this.findOperation,
return new ReactiveFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, this.resultType, this.findOperation,
this.countOperation, this.existsOperation, this.sort.and(sort), this.limit, this.properties);
}

@Override
@SuppressWarnings("HiddenField")
public ReactiveFluentQuery<R> limit(int limit) {
return new ReactiveFluentQueryByPredicate<>(this.predicate, this.metaData, this.resultType, this.findOperation,
return new ReactiveFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, this.resultType, this.findOperation,
this.countOperation, this.existsOperation, this.sort, limit, this.properties);
}

@Override
@SuppressWarnings("HiddenField")
public <NR> ReactiveFluentQuery<NR> as(Class<NR> resultType) {

return new ReactiveFluentQueryByPredicate<>(this.predicate, this.metaData, resultType, this.findOperation,
return new ReactiveFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, resultType, this.findOperation,
this.countOperation, this.existsOperation);
}

@Override
@SuppressWarnings("HiddenField")
public ReactiveFluentQuery<R> project(Collection<String> properties) {

return new ReactiveFluentQueryByPredicate<>(this.predicate, this.metaData, resultType, this.findOperation,
return new ReactiveFluentQueryByPredicate<>(this.predicate, this.mappingContext, this.metaData, resultType, this.findOperation,
this.countOperation, this.existsOperation, this.sort, this.limit, mergeProperties(properties));
}

Expand Down Expand Up @@ -174,6 +181,9 @@ public Mono<Page<R>> page(Pageable pageable) {
public Mono<Window<R>> scroll(ScrollPosition scrollPosition) {
QueryFragmentsAndParameters queryFragmentsAndParameters = QueryFragmentsAndParameters.forConditionWithScrollPosition(metaData,
Cypher.adapt(predicate).asCondition(),
(scrollPosition instanceof KeysetScrollPosition keysetScrollPosition
? CypherAdapterUtils.combineKeysetIntoCondition(metaData, keysetScrollPosition, sort, mappingContext.getConversionService())
: null),
scrollPosition, sort,
limit == null ? 1 : limit + 1,
createIncludedFieldsPredicate());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

import static org.neo4j.cypherdsl.core.Cypher.asterisk;

import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

Expand Down Expand Up @@ -63,9 +64,15 @@ public final class ReactiveQuerydslNeo4jPredicateExecutor<T> implements Reactive

private final Neo4jPersistentEntity<T> metaData;

public ReactiveQuerydslNeo4jPredicateExecutor(Neo4jEntityInformation<T, Object> entityInformation,
/**
* Mapping context
*/
private final Neo4jMappingContext mappingContext;

public ReactiveQuerydslNeo4jPredicateExecutor(Neo4jMappingContext mappingContext, Neo4jEntityInformation<T, Object> entityInformation,
ReactiveNeo4jOperations neo4jOperations) {

this.mappingContext = mappingContext;
this.entityInformation = entityInformation;
this.neo4jOperations = neo4jOperations;
this.metaData = this.entityInformation.getEntityMetaData();
Expand Down Expand Up @@ -131,7 +138,7 @@ public <S extends T, R, P extends Publisher<R>> P findBy(Predicate predicate, Fu

if (this.neo4jOperations instanceof ReactiveFluentFindOperation ops) {
@SuppressWarnings("unchecked") // defaultResultType will be a supertype of S and at this stage, the same.
ReactiveFluentQuery<S> fluentQuery = (ReactiveFluentQuery<S>) new ReactiveFluentQueryByPredicate<>(predicate, metaData, metaData.getType(),
ReactiveFluentQuery<S> fluentQuery = (ReactiveFluentQuery<S>) new ReactiveFluentQueryByPredicate<>(predicate, mappingContext, metaData, metaData.getType(),
ops, this::count, this::exists);
return queryFunction.apply(fluentQuery);
}
Expand Down

0 comments on commit 14665e1

Please sign in to comment.