View Javadoc
1   /*
2    * Copyright 2018-2022 Medical Information Systems Research Group (https://medical.zcu.cz),
3    * Department of Computer Science and Engineering, University of West Bohemia.
4    * Address: Univerzitni 8, 306 14 Plzen, Czech Republic.
5    *
6    * Author Petr Vcelak (vcelak@kiv.zcu.cz).
7    *
8    * This file is part of MRECore project.
9    *
10   * MRECore is free software: you can redistribute it and/or modify
11   * it under the terms of the GNU General Public License as published by
12   * the Free Software Foundation, either version 3 of the License.
13   *
14   * MRECore is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17   * GNU General Public License for more details.
18   *
19   * You should have received a copy of the GNU General Public License
20   * along with MRECore. If not, see <http://www.gnu.org/licenses/>.
21   */
22  package cz.zcu.mre.data.datatable;
23  
24  import java.util.ArrayList;
25  import java.util.Enumeration;
26  import java.util.List;
27  import java.util.regex.Matcher;
28  import java.util.regex.Pattern;
29  import jakarta.servlet.http.HttpServletRequest;
30  import org.slf4j.Logger;
31  import org.slf4j.LoggerFactory;
32  
33  /**
34   * The Class DataTableRequest.
35   *
36   * @author Petr Vcelak (vcelak@kiv.zcu.cz)
37   * @param <T> Class type.
38   */
39  public class DataTableRequest<T> {
40  
41      private static final Logger LOG = LoggerFactory.getLogger(DataTableRequest.class);
42      /**
43       * The unique id.
44       */
45      private String uniqueId;
46  
47      /**
48       * The draw.
49       */
50      private String draw;
51  
52      /**
53       * The start.
54       */
55      private Long start;
56  
57      /**
58       * The length.
59       */
60      private Long length;
61  
62      /**
63       * Filtered count.
64       */
65      private Long filteredCount;
66      /**
67       * The search.
68       */
69      private String search;
70  
71      /**
72       * The regex.
73       */
74      private boolean regex;
75  
76      /**
77       * The columns.
78       */
79      private List<DataTableColumnSpecs> columns;
80  
81      /**
82       * The order.
83       */
84      private List<DataTableColumnSpecs> order = null;
85  
86      /**
87       * The is global search.
88       */
89      private boolean globalSearch;
90  
91      /**
92       * The max params to check.
93       */
94      private int maxParamsToCheck = 0;
95  
96      /**
97       * Instantiates a new data table request.
98       *
99       * @param request the request
100      */
101     public DataTableRequest(HttpServletRequest request) {
102 
103         prepareDataTableRequest(request);
104     }
105 
106     /**
107      * Prepare data table request.
108      *
109      * @param request the request
110      */
111     private void prepareDataTableRequest(HttpServletRequest request) {
112 
113         Enumeration<String> parameterNames = request.getParameterNames();
114 
115         while (parameterNames.hasMoreElements()) {
116             String name = parameterNames.nextElement();
117             String value = request.getParameter(name);
118             LOG.debug("PARAMETER NAMES " + name + "=" + value);
119         }
120 
121         parameterNames = request.getParameterNames();
122         if (parameterNames.hasMoreElements()) {
123             LOG.debug("HttpServletRequest has more elements");
124 
125             this.setStart(Long.parseLong(request.getParameter(DataTableQueryCriteria.PAGE_NUMBER)));
126             LOG.debug("page number {}", getStart());
127             this.setLength(Long.parseLong(request.getParameter(DataTableQueryCriteria.PAGE_SIZE)));
128             LOG.debug("page size {}", getLength());
129 
130             this.setUniqueId(request.getParameter(DataTableQueryCriteria.UNIQUE_ID));
131             LOG.debug("uniq ID {}", getUniqueId());
132 
133             this.setDraw(request.getParameter(DataTableQueryCriteria.DRAW));
134             LOG.debug("draw {}", getDraw());
135 
136             this.setSearch(request.getParameter("search[value]"));
137             LOG.debug("search {}", getSearch());
138 
139             this.setRegex(Boolean.valueOf(request.getParameter("search[regex]")));
140             LOG.debug("regex {}", isRegex());
141 
142             if (!DataTableUtils.isObjectEmpty(this.getSearch())) {
143                 this.setGlobalSearch(true);
144                 LOG.debug("isGlobalSearch {}", isGlobalSearch());
145             }
146 
147             // parse specification for all columns
148             List<DataTableColumnSpecs> localColumns = new ArrayList<>();
149             maxParamsToCheck = getNumberOfColumns(request);
150             for (int i = 0; i < maxParamsToCheck; i++) {
151                 if (request.getParameter("columns[" + i + "][data]") != null
152                         && !"null".equalsIgnoreCase(request.getParameter("columns[" + i + "][data]"))
153                         && !DataTableUtils.isObjectEmpty(request.getParameter("columns[" + i + "][data]"))) {
154 
155                     DataTableColumnSpecs colSpec = new DataTableColumnSpecs(request, i);
156                     LOG.debug("DataTableColumnSpec {}", colSpec);
157 
158                     localColumns.add(colSpec);
159 
160                     if (!DataTableUtils.isObjectEmpty(colSpec.getSearch())) {
161                         this.setGlobalSearch(false);
162                         LOG.debug("isGlobalSearch {}", isGlobalSearch());
163                     }
164                 }
165             }
166 
167             // parse data for order by clause
168             for (int i = 0; i < maxParamsToCheck; i++) {
169                 if (request.getParameter("order[" + i + "][column]") != null
170                         && !"null".equalsIgnoreCase(request.getParameter("order[" + i + "][column]"))
171                         && !DataTableUtils.isObjectEmpty(request.getParameter("order[" + i + "][column]"))) {
172 
173                     int columnIndex = Integer.parseInt(request.getParameter("order[" + i + "][column]"));
174                     String sortDirection = request.getParameter("order[" + i + "][dir]");
175                     LOG.info("DataTable sort by ({}) column {} in direction {}", i, columnIndex, sortDirection);
176 
177                     // get specification for the column by its index
178                     DataTableColumnSpecs dtcs = localColumns.get(columnIndex);
179                     if (dtcs == null) {
180                         LOG.warn("Column specification for ordering not found.");
181                         continue;
182                     }
183 
184                     // set sort direction
185                     dtcs.setSortDir(sortDirection);
186 
187                     // add to the list of columns used for sorting the data
188                     addOrderByColumn(dtcs);
189                 }
190             }
191 
192             if (!DataTableUtils.isObjectEmpty(localColumns)) {
193                 this.setColumns(localColumns);
194                 LOG.debug("column.size {}", getColumns().size());
195             }
196         }
197 
198     }
199 
200     private int getNumberOfColumns(HttpServletRequest request) {
201 
202         Pattern p = Pattern.compile("columns\\[[0-9]+\\]\\[data\\]");
203         @SuppressWarnings("rawtypes")
204         Enumeration params = request.getParameterNames();
205         List<String> lstOfParams = new ArrayList<>();
206         while (params.hasMoreElements()) {
207             String paramName = (String) params.nextElement();
208             Matcher m = p.matcher(paramName);
209             if (m.matches()) {
210                 lstOfParams.add(paramName);
211             }
212         }
213 
214         return lstOfParams.size();
215     }
216 
217     /**
218      * Gets the pagination request.
219      *
220      * @return the pagination request
221      */
222     public DataTableQueryCriteria getQueryCriteria() {
223 
224         DataTableQueryCriteria queryCriteria = new DataTableQueryCriteria();
225         queryCriteria.setPageNumber(this.getStart() / this.getLength()); // have to compute the page number
226         queryCriteria.setPageSize(this.getLength());
227 
228         // prepare order-by list for DataTable query criteria
229         DataTableQuerySortBy sortBy = new DataTableQuerySortBy();
230         if (!DataTableUtils.isObjectEmpty(this.getOrder())) {
231             getOrder().stream().forEach((col) -> {
232                 // add all order-by columns
233                 sortBy.addSort(col.getData(), DataTableQuerySortOrder.fromValue(col.getSortDir()));
234             });
235         }
236         queryCriteria.setSortBy(sortBy);
237 
238         DataTableQueryFilterBy filterBy = new DataTableQueryFilterBy();
239         filterBy.setGlobalSearch(this.isGlobalSearch());
240 
241         if (getColumns() != null) {
242             this.getColumns().stream().filter((colSpec) -> (colSpec.isSearchable())).filter((colSpec) -> (!DataTableUtils.isObjectEmpty(this.getSearch()) || !DataTableUtils.isObjectEmpty(colSpec.getSearch()))).forEachOrdered((colSpec) -> {
243                 filterBy.addFilter(colSpec.getData(), (this.isGlobalSearch()) ? this.getSearch() : colSpec.getSearch());
244             });
245             queryCriteria.setFilterBy(filterBy);
246         }
247 
248         return queryCriteria;
249     }
250 
251     public String getUniqueId() {
252         return uniqueId;
253     }
254 
255     public void setUniqueId(String uniqueId) {
256         this.uniqueId = uniqueId;
257     }
258 
259     public String getDraw() {
260         return draw;
261     }
262 
263     public void setDraw(String draw) {
264         this.draw = draw;
265     }
266 
267     public Long getStart() {
268         return start;
269     }
270 
271     public void setStart(Long start) {
272         this.start = start;
273     }
274 
275     public Long getLength() {
276         return length;
277     }
278 
279     public void setLength(Long length) {
280         this.length = length;
281     }
282 
283     public String getSearch() {
284         return search;
285     }
286 
287     public void setSearch(String search) {
288         this.search = search;
289     }
290 
291     public boolean isRegex() {
292         return regex;
293     }
294 
295     public void setRegex(boolean regex) {
296         this.regex = regex;
297     }
298 
299     public List<DataTableColumnSpecs> getColumns() {
300         return columns;
301     }
302 
303     public void setColumns(List<DataTableColumnSpecs> columns) {
304         this.columns = columns;
305     }
306 
307     public List<DataTableColumnSpecs> getOrder() {
308         return order;
309     }
310 
311     public void setOrder(List<DataTableColumnSpecs> order) {
312         this.order = order;
313     }
314 
315     public void addOrderByColumn(DataTableColumnSpecs column) {
316         if (this.order == null) {
317             this.order = new ArrayList<>();
318         }
319 
320         this.order.add(column);
321     }
322 
323     public boolean isGlobalSearch() {
324         return globalSearch;
325     }
326 
327     public void setGlobalSearch(boolean globalSearch) {
328         this.globalSearch = globalSearch;
329     }
330 
331     public int getMaxParamsToCheck() {
332         return maxParamsToCheck;
333     }
334 
335     public void setMaxParamsToCheck(int maxParamsToCheck) {
336         this.maxParamsToCheck = maxParamsToCheck;
337     }
338 
339     public Long getFilteredCount() {
340         return filteredCount;
341     }
342 
343     public void setFilteredCount(Long filteredCount) {
344         this.filteredCount = filteredCount;
345     }
346 
347     @Override
348     public String toString() {
349         return "DataTableRequest{" + "uniqueId=" + uniqueId + ", draw=" + draw + ", start=" + start + ", length=" + length + ", filtered=" + filteredCount + ", search=" + search + ", regex=" + regex + ", columns=" + columns + ", order=" + order + ", globalSearch=" + globalSearch + ", maxParamsToCheck=" + maxParamsToCheck + '}';
350     }
351 
352 }