Skip to content

Commit eb818ef

Browse files
committed
test implement ReactiveCypherdslConditionExecutor
1 parent 2b06d45 commit eb818ef

File tree

4 files changed

+394
-3
lines changed

4 files changed

+394
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
/*
2+
* Copyright 2011-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.repository.query;
17+
18+
import static org.neo4j.cypherdsl.core.Cypher.asterisk;
19+
20+
import java.util.Arrays;
21+
import java.util.Collection;
22+
import java.util.List;
23+
import java.util.Optional;
24+
import java.util.function.LongSupplier;
25+
26+
import org.apiguardian.api.API;
27+
import org.neo4j.cypherdsl.core.Condition;
28+
import org.neo4j.cypherdsl.core.Conditions;
29+
import org.neo4j.cypherdsl.core.Functions;
30+
import org.neo4j.cypherdsl.core.SortItem;
31+
import org.neo4j.cypherdsl.core.Statement;
32+
import org.springframework.data.domain.Page;
33+
import org.springframework.data.domain.Pageable;
34+
import org.springframework.data.domain.Sort;
35+
import org.springframework.data.neo4j.core.ReactiveNeo4jOperations;
36+
import org.springframework.data.neo4j.core.mapping.CypherGenerator;
37+
import org.springframework.data.neo4j.core.mapping.Neo4jPersistentEntity;
38+
import org.springframework.data.neo4j.repository.support.ReactiveCypherdslConditionExecutor;
39+
import org.springframework.data.neo4j.repository.support.Neo4jEntityInformation;
40+
41+
import reactor.core.publisher.Flux;
42+
import reactor.core.publisher.Mono;
43+
44+
/**
45+
* @author Michael J. Simons
46+
* @param <T> The returned domain type.
47+
* @since 6.1
48+
*/
49+
@API(status = API.Status.INTERNAL, since = "6.1")
50+
public final class ReactiveCypherdslConditionExecutorImpl<T> implements ReactiveCypherdslConditionExecutor<T> {
51+
52+
private final Neo4jEntityInformation<T, Object> entityInformation;
53+
54+
private final ReactiveNeo4jOperations neo4jOperations;
55+
56+
private final Neo4jPersistentEntity<T> metaData;
57+
58+
public ReactiveCypherdslConditionExecutorImpl(Neo4jEntityInformation<T, Object> entityInformation,
59+
ReactiveNeo4jOperations neo4jOperations) {
60+
61+
this.entityInformation = entityInformation;
62+
this.neo4jOperations = neo4jOperations;
63+
this.metaData = this.entityInformation.getEntityMetaData();
64+
}
65+
66+
@Override
67+
public Mono<T> findOne(Condition condition) {
68+
69+
return this.neo4jOperations.toExecutableQuery(
70+
this.metaData.getType(),
71+
QueryFragmentsAndParameters.forCondition(this.metaData, condition, null, null)
72+
).flatMap(q -> q.getSingleResult());
73+
}
74+
75+
@Override
76+
public Flux<T> findAll(Condition condition) {
77+
78+
return this.neo4jOperations.toExecutableQuery(
79+
this.metaData.getType(),
80+
QueryFragmentsAndParameters.forCondition(this.metaData, condition, null, null)
81+
).flatMapMany(q -> q.getResults());
82+
}
83+
84+
@Override
85+
public Flux<T> findAll(Condition condition, Sort sort) {
86+
87+
return this.neo4jOperations.toExecutableQuery(
88+
metaData.getType(),
89+
QueryFragmentsAndParameters.forCondition(
90+
this.metaData, condition, null, CypherAdapterUtils.toSortItems(this.metaData, sort)
91+
)
92+
).flatMapMany(q -> q.getResults());
93+
}
94+
95+
@Override
96+
public Flux<T> findAll(Condition condition, SortItem... sortItems) {
97+
98+
return this.neo4jOperations.toExecutableQuery(
99+
this.metaData.getType(),
100+
QueryFragmentsAndParameters.forCondition(
101+
this.metaData, condition, null, Arrays.asList(sortItems)
102+
)
103+
).flatMapMany(q -> q.getResults());
104+
}
105+
106+
@Override
107+
public Flux<T> findAll(SortItem... sortItems) {
108+
109+
return this.neo4jOperations.toExecutableQuery(
110+
this.metaData.getType(),
111+
QueryFragmentsAndParameters.forCondition(this.metaData, Conditions.noCondition(), null, Arrays.asList(sortItems))
112+
).flatMapMany(q -> q.getResults());
113+
}
114+
115+
@Override
116+
public Mono<Long> count(Condition condition) {
117+
118+
Statement statement = CypherGenerator.INSTANCE.prepareMatchOf(this.metaData, condition)
119+
.returning(Functions.count(asterisk())).build();
120+
return this.neo4jOperations.count(statement, statement.getParameters());
121+
}
122+
123+
@Override
124+
public Mono<Boolean> exists(Condition condition) {
125+
Statement statement = CypherGenerator.INSTANCE.prepareMatchOf(this.metaData, condition)
126+
.returning(Functions.count(asterisk())).build();
127+
return this.neo4jOperations.count(statement, statement.getParameters()).map(count -> count > 0);
128+
}
129+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2011-2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.neo4j.repository.support;
17+
18+
import org.apiguardian.api.API;
19+
import org.neo4j.cypherdsl.core.Condition;
20+
import org.neo4j.cypherdsl.core.SortItem;
21+
import org.springframework.data.domain.Sort;
22+
23+
import reactor.core.publisher.Flux;
24+
import reactor.core.publisher.Mono;
25+
26+
/**
27+
* An interface that can be added to any repository so that queries can be enriched by {@link Condition conditions} of the
28+
* Cypher-DSL. This interface behaves the same as the {@link org.springframework.data.querydsl.QuerydslPredicateExecutor}.
29+
*
30+
* @author Michael J. Simons
31+
* @param <T> Type of the domain
32+
* @since 6.1
33+
*/
34+
@API(status = API.Status.STABLE, since = "6.1")
35+
public interface ReactiveCypherdslConditionExecutor<T> {
36+
37+
Mono<T> findOne(Condition condition);
38+
39+
Flux<T> findAll(Condition condition);
40+
41+
Flux<T> findAll(Condition condition, Sort sort);
42+
43+
Flux<T> findAll(Condition condition, SortItem... sortItems);
44+
45+
Flux<T> findAll(SortItem... sortItems);
46+
47+
Mono<Long> count(Condition condition);
48+
49+
Mono<Boolean> exists(Condition condition);
50+
}
51+

src/main/java/org/springframework/data/neo4j/repository/support/ReactiveNeo4jRepositoryFactory.java

+6-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@
2424
import org.springframework.data.neo4j.core.mapping.Neo4jMappingContext;
2525
import org.springframework.data.neo4j.core.mapping.Neo4jPersistentEntity;
2626
import org.springframework.data.neo4j.repository.ReactiveNeo4jRepository;
27-
import org.springframework.data.neo4j.repository.query.ReactiveNeo4jQueryLookupStrategy;
28-
import org.springframework.data.neo4j.repository.query.ReactiveQuerydslNeo4jPredicateExecutor;
29-
import org.springframework.data.neo4j.repository.query.SimpleReactiveQueryByExampleExecutor;
27+
import org.springframework.data.neo4j.repository.query.*;
3028
import org.springframework.data.projection.ProjectionFactory;
3129
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
3230
import org.springframework.data.querydsl.QuerydslUtils;
@@ -93,6 +91,11 @@ protected RepositoryFragments getRepositoryFragments(RepositoryMetadata metadata
9391
fragments = fragments.append(createDSLExecutorFragment(metadata, ReactiveQuerydslNeo4jPredicateExecutor.class));
9492
}
9593

94+
if (ReactiveCypherdslConditionExecutor.class.isAssignableFrom(metadata.getRepositoryInterface())) {
95+
96+
fragments = fragments.append(createDSLExecutorFragment(metadata, ReactiveCypherdslConditionExecutorImpl.class));
97+
}
98+
9699
return fragments;
97100
}
98101

0 commit comments

Comments
 (0)