Skip to content

Commit

Permalink
DATAJPA-253 - Fixed application of Specifications.not(…).
Browse files Browse the repository at this point in the history
Specifications.not(…) now also gets applied correctly when used without where(…) wrapper. Polished Specifications class, JavaDoc and added not null assertions.
  • Loading branch information
odrotbohm committed Aug 30, 2012
1 parent a9cfe73 commit 918099e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 21 deletions.
Original file line number Original file line Diff line number Diff line change
@@ -1,5 +1,5 @@
/* /*
* Copyright 2008-2011 the original author or authors. * Copyright 2008-2012 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
Expand All @@ -20,49 +20,54 @@
import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;


import org.springframework.util.Assert;

/** /**
* Helper class to easily combine {@link Specification} instances. * Helper class to easily combine {@link Specification} instances.
* *
* @author Oliver Gierke * @author Oliver Gierke
*/ */
public class Specifications<T> implements Specification<T> { public class Specifications<T> implements Specification<T> {


private static final String NOT_NULL = "Specification given to %s(…) must not be null!";

private final Specification<T> spec; private final Specification<T> spec;


/** /**
* Creates a new {@link Specifications} wrapper for the given {@link Specification}. * Creates a new {@link Specifications} wrapper for the given {@link Specification}.
* *
* @param spec * @param spec must not be {@literal null}.
*/ */
private Specifications(Specification<T> spec) { private Specifications(Specification<T> spec) {

this.spec = spec; this.spec = spec;
} }


/** /**
* Simple static factory method to add some syntactic sugar around a {@link Specification}. * Simple static factory method to add some syntactic sugar around a {@link Specification}.
* *
* @param <T> * @param <T>
* @param spec * @param spec must not be {@literal null}.
* @return * @return
*/ */
public static <T> Specifications<T> where(Specification<T> spec) { public static <T> Specifications<T> where(Specification<T> spec) {


Assert.notNull(spec, String.format(NOT_NULL, "where"));
return new Specifications<T>(spec); return new Specifications<T>(spec);
} }


/** /**
* ANDs the given {@link Specification} to the current one. * ANDs the given {@link Specification} to the current one.
* *
* @param other * @param <T>
* @param other must not be {@literal null}.
* @return * @return
*/ */
public Specifications<T> and(final Specification<T> other) { public Specifications<T> and(final Specification<T> other) {


return new Specifications<T>(new Specification<T>() { Assert.notNull(spec, String.format(NOT_NULL, "and"));


return new Specifications<T>(new Specification<T>() {
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {

return builder.and(spec.toPredicate(root, query, builder), other.toPredicate(root, query, builder)); return builder.and(spec.toPredicate(root, query, builder), other.toPredicate(root, query, builder));
} }
}); });
Expand All @@ -71,15 +76,16 @@ public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuild
/** /**
* ORs the given specification to the current one. * ORs the given specification to the current one.
* *
* @param other * @param <T>
* @param other must not be {@literal null}.
* @return * @return
*/ */
public Specifications<T> or(final Specification<T> other) { public Specifications<T> or(final Specification<T> other) {


return new Specifications<T>(new Specification<T>() { Assert.notNull(spec, String.format(NOT_NULL, "or"));


return new Specifications<T>(new Specification<T>() {
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {

return builder.or(spec.toPredicate(root, query, builder), other.toPredicate(root, query, builder)); return builder.or(spec.toPredicate(root, query, builder), other.toPredicate(root, query, builder));
} }
}); });
Expand All @@ -89,30 +95,25 @@ public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuild
* Negates the given {@link Specification}. * Negates the given {@link Specification}.
* *
* @param <T> * @param <T>
* @param spec * @param spec must not be {@literal null}.
* @return * @return
*/ */
public static <T> Specifications<T> not(final Specification<T> spec) { public static <T> Specifications<T> not(final Specification<T> spec) {


return new Specifications<T>(spec) { Assert.notNull(spec, String.format(NOT_NULL, "not"));


@Override return new Specifications<T>(new Specification<T>() {
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {

return builder.not(spec.toPredicate(root, query, builder)); return builder.not(spec.toPredicate(root, query, builder));
} }
}; });
} }


/* /*
* (non-Javadoc) * (non-Javadoc)
* * @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery, javax.persistence.criteria.CriteriaBuilder)
* @see org.springframework.data.jpa.domain.Specification#toPredicate(javax.
* persistence.criteria.Root, javax.persistence.criteria.CriteriaQuery,
* javax.persistence.criteria.CriteriaBuilder)
*/ */
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) { public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder builder) {

return spec.toPredicate(root, query, builder); return spec.toPredicate(root, query, builder);
} }
} }
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -443,7 +443,21 @@ public void executesCombinedSpecificationsCorrectly() {


flushTestUsers(); flushTestUsers();
Specification<User> spec = where(userHasFirstname("Oliver")).or(userHasLastname("Arrasz")); Specification<User> spec = where(userHasFirstname("Oliver")).or(userHasLastname("Arrasz"));
assertThat(repository.findAll(spec).size(), is(2)); assertThat(repository.findAll(spec), hasSize(2));
}

/**
* @see DATAJPA-253
*/
@Test
public void executesNegatingSpecificationCorrectly() {

flushTestUsers();
Specification<User> spec = not(userHasFirstname("Oliver")).and(userHasLastname("Arrasz"));
List<User> result = repository.findAll(spec);

assertThat(result, hasSize(1));
assertThat(result, hasItem(secondUser));
} }


@Test @Test
Expand Down

0 comments on commit 918099e

Please sign in to comment.