1 /*
2 * Copyright 2008-2020 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.jpa.domain;
17
18 import java.io.Serializable;
19
20 import javax.persistence.criteria.CriteriaBuilder;
21 import javax.persistence.criteria.CriteriaQuery;
22 import javax.persistence.criteria.Predicate;
23 import javax.persistence.criteria.Root;
24
25 import org.springframework.lang.Nullable;
26
27 /**
28 * Specification in the sense of Domain Driven Design.
29 *
30 * @author Oliver Gierke
31 * @author Thomas Darimont
32 * @author Krzysztof Rzymkowski
33 * @author Sebastian Staudt
34 * @author Mark Paluch
35 * @author Jens Schauder
36 */
37 public interface Specification<T> extends Serializable {
38
39 long serialVersionUID = 1L;
40
41 /**
42 * Negates the given {@link Specification}.
43 *
44 * @param <T> the type of the {@link Root} the resulting {@literal Specification} operates on.
45 * @param spec can be {@literal null}.
46 * @return guaranteed to be not {@literal null}.
47 * @since 2.0
48 */
49 static <T> Specification<T> not(@Nullable Specification<T> spec) {
50
51 return spec == null //
52 ? (root, query, builder) -> null //
53 : (root, query, builder) -> builder.not(spec.toPredicate(root, query, builder));
54 }
55
56 /**
57 * Simple static factory method to add some syntactic sugar around a {@link Specification}.
58 *
59 * @param <T> the type of the {@link Root} the resulting {@literal Specification} operates on.
60 * @param spec can be {@literal null}.
61 * @return guaranteed to be not {@literal null}.
62 * @since 2.0
63 */
64 static <T> Specification<T> where(@Nullable Specification<T> spec) {
65 return spec == null ? (root, query, builder) -> null : spec;
66 }
67
68 /**
69 * ANDs the given {@link Specification} to the current one.
70 *
71 * @param other can be {@literal null}.
72 * @return The conjunction of the specifications
73 * @since 2.0
74 */
75 default Specification<T> and(@Nullable Specification<T> other) {
76 return SpecificationComposition.composed(this, other, CriteriaBuilder::and);
77 }
78
79 /**
80 * ORs the given specification to the current one.
81 *
82 * @param other can be {@literal null}.
83 * @return The disjunction of the specifications
84 * @since 2.0
85 */
86 default Specification<T> or(@Nullable Specification<T> other) {
87 return SpecificationComposition.composed(this, other, CriteriaBuilder::or);
88 }
89
90 /**
91 * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
92 * {@link Root} and {@link CriteriaQuery}.
93 *
94 * @param root must not be {@literal null}.
95 * @param query must not be {@literal null}.
96 * @param criteriaBuilder must not be {@literal null}.
97 * @return a {@link Predicate}, may be {@literal null}.
98 */
99 @Nullable
100 Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);
101 }
102