001/*
002 *   Copyright 2024 Vonage
003 *
004 *   Licensed under the Apache License, Version 2.0 (the "License");
005 *   you may not use this file except in compliance with the License.
006 *   You may obtain a copy of the License at
007 *
008 *        http://www.apache.org/licenses/LICENSE-2.0
009 *
010 *   Unless required by applicable law or agreed to in writing, software
011 *   distributed under the License is distributed on an "AS IS" BASIS,
012 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 *   See the License for the specific language governing permissions and
014 *   limitations under the License.
015 */
016package com.vonage.client.common;
017
018import com.vonage.client.QueryParamsRequest;
019import java.time.Instant;
020import java.util.LinkedHashMap;
021import java.util.Map;
022
023/**
024 * Provides basic filtering parameters for HAL resources.
025 *
026 * @since 8.4.0
027 */
028public abstract class HalFilterRequest implements QueryParamsRequest {
029        protected final String cursor;
030        protected final Integer page, pageSize;
031        protected final SortOrder order;
032        protected final Instant startDate, endDate;
033
034        protected HalFilterRequest(Builder<?, ?> builder) {
035                cursor = builder.cursor;
036                page = validatePage(builder.page);
037                pageSize = validatePageSize(builder.pageSize);
038                order = builder.order;
039                startDate = builder.startDate;
040                endDate = builder.endDate;
041        }
042
043        protected Integer validatePage(Integer page) {
044                if (page != null && page < 1) {
045                        throw new IllegalArgumentException("Page must be positive.");
046                }
047                return page;
048        }
049
050        protected Integer validatePageSize(Integer pageSize) {
051                if (pageSize != null && (pageSize < 1 || pageSize > 1000)) {
052                        throw new IllegalArgumentException("Page size must be between 1 and 1000.");
053                }
054                return pageSize;
055        }
056
057        protected HalFilterRequest(Integer page, Integer pageSize, SortOrder order) {
058                this.page = validatePage(page);
059                this.pageSize = validatePageSize(pageSize);
060                this.order = order;
061                cursor = null;
062                startDate = null;
063                endDate = null;
064        }
065
066        @Override
067        public Map<String, String> makeParams() {
068                Map<String, String> params = new LinkedHashMap<>();
069                if (cursor != null) {
070                        params.put("cursor", cursor);
071                }
072                if (page != null) {
073                        params.put("page", page.toString());
074                }
075                if (pageSize != null) {
076                        params.put("page_size", pageSize.toString());
077                }
078                if (order != null) {
079                        params.put("order", order.toString());
080                }
081                return params;
082        }
083
084        /**
085         * Page number to navigate to in the response.
086         *
087         * @return The page as an integer, or {@code null} if not specified.
088         */
089        protected Integer getPage() {
090                return page;
091        }
092
093        /**
094         * Number of results per page.
095         *
096         * @return The page size as an integer, or {@code null} if not specified.
097         */
098        protected Integer getPageSize() {
099                return pageSize;
100        }
101
102        /**
103         * Order to sort the results by.
104         *
105         * @return The result sort order as an enum, or {@code null} if not specified.
106         */
107        protected SortOrder getOrder() {
108                return order;
109        }
110
111        /**
112         * Filter records that occurred after this point in time.
113         *
114         * @return The start timestamp for results, or {@code null} if unspecified.
115         */
116        protected Instant getStartDate() {
117                return startDate;
118        }
119
120        /**
121         * Filter records that occurred before this point in time.
122         *
123         * @return The end timestamp for results, or {@code null} if unspecified.
124         */
125        protected Instant getEndDate() {
126                return endDate;
127        }
128
129        /**
130         * The cursor to start returning results from. This can be obtained from
131         * the URL in the relevant section from {@link HalPageResponse#getLinks()}.
132         *
133         * @return The page navigation cursor as a string, or {@code null} if unspecified.
134         */
135        protected String getCursor() {
136                return cursor;
137        }
138
139        @SuppressWarnings("unchecked")
140        protected abstract static class Builder<F extends HalFilterRequest, B extends Builder<? extends F, ? extends B>> {
141                protected String cursor;
142                protected Integer page, pageSize;
143                protected SortOrder order;
144                protected Instant startDate, endDate;
145
146                /**
147                 * The cursor to start returning results from. This can be obtained from the URL in the
148                 * relevant section from {@link HalPageResponse#getLinks()}.
149                 *
150                 * @param cursor The page navigation cursor as a string.
151                 *
152                 * @return This builder.
153                 */
154                protected B cursor(String cursor) {
155                        this.cursor = cursor;
156                        return (B) this;
157                }
158
159                /**
160                 * Page to navigate to in the response.
161                 *
162                 * @param page The page as an int.
163                 *
164                 * @return This builder.
165                 */
166                protected B page(int page) {
167                        this.page = page;
168                        return (B) this;
169                }
170
171                /**
172                 * Number of results per page.
173                 *
174                 * @param pageSize he page size as an int.
175                 *
176                 * @return This builder.
177                 */
178                protected B pageSize(int pageSize) {
179                        this.pageSize = pageSize;
180                        return (B) this;
181                }
182
183                /**
184                 * Order to sort the results by.
185                 *
186                 * @param order The results sort order as an enum.
187                 *
188                 * @return This builder.
189                 */
190                protected B order(SortOrder order) {
191                        this.order = order;
192                        return (B) this;
193                }
194
195                /**
196                 * Filter records that occurred after this point in time.
197                 *
198                 * @param startDate The start timestamp for results.
199                 *
200                 * @return This builder.
201                 */
202                protected B startDate(Instant startDate) {
203                        this.startDate = startDate;
204                        return (B) this;
205                }
206
207                /**
208                 * Filter records that occurred before this point in time.
209                 *
210                 * @param endDate The end timestamp for results.
211                 *
212                 * @return This builder.
213                 */
214                protected B endDate(Instant endDate) {
215                        this.endDate = endDate;
216                        return (B) this;
217                }
218
219                /**
220                 * Builds the filter request.
221                 *
222                 * @return A new FilterRequest with this builder's properties.
223                 */
224                public abstract F build();
225        }
226}