diff --git a/src/main/java/org/springframework/data/domain/Chunk.java b/src/main/java/org/springframework/data/domain/Chunk.java new file mode 100644 index 000000000..7a5a8d310 --- /dev/null +++ b/src/main/java/org/springframework/data/domain/Chunk.java @@ -0,0 +1,191 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.domain; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.springframework.util.Assert; + +/** + * A chunk of data restricted by the configured {@link Pageable}. + * + * @author Oliver Gierke + * @since 1.8 + */ +abstract class Chunk implements Slice, Serializable { + + private static final long serialVersionUID = 867755909294344406L; + + private final List content = new ArrayList(); + private final Pageable pageable; + + /** + * Creates a new {@link Chunk} with the given content and the given governing {@link Pageable}. + * + * @param content must not be {@literal null}. + * @param pageable can be {@literal null}. + */ + public Chunk(List content, Pageable pageable) { + + Assert.notNull(content, "Content must not be null!"); + + this.content.addAll(content); + this.pageable = pageable; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#getNumber() + */ + public int getNumber() { + return pageable == null ? 0 : pageable.getPageNumber(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#getSize() + */ + public int getSize() { + return pageable == null ? 0 : pageable.getPageSize(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#getNumberOfElements() + */ + public int getNumberOfElements() { + return content.size(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#hasPrevious() + */ + public boolean hasPrevious() { + return getNumber() > 0; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#isFirst() + */ + public boolean isFirst() { + return !hasPrevious(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#isLast() + */ + public boolean isLast() { + return !hasNext(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#nextPageable() + */ + public Pageable nextPageable() { + return hasNext() ? pageable.next() : null; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#previousPageable() + */ + public Pageable previousPageable() { + + if (hasPrevious()) { + return pageable.previousOrFirst(); + } + + return null; + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#hasContent() + */ + public boolean hasContent() { + return !content.isEmpty(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#getContent() + */ + public List getContent() { + return Collections.unmodifiableList(content); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#getSort() + */ + public Sort getSort() { + return pageable == null ? null : pageable.getSort(); + } + + /* + * (non-Javadoc) + * @see java.lang.Iterable#iterator() + */ + public Iterator iterator() { + return content.iterator(); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (!(obj instanceof Chunk)) { + return false; + } + + Chunk that = (Chunk) obj; + + boolean contentEqual = this.content.equals(that.content); + boolean pageableEqual = this.pageable == null ? that.pageable == null : this.pageable.equals(that.pageable); + + return contentEqual && pageableEqual; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + + int result = 17; + + result += 31 * (pageable == null ? 0 : pageable.hashCode()); + result += 31 * content.hashCode(); + + return result; + } +} diff --git a/src/main/java/org/springframework/data/domain/Page.java b/src/main/java/org/springframework/data/domain/Page.java index 393913b2a..51c64e978 100644 --- a/src/main/java/org/springframework/data/domain/Page.java +++ b/src/main/java/org/springframework/data/domain/Page.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2013 the original author or authors. + * Copyright 2008-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,9 +15,6 @@ */ package org.springframework.data.domain; -import java.util.Iterator; -import java.util.List; - /** * A page is a sublist of a list of objects. It allows gain information about the position of it in the containing * entire list. @@ -25,21 +22,7 @@ import java.util.List; * @param * @author Oliver Gierke */ -public interface Page extends Iterable { - - /** - * Returns the number of the current page. Is always non-negative and less that {@code Page#getTotalPages()}. - * - * @return the number of the current page - */ - int getNumber(); - - /** - * Returns the size of the page. - * - * @return the size of the page - */ - int getSize(); +public interface Page extends Slice { /** * Returns the number of total pages. @@ -48,13 +31,6 @@ public interface Page extends Iterable { */ int getTotalPages(); - /** - * Returns the number of elements currently on this page. - * - * @return the number of elements currently on this page - */ - int getNumberOfElements(); - /** * Returns the total amount of elements. * @@ -65,73 +41,36 @@ public interface Page extends Iterable { /** * Returns if there is a previous page. * + * @deprecated use {@link #hasPrevious()} instead. * @return if there is a previous page */ + @Deprecated boolean hasPreviousPage(); /** * Returns whether the current page is the first one. * + * @deprecated use {@link #isFirst()} instead. * @return */ + @Deprecated boolean isFirstPage(); /** * Returns if there is a next page. * + * @deprecated use {@link #hasNext()} instead. * @return if there is a next page */ + @Deprecated boolean hasNextPage(); /** * Returns whether the current page is the last one. * + * @deprecated use {@link #isLast()} instead. * @return */ + @Deprecated boolean isLastPage(); - - /** - * Returns the {@link Pageable} to request the next {@link Page}. Can be {@literal null} in case the current - * {@link Page} is already the last one. Clients should check {@link #hasNextPage()} before calling this method to - * make sure they receive a non-{@literal null} value. - * - * @return - */ - Pageable nextPageable(); - - /** - * Returns the {@link Pageable} to request the previous page. Can be {@literal null} in case the current {@link Page} - * is already the first one. Clients should check {@link #hasPreviousPage()} before calling this method make sure - * receive a non-{@literal null} value. - * - * @return - */ - Pageable previousPageable(); - - /* - * (non-Javadoc) - * @see java.lang.Iterable#iterator() - */ - Iterator iterator(); - - /** - * Returns the page content as {@link List}. - * - * @return - */ - List getContent(); - - /** - * Returns whether the {@link Page} has content at all. - * - * @return - */ - boolean hasContent(); - - /** - * Returns the sorting parameters for the page. - * - * @return - */ - Sort getSort(); } diff --git a/src/main/java/org/springframework/data/domain/PageImpl.java b/src/main/java/org/springframework/data/domain/PageImpl.java index 513248d74..9f63902d9 100644 --- a/src/main/java/org/springframework/data/domain/PageImpl.java +++ b/src/main/java/org/springframework/data/domain/PageImpl.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2013 the original author or authors. + * Copyright 2008-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,10 +15,6 @@ */ package org.springframework.data.domain; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; import java.util.List; /** @@ -27,12 +23,10 @@ import java.util.List; * @param the type of which the page consists. * @author Oliver Gierke */ -public class PageImpl implements Page, Serializable { +public class PageImpl extends Chunk implements Page { private static final long serialVersionUID = 867755909294344406L; - private final List content = new ArrayList(); - private final Pageable pageable; private final long total; /** @@ -44,13 +38,8 @@ public class PageImpl implements Page, Serializable { */ public PageImpl(List content, Pageable pageable, long total) { - if (null == content) { - throw new IllegalArgumentException("Content must not be null!"); - } - - this.content.addAll(content); + super(content, pageable); this.total = total; - this.pageable = pageable; } /** @@ -63,22 +52,6 @@ public class PageImpl implements Page, Serializable { this(content, null, null == content ? 0 : content.size()); } - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#getNumber() - */ - public int getNumber() { - return pageable == null ? 0 : pageable.getPageNumber(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#getSize() - */ - public int getSize() { - return pageable == null ? 0 : pageable.getPageSize(); - } - /* * (non-Javadoc) * @see org.springframework.data.domain.Page#getTotalPages() @@ -87,14 +60,6 @@ public class PageImpl implements Page, Serializable { return getSize() == 0 ? 1 : (int) Math.ceil((double) total / (double) getSize()); } - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#getNumberOfElements() - */ - public int getNumberOfElements() { - return content.size(); - } - /* * (non-Javadoc) * @see org.springframework.data.domain.Page#getTotalElements() @@ -108,7 +73,7 @@ public class PageImpl implements Page, Serializable { * @see org.springframework.data.domain.Page#hasPreviousPage() */ public boolean hasPreviousPage() { - return getNumber() > 0; + return hasPrevious(); } /* @@ -116,7 +81,16 @@ public class PageImpl implements Page, Serializable { * @see org.springframework.data.domain.Page#isFirstPage() */ public boolean isFirstPage() { - return !hasPreviousPage(); + return isFirst(); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#hasNext() + */ + @Override + public boolean hasNext() { + return hasNextPage(); } /* @@ -127,6 +101,15 @@ public class PageImpl implements Page, Serializable { return getNumber() + 1 < getTotalPages(); } + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#isLast() + */ + @Override + public boolean isLast() { + return isLastPage(); + } + /* * (non-Javadoc) * @see org.springframework.data.domain.Page#isLastPage() @@ -135,59 +118,6 @@ public class PageImpl implements Page, Serializable { return !hasNextPage(); } - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#nextPageable() - */ - public Pageable nextPageable() { - return hasNextPage() ? pageable.next() : null; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#previousOrFirstPageable() - */ - public Pageable previousPageable() { - - if (hasPreviousPage()) { - return pageable.previousOrFirst(); - } - - return null; - } - - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#iterator() - */ - public Iterator iterator() { - return content.iterator(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#getContent() - */ - public List getContent() { - return Collections.unmodifiableList(content); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#hasContent() - */ - public boolean hasContent() { - return !content.isEmpty(); - } - - /* - * (non-Javadoc) - * @see org.springframework.data.domain.Page#getSort() - */ - public Sort getSort() { - return pageable == null ? null : pageable.getSort(); - } - /* * (non-Javadoc) * @see java.lang.Object#toString() @@ -196,6 +126,7 @@ public class PageImpl implements Page, Serializable { public String toString() { String contentType = "UNKNOWN"; + List content = getContent(); if (content.size() > 0) { contentType = content.get(0).getClass().getName(); @@ -221,11 +152,7 @@ public class PageImpl implements Page, Serializable { PageImpl that = (PageImpl) obj; - boolean totalEqual = this.total == that.total; - boolean contentEqual = this.content.equals(that.content); - boolean pageableEqual = this.pageable == null ? that.pageable == null : this.pageable.equals(that.pageable); - - return totalEqual && contentEqual && pageableEqual; + return this.total == that.total && super.equals(obj); } /* @@ -237,9 +164,8 @@ public class PageImpl implements Page, Serializable { int result = 17; - result = 31 * result + (int) (total ^ total >>> 32); - result = 31 * result + (pageable == null ? 0 : pageable.hashCode()); - result = 31 * result + content.hashCode(); + result += 31 * (int) (total ^ total >>> 32); + result += 31 * super.hashCode(); return result; } diff --git a/src/main/java/org/springframework/data/domain/Slice.java b/src/main/java/org/springframework/data/domain/Slice.java new file mode 100644 index 000000000..213de1956 --- /dev/null +++ b/src/main/java/org/springframework/data/domain/Slice.java @@ -0,0 +1,116 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.domain; + +import java.util.List; + +/** + * A slice of data that indicates whether there's a next or previous slice available. Allows to obtain a + * {@link Pageable} to request a previous or next {@link Slice}. + * + * @author Oliver Gierke + * @since 1.8 + */ +public interface Slice extends Iterable { + + /** + * Returns the number of the current {@link Slice}. Is always non-negative. + * + * @return the number of the current {@link Slice}. + */ + int getNumber(); + + /** + * Returns the size of the {@link Slice}. + * + * @return the size of the {@link Slice}. + */ + int getSize(); + + /** + * Returns the number of elements currently on this {@link Slice}. + * + * @return the number of elements currently on this {@link Slice}. + */ + int getNumberOfElements(); + + /** + * Returns the page content as {@link List}. + * + * @return + */ + List getContent(); + + /** + * Returns whether the {@link Slice} has content at all. + * + * @return + */ + boolean hasContent(); + + /** + * Returns the sorting parameters for the {@link Slice}. + * + * @return + */ + Sort getSort(); + + /** + * Returns whether the current {@link Slice} is the first one. + * + * @return + */ + boolean isFirst(); + + /** + * Returns whether the current {@link Slice} is the last one. + * + * @return + */ + boolean isLast(); + + /** + * Returns if there is a next {@link Slice}. + * + * @return if there is a next {@link Slice}. + */ + boolean hasNext(); + + /** + * Returns if there is a previous {@link Slice}. + * + * @return if there is a previous {@link Slice}. + */ + boolean hasPrevious(); + + /** + * Returns the {@link Pageable} to request the next {@link Slice}. Can be {@literal null} in case the current + * {@link Slice} is already the last one. Clients should check {@link #hasNext()} before calling this method to make + * sure they receive a non-{@literal null} value. + * + * @return + */ + Pageable nextPageable(); + + /** + * Returns the {@link Pageable} to request the previous {@link Slice}. Can be {@literal null} in case the current + * {@link Slice} is already the first one. Clients should check {@link #hasPrevious()} before calling this method make + * sure receive a non-{@literal null} value. + * + * @return + */ + Pageable previousPageable(); +} diff --git a/src/main/java/org/springframework/data/domain/SliceImpl.java b/src/main/java/org/springframework/data/domain/SliceImpl.java new file mode 100644 index 000000000..d66a9229a --- /dev/null +++ b/src/main/java/org/springframework/data/domain/SliceImpl.java @@ -0,0 +1,114 @@ +/* + * Copyright 2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.domain; + +import java.util.List; + +/** + * Default implementation of {@link Slice}. + * + * @author Oliver Gierke + * @since 1.8 + */ +public class SliceImpl extends Chunk { + + private static final long serialVersionUID = 867755909294344406L; + + private final boolean hasNext; + + /** + * Creates a new {@link Slice} with the given content and {@link Pageable}. + * + * @param content the content of this {@link Slice}, must not be {@literal null}. + * @param pageable the paging information, can be {@literal null}. + * @param hasNext whether there's another slice following the current one. + */ + public SliceImpl(List content, Pageable pageable, boolean hasNext) { + + super(content, pageable); + this.hasNext = hasNext; + } + + /** + * Creates a new {@link SliceImpl} with the given content. This will result in the created {@link Slice} being + * identical to the entire {@link List}. + * + * @param content must not be {@literal null}. + */ + public SliceImpl(List content) { + this(content, null, false); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.domain.Slice#hasNext() + */ + public boolean hasNext() { + return hasNext; + } + + /* + * (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + + String contentType = "UNKNOWN"; + List content = getContent(); + + if (content.size() > 0) { + contentType = content.get(0).getClass().getName(); + } + + return String.format("Slice %s of %d containing %s instances", getNumber(), contentType); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + @Override + public boolean equals(Object obj) { + + if (this == obj) { + return true; + } + + if (!(obj instanceof SliceImpl)) { + return false; + } + + SliceImpl that = (SliceImpl) obj; + + return this.hasNext == that.hasNext && super.equals(obj); + } + + /* + * (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + + int result = 17; + + result += 31 * (hasNext ? 1 : 0); + result += 31 * super.hashCode(); + + return result; + } +} diff --git a/src/main/java/org/springframework/data/repository/query/QueryMethod.java b/src/main/java/org/springframework/data/repository/query/QueryMethod.java index 69d536eb2..9896220bd 100644 --- a/src/main/java/org/springframework/data/repository/query/QueryMethod.java +++ b/src/main/java/org/springframework/data/repository/query/QueryMethod.java @@ -22,6 +22,7 @@ import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; import org.springframework.data.domain.Sort; import org.springframework.data.repository.core.EntityMetadata; import org.springframework.data.repository.core.RepositoryMetadata; @@ -59,7 +60,7 @@ public class QueryMethod { } if (hasParameterOfType(method, Pageable.class)) { - assertReturnTypeAssignable(method, Page.class, List.class); + assertReturnTypeAssignable(method, Slice.class, Page.class, List.class); if (hasParameterOfType(method, Sort.class)) { throw new IllegalStateException(String.format("Method must not have Pageable *and* Sort parameter. " + "Use sorting capabilities on Pageble instead! Offending method: %s", method.toString())); @@ -152,7 +153,20 @@ public class QueryMethod { public boolean isCollectionQuery() { Class returnType = method.getReturnType(); - return !isPageQuery() && org.springframework.util.ClassUtils.isAssignable(Iterable.class, returnType); + return !(isPageQuery() || isSliceQuery()) + && org.springframework.util.ClassUtils.isAssignable(Iterable.class, returnType); + } + + /** + * Returns whether the query method will return a {@link Slice}. + * + * @return + * @since 1.8 + */ + public boolean isSliceQuery() { + + Class returnType = method.getReturnType(); + return !isPageQuery() && org.springframework.util.ClassUtils.isAssignable(Slice.class, returnType); } /** diff --git a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java index cf7f3ba18..669e73cea 100644 --- a/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java +++ b/src/main/java/org/springframework/data/web/PagedResourcesAssembler.java @@ -155,11 +155,11 @@ public class PagedResourcesAssembler implements ResourceAssembler, Pa private PagedResources addPaginationLinks(PagedResources resources, Page page, String uri) { - if (page.hasNextPage()) { + if (page.hasNext()) { foo(resources, page.nextPageable(), uri, Link.REL_NEXT); } - if (page.hasPreviousPage()) { + if (page.hasPrevious()) { foo(resources, page.previousPageable(), uri, Link.REL_PREVIOUS); } diff --git a/src/test/java/org/springframework/data/domain/PageImplUnitTests.java b/src/test/java/org/springframework/data/domain/PageImplUnitTests.java index 220d8065c..f754e5673 100644 --- a/src/test/java/org/springframework/data/domain/PageImplUnitTests.java +++ b/src/test/java/org/springframework/data/domain/PageImplUnitTests.java @@ -1,17 +1,17 @@ /* - * Copyright 2008-2013 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * + * Copyright 2008-2014 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.springframework.data.domain; @@ -71,12 +71,12 @@ public class PageImplUnitTests { Page page = new PageImpl(Arrays.asList(new Object()), new PageRequest(0, 1), 10); - assertThat(page.isFirstPage(), is(true)); - assertThat(page.hasPreviousPage(), is(false)); + assertThat(page.isFirst(), is(true)); + assertThat(page.hasPrevious(), is(false)); assertThat(page.previousPageable(), is(nullValue())); - assertThat(page.isLastPage(), is(false)); - assertThat(page.hasNextPage(), is(true)); + assertThat(page.isLast(), is(false)); + assertThat(page.hasNext(), is(true)); assertThat(page.nextPageable(), is((Pageable) new PageRequest(1, 1))); } @@ -85,12 +85,12 @@ public class PageImplUnitTests { Page page = new PageImpl(Arrays.asList(new Object()), new PageRequest(1, 1), 2); - assertThat(page.isFirstPage(), is(false)); - assertThat(page.hasPreviousPage(), is(true)); + assertThat(page.isFirst(), is(false)); + assertThat(page.hasPrevious(), is(true)); assertThat(page.previousPageable(), is((Pageable) new PageRequest(0, 1))); - assertThat(page.isLastPage(), is(true)); - assertThat(page.hasNextPage(), is(false)); + assertThat(page.isLast(), is(true)); + assertThat(page.hasNext(), is(false)); assertThat(page.nextPageable(), is(nullValue())); } @@ -107,10 +107,10 @@ public class PageImplUnitTests { assertThat(page.getSort(), is((Sort) null)); assertThat(page.getTotalElements(), is(0L)); assertThat(page.getTotalPages(), is(1)); - assertThat(page.hasNextPage(), is(false)); - assertThat(page.hasPreviousPage(), is(false)); - assertThat(page.isFirstPage(), is(true)); - assertThat(page.isLastPage(), is(true)); + assertThat(page.hasNext(), is(false)); + assertThat(page.hasPrevious(), is(false)); + assertThat(page.isFirst(), is(true)); + assertThat(page.isLast(), is(true)); assertThat(page.hasContent(), is(false)); } @@ -123,7 +123,7 @@ public class PageImplUnitTests { Page page = new PageImpl(Arrays.asList("a")); assertThat(page.getTotalPages(), is(1)); - assertThat(page.hasNextPage(), is(false)); - assertThat(page.hasPreviousPage(), is(false)); + assertThat(page.hasNext(), is(false)); + assertThat(page.hasPrevious(), is(false)); } } diff --git a/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java b/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java index 5375477c9..64a36b31e 100644 --- a/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java +++ b/src/test/java/org/springframework/data/repository/query/QueryMethodUnitTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2008-2011 the original author or authors. + * Copyright 2008-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,32 +15,32 @@ */ package org.springframework.data.repository.query; -import static org.junit.Assert.*; -import static org.mockito.Mockito.*; import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import java.io.Serializable; import java.lang.reflect.Method; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.runners.MockitoJUnitRunner; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Slice; +import org.springframework.data.repository.Repository; import org.springframework.data.repository.core.RepositoryMetadata; +import org.springframework.data.repository.core.support.DefaultRepositoryMetadata; /** * Unit tests for {@link QueryMethod}. * * @author Oliver Gierke */ -@RunWith(MockitoJUnitRunner.class) public class QueryMethodUnitTests { - @Mock - RepositoryMetadata metadata; + RepositoryMetadata metadata = new DefaultRepositoryMetadata(SampleRepository.class); + /** + * @see DATAJPA-59 + */ @Test(expected = IllegalStateException.class) public void rejectsPagingMethodWithInvalidReturnType() throws Exception { @@ -48,18 +48,27 @@ public class QueryMethodUnitTests { new QueryMethod(method, metadata); } + /** + * @see DATAJPA-59 + */ @Test(expected = IllegalArgumentException.class) public void rejectsPagingMethodWithoutPageable() throws Exception { Method method = SampleRepository.class.getMethod("pagingMethodWithoutPageable"); new QueryMethod(method, metadata); } + /** + * @see DATACMNS-64 + */ @Test public void setsUpSimpleQueryMethodCorrectly() throws Exception { Method method = SampleRepository.class.getMethod("findByUsername", String.class); new QueryMethod(method, metadata); } + /** + * @see DATACMNS-61 + */ @Test public void considersIterableMethodForCollectionQuery() throws Exception { Method method = SampleRepository.class.getMethod("sampleMethod"); @@ -67,6 +76,9 @@ public class QueryMethodUnitTests { assertThat(queryMethod.isCollectionQuery(), is(true)); } + /** + * @see DATACMNS-67 + */ @Test public void doesNotConsiderPageMethodCollectionQuery() throws Exception { Method method = SampleRepository.class.getMethod("anotherSampleMethod", Pageable.class); @@ -75,33 +87,47 @@ public class QueryMethodUnitTests { assertThat(queryMethod.isCollectionQuery(), is(false)); } + /** + * @see DATACMNS-171 + */ @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) public void detectsAnEntityBeingReturned() throws Exception { - when(metadata.getDomainType()).thenReturn((Class) User.class); - when(metadata.getReturnedDomainClass(Mockito.any(Method.class))).thenReturn((Class) SpecialUser.class); - Method method = SampleRepository.class.getMethod("returnsEntitySubclass"); QueryMethod queryMethod = new QueryMethod(method, metadata); assertThat(queryMethod.isQueryForEntity(), is(true)); } + /** + * @see DATACMNS-171 + */ @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) public void detectsNonEntityBeingReturned() throws Exception { - when(metadata.getDomainType()).thenReturn((Class) User.class); - when(metadata.getReturnedDomainClass(Mockito.any(Method.class))).thenReturn((Class) Integer.class); - Method method = SampleRepository.class.getMethod("returnsProjection"); QueryMethod queryMethod = new QueryMethod(method, metadata); assertThat(queryMethod.isQueryForEntity(), is(false)); } - interface SampleRepository { + /** + * @see DATACMNS-397 + */ + @Test + public void detectsSliceMethod() throws Exception { + + RepositoryMetadata repositoryMetadata = new DefaultRepositoryMetadata(SampleRepository.class); + Method method = SampleRepository.class.getMethod("sliceOfUsers"); + QueryMethod queryMethod = new QueryMethod(method, repositoryMetadata); + + assertThat(queryMethod.isSliceQuery(), is(true)); + assertThat(queryMethod.isCollectionQuery(), is(false)); + assertThat(queryMethod.isPageQuery(), is(false)); + } + + interface SampleRepository extends Repository { + String pagingMethodWithInvalidReturnType(Pageable pageable); Page pagingMethodWithoutPageable(); @@ -115,6 +141,8 @@ public class QueryMethodUnitTests { SpecialUser returnsEntitySubclass(); Integer returnsProjection(); + + Slice sliceOfUsers(); } class User {