Skip to content

Commit

Permalink
Address review findings.
Browse files Browse the repository at this point in the history
  • Loading branch information
mp911de committed Jan 8, 2025
1 parent e88a895 commit 490eef0
Show file tree
Hide file tree
Showing 11 changed files with 105 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@

/**
* Specification in the sense of Domain Driven Design to handle Criteria Deletes.
* <p>
* Specifications can be composed into higher order functions from other specifications using
* {@link #and(DeleteSpecification)}, {@link #or(DeleteSpecification)} or factory methods such as
* {@link #allOf(Iterable)}. Composition considers whether one or more specifications contribute to the overall
* predicate by returning a {@link Predicate} or {@literal null}. Specifications returning {@literal null} are
* considered to not contribute to the overall predicate and their result is not considered in the final predicate.
*
* @author Mark Paluch
* @since 4.0
Expand All @@ -44,7 +50,7 @@ public interface DeleteSpecification<T> extends Serializable {
* @param <T> the type of the {@link Root} the resulting {@literal DeleteSpecification} operates on.
* @return guaranteed to be not {@literal null}.
*/
static <T> DeleteSpecification<T> all() {
static <T> DeleteSpecification<T> unrestricted() {
return (root, query, builder) -> null;
}

Expand Down Expand Up @@ -150,13 +156,14 @@ static <T> DeleteSpecification<T> not(DeleteSpecification<T> spec) {

return (root, delete, builder) -> {

Predicate not = spec.toPredicate(root, delete, builder);
return not != null ? builder.not(not) : null;
Predicate predicate = spec.toPredicate(root, delete, builder);
return predicate != null ? builder.not(predicate) : null;
};
}

/**
* Applies an AND operation to all the given {@link DeleteSpecification}s.
* Applies an AND operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
* resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -169,7 +176,8 @@ static <T> DeleteSpecification<T> allOf(DeleteSpecification<T>... specifications
}

/**
* Applies an AND operation to all the given {@link DeleteSpecification}s.
* Applies an AND operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
* resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -179,11 +187,12 @@ static <T> DeleteSpecification<T> allOf(DeleteSpecification<T>... specifications
static <T> DeleteSpecification<T> allOf(Iterable<DeleteSpecification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(DeleteSpecification.all(), DeleteSpecification::and);
.reduce(DeleteSpecification.unrestricted(), DeleteSpecification::and);
}

/**
* Applies an OR operation to all the given {@link DeleteSpecification}s.
* Applies an OR operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
* resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the disjunction of the specifications.
Expand All @@ -196,7 +205,8 @@ static <T> DeleteSpecification<T> anyOf(DeleteSpecification<T>... specifications
}

/**
* Applies an OR operation to all the given {@link DeleteSpecification}s.
* Applies an OR operation to all the given {@link DeleteSpecification}s. If {@code specifications} is empty, the
* resulting {@link DeleteSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link DeleteSpecification}s to compose.
* @return the disjunction of the specifications.
Expand All @@ -206,7 +216,7 @@ static <T> DeleteSpecification<T> anyOf(DeleteSpecification<T>... specifications
static <T> DeleteSpecification<T> anyOf(Iterable<DeleteSpecification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(DeleteSpecification.all(), DeleteSpecification::or);
.reduce(DeleteSpecification.unrestricted(), DeleteSpecification::or);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@

/**
* Specification in the sense of Domain Driven Design.
* <p>
* Specifications can be composed into higher order functions from other specifications using
* {@link #and(PredicateSpecification)}, {@link #or(PredicateSpecification)} or factory methods such as
* {@link #allOf(Iterable)}. Composition considers whether one or more specifications contribute to the overall
* predicate by returning a {@link Predicate} or {@literal null}. Specifications returning {@literal null} are
* considered to not contribute to the overall predicate and their result is not considered in the final predicate.
*
* @author Mark Paluch
* @since 4.0
Expand All @@ -42,7 +48,7 @@ public interface PredicateSpecification<T> extends Serializable {
* @param <T> the type of the {@link Root} the resulting {@literal PredicateSpecification} operates on.
* @return guaranteed to be not {@literal null}.
*/
static <T> PredicateSpecification<T> all() {
static <T> PredicateSpecification<T> unrestricted() {
return (root, builder) -> null;
}

Expand Down Expand Up @@ -104,13 +110,14 @@ static <T> PredicateSpecification<T> not(PredicateSpecification<T> spec) {

return (root, builder) -> {

Predicate not = spec.toPredicate(root, builder);
return not != null ? builder.not(not) : null;
Predicate predicate = spec.toPredicate(root, builder);
return predicate != null ? builder.not(predicate) : null;
};
}

/**
* Applies an AND operation to all the given {@link PredicateSpecification}s.
* Applies an AND operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
* resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -123,7 +130,8 @@ static <T> PredicateSpecification<T> allOf(PredicateSpecification<T>... specific
}

/**
* Applies an AND operation to all the given {@link PredicateSpecification}s.
* Applies an AND operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
* resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -133,11 +141,12 @@ static <T> PredicateSpecification<T> allOf(PredicateSpecification<T>... specific
static <T> PredicateSpecification<T> allOf(Iterable<PredicateSpecification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(PredicateSpecification.all(), PredicateSpecification::and);
.reduce(PredicateSpecification.unrestricted(), PredicateSpecification::and);
}

/**
* Applies an OR operation to all the given {@link PredicateSpecification}s.
* Applies an OR operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
* resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the disjunction of the specifications.
Expand All @@ -150,7 +159,8 @@ static <T> PredicateSpecification<T> anyOf(PredicateSpecification<T>... specific
}

/**
* Applies an OR operation to all the given {@link PredicateSpecification}s.
* Applies an OR operation to all the given {@link PredicateSpecification}s. If {@code specifications} is empty, the
* resulting {@link PredicateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link PredicateSpecification}s to compose.
* @return the disjunction of the specifications.
Expand All @@ -160,7 +170,7 @@ static <T> PredicateSpecification<T> anyOf(PredicateSpecification<T>... specific
static <T> PredicateSpecification<T> anyOf(Iterable<PredicateSpecification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(PredicateSpecification.all(), PredicateSpecification::or);
.reduce(PredicateSpecification.unrestricted(), PredicateSpecification::or);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@

/**
* Specification in the sense of Domain Driven Design.
* <p>
* Specifications can be composed into higher order functions from other specifications using
* {@link #and(Specification)}, {@link #or(Specification)} or factory methods such as {@link #allOf(Iterable)}.
* Composition considers whether one or more specifications contribute to the overall predicate by returning a
* {@link Predicate} or {@literal null}. Specifications returning {@literal null} are considered to not contribute to
* the overall predicate and their result is not considered in the final predicate.
*
* @author Oliver Gierke
* @author Thomas Darimont
Expand All @@ -51,7 +57,7 @@ public interface Specification<T> extends Serializable {
* @param <T> the type of the {@link Root} the resulting {@literal Specification} operates on.
* @return guaranteed to be not {@literal null}.
*/
static <T> Specification<T> all() {
static <T> Specification<T> unrestricted() {
return (root, query, builder) -> null;
}

Expand Down Expand Up @@ -148,13 +154,14 @@ static <T> Specification<T> not(Specification<T> spec) {

return (root, query, builder) -> {

Predicate not = spec.toPredicate(root, query, builder);
return not != null ? builder.not(not) : null;
Predicate predicate = spec.toPredicate(root, query, builder);
return predicate != null ? builder.not(predicate) : null;
};
}

/**
* Applies an AND operation to all the given {@link Specification}s.
* Applies an AND operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
* {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -168,7 +175,8 @@ static <T> Specification<T> allOf(Specification<T>... specifications) {
}

/**
* Applies an AND operation to all the given {@link Specification}s.
* Applies an AND operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
* {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -179,11 +187,12 @@ static <T> Specification<T> allOf(Specification<T>... specifications) {
static <T> Specification<T> allOf(Iterable<Specification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(Specification.all(), Specification::and);
.reduce(Specification.unrestricted(), Specification::and);
}

/**
* Applies an OR operation to all the given {@link Specification}s.
* Applies an OR operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
* {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the disjunction of the specifications
Expand All @@ -197,7 +206,8 @@ static <T> Specification<T> anyOf(Specification<T>... specifications) {
}

/**
* Applies an OR operation to all the given {@link Specification}s.
* Applies an OR operation to all the given {@link Specification}s. If {@code specifications} is empty, the resulting
* {@link Specification} will be unrestricted applying to all objects.
*
* @param specifications the {@link Specification}s to compose.
* @return the disjunction of the specifications
Expand All @@ -208,7 +218,7 @@ static <T> Specification<T> anyOf(Specification<T>... specifications) {
static <T> Specification<T> anyOf(Iterable<Specification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(Specification.all(), Specification::or);
.reduce(Specification.unrestricted(), Specification::or);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@

/**
* Specification in the sense of Domain Driven Design to handle Criteria Updates.
* <p>
* Specifications can be composed into higher order functions from other specifications using
* {@link #and(UpdateSpecification)}, {@link #or(UpdateSpecification)} or factory methods such as
* {@link #allOf(Iterable)}. Composition considers whether one or more specifications contribute to the overall
* predicate by returning a {@link Predicate} or {@literal null}. Specifications returning {@literal null} are
* considered to not contribute to the overall predicate and their result is not considered in the final predicate.
*
* @author Mark Paluch
* @since 4.0
Expand All @@ -39,27 +45,27 @@
public interface UpdateSpecification<T> extends Serializable {

/**
* Simple static factory method to create a specification deleting all objects.
* Simple static factory method to create a specification updating all objects.
*
* @param <T> the type of the {@link Root} the resulting {@literal UpdateSpecification} operates on.
* @return guaranteed to be not {@literal null}.
*/
static <T> UpdateSpecification<T> all() {
static <T> UpdateSpecification<T> unrestricted() {
return (root, query, builder) -> null;
}

/**
* Simple static factory method to add some syntactic sugar around a {@literal UpdateSpecification}. For example:
* Simple static factory method to add some syntactic sugar around a {@literal UpdateOperation}. For example:
*
* <pre class="code">
* UpdateSpecification&lt;User&gt; updateLastname = UpdateSpecification
* UpdateSpecification&lt;User&gt; updateLastname = UpdateOperation
* .&lt;User&gt; update((root, update, criteriaBuilder) -> update.set("lastname", "Heisenberg"))
* .where(userHasFirstname("Walter").and(userHasLastname("White")));
*
* repository.update(updateLastname);
* </pre>
*
* @param <T> the type of the {@link Root} the resulting {@literal UpdateSpecification} operates on.
* @param <T> the type of the {@link Root} the resulting {@literal UpdateOperation} operates on.
* @param spec must not be {@literal null}.
* @return guaranteed to be not {@literal null}.
*/
Expand Down Expand Up @@ -172,13 +178,14 @@ static <T> UpdateSpecification<T> not(UpdateSpecification<T> spec) {

return (root, update, builder) -> {

Predicate not = spec.toPredicate(root, update, builder);
return not != null ? builder.not(not) : null;
Predicate predicate = spec.toPredicate(root, update, builder);
return predicate != null ? builder.not(predicate) : null;
};
}

/**
* Applies an AND operation to all the given {@link UpdateSpecification}s.
* Applies an AND operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
* resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -191,7 +198,8 @@ static <T> UpdateSpecification<T> allOf(UpdateSpecification<T>... specifications
}

/**
* Applies an AND operation to all the given {@link UpdateSpecification}s.
* Applies an AND operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
* resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the conjunction of the specifications.
Expand All @@ -201,11 +209,12 @@ static <T> UpdateSpecification<T> allOf(UpdateSpecification<T>... specifications
static <T> UpdateSpecification<T> allOf(Iterable<UpdateSpecification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(UpdateSpecification.all(), UpdateSpecification::and);
.reduce(UpdateSpecification.unrestricted(), UpdateSpecification::and);
}

/**
* Applies an OR operation to all the given {@link UpdateSpecification}s.
* Applies an OR operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
* resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the disjunction of the specifications.
Expand All @@ -218,7 +227,8 @@ static <T> UpdateSpecification<T> anyOf(UpdateSpecification<T>... specifications
}

/**
* Applies an OR operation to all the given {@link UpdateSpecification}s.
* Applies an OR operation to all the given {@link UpdateSpecification}s. If {@code specifications} is empty, the
* resulting {@link UpdateSpecification} will be unrestricted applying to all objects.
*
* @param specifications the {@link UpdateSpecification}s to compose.
* @return the disjunction of the specifications.
Expand All @@ -228,7 +238,7 @@ static <T> UpdateSpecification<T> anyOf(UpdateSpecification<T>... specifications
static <T> UpdateSpecification<T> anyOf(Iterable<UpdateSpecification<T>> specifications) {

return StreamSupport.stream(specifications.spliterator(), false) //
.reduce(UpdateSpecification.all(), UpdateSpecification::or);
.reduce(UpdateSpecification.unrestricted(), UpdateSpecification::or);
}

/**
Expand Down
Loading

0 comments on commit 490eef0

Please sign in to comment.