1 /*******************************************************************************
2 * Gisgraphy Project
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
17 *
18 * Copyright 2008 Gisgraphy project
19 * David Masclet <davidmasclet@gisgraphy.com>
20 *
21 *
22 *******************************************************************************/
23 /**
24 *
25 */
26 package com.gisgraphy.domain.valueobject;
27
28 /**
29 * Represent a pagination specification.the design (with DSL and interface) does
30 * not allow to set the 'to' properties before the from e.g :
31 * <code>Paginate().from(1).to(9) will return [1,2,3,4,5,6,7,8,9].
32 * @see <a href="http://www.infoq.com/articles/internal-dsls-java/">DSL</a>
33 * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
34 */
35 public class Pagination {
36
37 /**
38 * If the 'to' parameter is not specified or incorrect, it will be set to a
39 * value to have {@link #DEFAULT_MAX_RESULTS} results this value is NOT the
40 * default to parameters, we prefer to use a startegy to fix number of
41 * results instead of the from
42 */
43 public static final int DEFAULT_MAX_RESULTS = 10;
44
45
46 /**
47 * max result the pagination should have
48 */
49 public int maxResult = DEFAULT_MAX_RESULTS;
50
51 /**
52 * the default 'from' parameters if the one specified is missing or
53 * incorrect
54 */
55 public static final int DEFAULT_FROM = 1;
56
57 /**
58 * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
59 * To specification
60 */
61 public interface ToSpecification {
62 Pagination to(int to);
63 }
64
65 /**
66 * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a>
67 * From Specification
68 */
69 public interface FromSpecification {
70 ToSpecification from(int from);
71 }
72
73 /**
74 * @author <a href="mailto:david.masclet@gisgraphy.com">David Masclet</a> A
75 * pagination builder
76 */
77 public static class PaginationBuilder implements FromSpecification,
78 ToSpecification {
79
80 private int from;
81 private int to;
82 private int maxResults = DEFAULT_MAX_RESULTS;
83
84 private PaginationBuilder() {
85
86 }
87
88 // builder is private
89 private Pagination build() {
90 Pagination pagination = new Pagination();
91 pagination.maxResult=maxResults;
92 pagination.from(this.from)
93 .to(this.to);
94 return pagination;
95 }
96
97 /*
98 * (non-Javadoc)
99 *
100 * @see com.gisgraphy.domain.valueobject.Pagination.ToSpecification#to(int)
101 */
102 public Pagination to(int to) {
103 this.to = to;
104 return build();
105 }
106
107 /*
108 * (non-Javadoc)
109 *
110 * @see com.gisgraphy.domain.valueobject.Pagination.FromSpecification#from(int)
111 */
112 public ToSpecification from(int from) {
113 this.from = from;
114 return this;
115 }
116
117 }
118
119 /**
120 * Default Pagination
121 */
122 public static final Pagination DEFAULT_PAGINATION = new Pagination();
123
124 /**
125 * The from attribute (int to force non null value)
126 */
127 private int from = DEFAULT_FROM;
128
129 /**
130 * The to attribute
131 */
132 private int to = DEFAULT_FROM + DEFAULT_MAX_RESULTS - 1;
133
134 /**
135 * private contructor
136 */
137 private Pagination() {
138 super();
139 }
140
141 /**
142 * Static method to be used to create a pagination object. (tip : use Static
143 * import)
144 *
145 * @return An instance of {@link FromSpecification} to force the from
146 * parameter to be set first
147 */
148 public static FromSpecification paginate() {
149 return new PaginationBuilder();
150 }
151
152 /**
153 * Static method to be used to create a pagination object and define maxResults. (tip : use Static
154 * import). because The to parameter is calculated with the masResultValue, you need to use this method befor set the to and the from.
155 *
156 * @param maxResult the max number of results he pagination should have, if max results is incorrect,{@link #DEFAULT_MAX_RESULTS} will be used
157 * @return An instance of {@link FromSpecification} to force the from
158 * parameter to be set first
159 */
160 public static FromSpecification paginateWithMaxResults(int maxResult) {
161 PaginationBuilder builder = new PaginationBuilder();
162 if (maxResult <= 0){
163 builder.maxResults = DEFAULT_MAX_RESULTS;
164 }else {
165 builder.maxResults = maxResult;
166 }
167 return builder;
168 }
169
170 /**
171 * @param from
172 * the from parameter for the current pagination, must be > 0
173 * (numberd from 1)
174 * @return the current Pagination instance in order to chain setters if the
175 * parameter is not >0, it will be set to default :
176 * {@link #DEFAULT_FROM}
177 * @see <a href="http://www.infoq.com/articles/internal-dsls-java/">DSL</a>
178 */
179 private Pagination from(int from) {
180 this.from = from > 0 ? from : DEFAULT_FROM;
181 return this;
182 }
183
184 /**
185 * @param to
186 * the to parameter for the current pagination,must be > 0
187 * and > {@link #from(int)}
188 * @return the current Pagination instance in order to chain setters If the
189 * parameter is < from or <= 0, it will be set at a specific value
190 * in order to have {@link #DEFAULT_MAX_RESULTS}
191 * @see <a href="http://www.infoq.com/articles/internal-dsls-java/">DSL</a>
192 */
193 private Pagination to(int to) {
194 this.to = (to > 0 && to >= this.from) ? to : this.from
195 + maxResult - 1;
196 return this;
197 }
198
199 /**
200 * @return the from
201 */
202 public int getFrom() {
203 return from;
204 }
205
206 /**
207 * @return the to
208 */
209 public int getTo() {
210 return to;
211 }
212
213 /**
214 * Do a post-treatment on the current pagination to limit number of results.
215 * 'from will be unchanged, only 'to' will be changed if limit is <=0, there
216 * is no effect
217 *
218 * @param limit
219 * the max number Of results
220 * @return the current Pagination to chain methods
221 */
222 public Pagination limitNumberOfResults(int limit) {
223 if (limit > 0) {
224 this.to = getMaxNumberOfResults() > limit ? from + limit - 1 : to;
225 }
226 return this;
227 }
228
229 /**
230 * @return how many results will be return according the from and to
231 * parameters (the max expected numbers of results). it can be less
232 * than expected if there is less results to return. e.g :
233 * from(1).to(5) can nly return 2 results if there is only 2
234 * parameters but this method return the max expected numbers of
235 * results) it will return 0 if from and to equals 0
236 */
237 public int getMaxNumberOfResults() {
238 return (to - from) + 1;
239 }
240
241 /* (non-Javadoc)
242 * @see java.lang.Object#hashCode()
243 */
244 @Override
245 public int hashCode() {
246 final int prime = 31;
247 int result = 1;
248 result = prime * result + from;
249 result = prime * result + to;
250 return result;
251 }
252
253 /* (non-Javadoc)
254 * @see java.lang.Object#equals(java.lang.Object)
255 */
256 @Override
257 public boolean equals(Object obj) {
258 if (this == obj)
259 return true;
260 if (obj == null)
261 return false;
262 if (getClass() != obj.getClass())
263 return false;
264 final Pagination other = (Pagination) obj;
265 if (from != other.from)
266 return false;
267 if (to != other.to)
268 return false;
269 return true;
270 }
271
272 /*
273 * (non-Javadoc)
274 *
275 * @see java.lang.Object#toString()
276 */
277 @Override
278 public String toString() {
279 return "paginate from " + from + " to " + to;
280 }
281
282 }