1 /*
2 * Copyright 2014-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.domain;
17
18 import lombok.Getter;
19
20 import java.io.Serializable;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.function.Function;
26 import java.util.stream.Collectors;
27
28 import org.springframework.lang.Nullable;
29 import org.springframework.util.Assert;
30
31 /**
32 * A chunk of data restricted by the configured {@link Pageable}.
33 *
34 * @author Oliver Gierke
35 * @author Christoph Strobl
36 * @since 1.8
37 */
38 abstract class Chunk<T> implements Slice<T>, Serializable {
39
40 private static final long serialVersionUID = 867755909294344406L;
41
42 private final List<T> content = new ArrayList<>();
43 private final @Getter Pageable pageable;
44
45 /**
46 * Creates a new {@link Chunk} with the given content and the given governing {@link Pageable}.
47 *
48 * @param content must not be {@literal null}.
49 * @param pageable must not be {@literal null}.
50 */
51 public Chunk(List<T> content, Pageable pageable) {
52
53 Assert.notNull(content, "Content must not be null!");
54 Assert.notNull(pageable, "Pageable must not be null!");
55
56 this.content.addAll(content);
57 this.pageable = pageable;
58 }
59
60 /*
61 * (non-Javadoc)
62 * @see org.springframework.data.domain.Slice#getNumber()
63 */
64 public int getNumber() {
65 return pageable.isPaged() ? pageable.getPageNumber() : 0;
66 }
67
68 /*
69 * (non-Javadoc)
70 * @see org.springframework.data.domain.Slice#getSize()
71 */
72 public int getSize() {
73 return pageable.isPaged() ? pageable.getPageSize() : content.size();
74 }
75
76 /*
77 * (non-Javadoc)
78 * @see org.springframework.data.domain.Slice#getNumberOfElements()
79 */
80 public int getNumberOfElements() {
81 return content.size();
82 }
83
84 /*
85 * (non-Javadoc)
86 * @see org.springframework.data.domain.Slice#hasPrevious()
87 */
88 public boolean hasPrevious() {
89 return getNumber() > 0;
90 }
91
92 /*
93 * (non-Javadoc)
94 * @see org.springframework.data.domain.Slice#isFirst()
95 */
96 public boolean isFirst() {
97 return !hasPrevious();
98 }
99
100 /*
101 * (non-Javadoc)
102 * @see org.springframework.data.domain.Slice#isLast()
103 */
104 public boolean isLast() {
105 return !hasNext();
106 }
107
108 /*
109 * (non-Javadoc)
110 * @see org.springframework.data.domain.Slice#nextPageable()
111 */
112 public Pageable nextPageable() {
113 return hasNext() ? pageable.next() : Pageable.unpaged();
114 }
115
116 /*
117 * (non-Javadoc)
118 * @see org.springframework.data.domain.Slice#previousPageable()
119 */
120 public Pageable previousPageable() {
121 return hasPrevious() ? pageable.previousOrFirst() : Pageable.unpaged();
122 }
123
124 /*
125 * (non-Javadoc)
126 * @see org.springframework.data.domain.Slice#hasContent()
127 */
128 public boolean hasContent() {
129 return !content.isEmpty();
130 }
131
132 /*
133 * (non-Javadoc)
134 * @see org.springframework.data.domain.Slice#getContent()
135 */
136 public List<T> getContent() {
137 return Collections.unmodifiableList(content);
138 }
139
140 /*
141 * (non-Javadoc)
142 * @see org.springframework.data.domain.Slice#getSort()
143 */
144 @Override
145 public Sort getSort() {
146 return pageable.getSort();
147 }
148
149 /*
150 * (non-Javadoc)
151 * @see java.lang.Iterable#iterator()
152 */
153 public Iterator<T> iterator() {
154 return content.iterator();
155 }
156
157 /**
158 * Applies the given {@link Function} to the content of the {@link Chunk}.
159 *
160 * @param converter must not be {@literal null}.
161 * @return
162 */
163 protected <U> List<U> getConvertedContent(Function<? super T, ? extends U> converter) {
164
165 Assert.notNull(converter, "Function must not be null!");
166
167 return this.stream().map(converter::apply).collect(Collectors.toList());
168 }
169
170 /*
171 * (non-Javadoc)
172 * @see java.lang.Object#equals(java.lang.Object)
173 */
174 @Override
175 public boolean equals(@Nullable Object obj) {
176
177 if (this == obj) {
178 return true;
179 }
180
181 if (!(obj instanceof Chunk<?>)) {
182 return false;
183 }
184
185 Chunk<?> that = (Chunk<?>) obj;
186
187 boolean contentEqual = this.content.equals(that.content);
188 boolean pageableEqual = this.pageable.equals(that.pageable);
189
190 return contentEqual && pageableEqual;
191 }
192
193 /*
194 * (non-Javadoc)
195 * @see java.lang.Object#hashCode()
196 */
197 @Override
198 public int hashCode() {
199
200 int result = 17;
201
202 result += 31 * pageable.hashCode();
203 result += 31 * content.hashCode();
204
205 return result;
206 }
207 }
208