1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.web.controller.helper;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.krad.uif.UifConstants;
21 import org.kuali.rice.krad.uif.UifParameters;
22 import org.kuali.rice.krad.uif.component.BindingInfo;
23 import org.kuali.rice.krad.uif.container.CollectionGroup;
24 import org.kuali.rice.krad.uif.layout.TableLayoutManager;
25 import org.kuali.rice.krad.uif.util.ColumnSort;
26 import org.kuali.rice.krad.uif.util.ComponentFactory;
27 import org.kuali.rice.krad.uif.util.MultiColumnComparator;
28 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
29 import org.kuali.rice.krad.uif.view.View;
30 import org.kuali.rice.krad.web.form.UifFormBase;
31
32 import javax.json.Json;
33 import javax.json.JsonArray;
34 import javax.json.JsonObject;
35 import javax.json.JsonReader;
36 import javax.servlet.http.HttpServletRequest;
37 import java.io.StringReader;
38 import java.util.ArrayList;
39 import java.util.Arrays;
40 import java.util.List;
41
42
43
44
45 public class DataTablesPagingHelper {
46
47 private int totalCollectionSize;
48 private Integer filteredCollectionSize;
49
50 private TableLayoutManager tableLayoutManager;
51
52 public void processPagingRequest(View view, String tableId, UifFormBase form, DataTablesInputs dataTablesInputs) {
53
54 form.setRequestJsonTemplate(UifConstants.TableToolsValues.JSON_TEMPLATE);
55
56 if (view != null) {
57
58 form.setUpdateComponentId(tableId);
59
60 @SuppressWarnings("unchecked") List<ColumnSort> oldColumnSorts =
61 (List<ColumnSort>) form.getExtensionData().get(tableId + UifConstants.IdSuffixes.COLUMN_SORTS);
62
63
64 CollectionGroup newCollectionGroup = null;
65 List<Object> modelCollection = null;
66 List<ColumnSort> newColumnSorts = null;
67
68 synchronized (view) {
69
70 CollectionGroup oldCollectionGroup = (CollectionGroup) view.getViewIndex().getComponentById(tableId);
71 newColumnSorts = buildColumnSorts(view, dataTablesInputs, oldCollectionGroup);
72
73
74 modelCollection = ObjectPropertyUtils.getPropertyValue(form,
75 oldCollectionGroup.getBindingInfo().getBindingPath());
76
77 applyTableJsonSort(modelCollection, oldColumnSorts, newColumnSorts, oldCollectionGroup, view);
78
79
80 newCollectionGroup = (CollectionGroup) ComponentFactory.getNewInstanceForRefresh(form.getPostedView(),
81 tableId);
82
83
84
85 newCollectionGroup.setUseServerPaging(true);
86 newCollectionGroup.setDisplayStart(dataTablesInputs.iDisplayStart);
87 newCollectionGroup.setDisplayLength(dataTablesInputs.iDisplayLength);
88
89
90 view.getViewHelperService().performComponentLifecycle(view, form, newCollectionGroup,
91 oldCollectionGroup.getId());
92 }
93
94 this.tableLayoutManager = (TableLayoutManager) newCollectionGroup.getLayoutManager();
95 this.filteredCollectionSize = newCollectionGroup.getFilteredCollectionSize();
96 this.totalCollectionSize = modelCollection.size();
97
98
99
100 form.getExtensionData().put(tableId + "_columnSorts", newColumnSorts);
101 }
102 }
103
104
105
106
107
108
109
110
111 private List<ColumnSort> buildColumnSorts(View view, DataTablesInputs dataTablesInputs, CollectionGroup collectionGroup) {
112 int[] sortCols = dataTablesInputs.iSortCol_;
113 boolean[] sortable = dataTablesInputs.bSortable_;
114 String[] sortDir = dataTablesInputs.sSortDir_;
115
116
117 String aoColumnDefsValue = (String) view.getViewIndex().getPostContextEntry(collectionGroup.getId(),
118 UifConstants.TableToolsKeys.AO_COLUMN_DEFS);
119 JsonArray jsonColumnDefs = null;
120
121 if (!StringUtils.isEmpty(aoColumnDefsValue)) {
122
123 aoColumnDefsValue = aoColumnDefsValue.replaceAll("function\\([^)]*\\)\\s*\\{[^}]*\\}", "\"REDACTED\"");
124 JsonReader jsonReader = Json.createReader(new StringReader(aoColumnDefsValue));
125 jsonColumnDefs = jsonReader.readArray();
126 }
127
128 List<ColumnSort> columnSorts = new ArrayList<ColumnSort>(sortCols.length);
129
130 for (int sortColsIndex = 0; sortColsIndex < sortCols.length; sortColsIndex++) {
131 int sortCol = sortCols[sortColsIndex];
132
133 if (sortable[sortCol]) {
134 String sortType = getSortType(jsonColumnDefs, sortCol);
135 ColumnSort.Direction sortDirection = ColumnSort.Direction.valueOf(sortDir[sortColsIndex].toUpperCase());
136 columnSorts.add(new ColumnSort(sortCol, sortDirection, sortType));
137 }
138 }
139
140 return columnSorts;
141 }
142
143
144
145
146
147
148
149
150
151
152 private String getSortType(JsonArray jsonColumnDefs, int sortCol) {
153 String sortType = "string";
154
155 if (jsonColumnDefs != null) {
156 JsonObject column = jsonColumnDefs.getJsonObject(sortCol);
157
158 if (column.containsKey("sType")) {
159 sortType = column.getString("sType");
160 }
161 }
162 return sortType;
163 }
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 protected void applyTableJsonSort(List<Object> modelCollection, List<ColumnSort> oldColumnSorts,
205 List<ColumnSort> newColumnSorts, CollectionGroup collectionGroup, View view) {
206
207 boolean isCollectionEmpty = CollectionUtils.isEmpty(modelCollection);
208 boolean isSortingSpecified = !CollectionUtils.isEmpty(newColumnSorts);
209 boolean isSortOrderChanged = newColumnSorts != oldColumnSorts && !newColumnSorts.equals(oldColumnSorts);
210
211 if (!isCollectionEmpty && isSortingSpecified && isSortOrderChanged) {
212 Integer[] sortIndices = new Integer[modelCollection.size()];
213 for (int i = 0; i < sortIndices.length; i++) {
214 sortIndices[i] = i;
215 }
216
217 Arrays.sort(sortIndices, new MultiColumnComparator(modelCollection, collectionGroup, newColumnSorts, view));
218
219
220 Object[] sorted = new Object[sortIndices.length];
221 for (int i = 0; i < sortIndices.length; i++) {
222 sorted[i] = modelCollection.get(sortIndices[i]);
223 }
224 for (int i = 0; i < sorted.length; i++) {
225 modelCollection.set(i, sorted[i]);
226 }
227 }
228 }
229
230 public int getTotalCollectionSize() {
231 return totalCollectionSize;
232 }
233
234 public Integer getFilteredCollectionSize() {
235 return filteredCollectionSize;
236 }
237
238 public TableLayoutManager getTableLayoutManager() {
239 return tableLayoutManager;
240 }
241
242
243
244
245
246
247 public static class DataTablesInputs {
248 private static final String DISPLAY_START = "iDisplayStart";
249 private static final String DISPLAY_LENGTH = "iDisplayLength";
250 private static final String COLUMNS = "iColumns";
251 private static final String REGEX = "bRegex";
252 private static final String REGEX_PREFIX = "bRegex_";
253 private static final String SORTABLE_PREFIX = "bSortable_";
254 private static final String SORTING_COLS = "iSortingCols";
255 private static final String SORT_COL_PREFIX = "iSortCol_";
256 private static final String SORT_DIR_PREFIX = "sSortDir_";
257 private static final String DATA_PROP_PREFIX = "mDataProp_";
258 private static final String ECHO = "sEcho";
259
260 private final int iDisplayStart, iDisplayLength, iColumns, iSortingCols, sEcho;
261
262
263
264
265
266
267
268
269 private final boolean bRegex;
270 private final boolean[] bRegex_, bSortable_;
271 private final String[] sSortDir_, mDataProp_;
272
273
274
275 private final int[] iSortCol_;
276
277 public DataTablesInputs(HttpServletRequest request) {
278 String s;
279 iDisplayStart = (s = request.getParameter(DISPLAY_START)) == null ? 0 : Integer.parseInt(s);
280 iDisplayLength = (s = request.getParameter(DISPLAY_LENGTH)) == null ? 0 : Integer.parseInt(s);
281 iColumns = (s = request.getParameter(COLUMNS)) == null ? 0 : Integer.parseInt(s);
282 bRegex = (s = request.getParameter(REGEX)) == null ? false : new Boolean(s);
283
284
285
286
287
288
289
290 bRegex_ = new boolean[iColumns];
291 bSortable_ = new boolean[iColumns];
292
293 for (int i = 0; i < iColumns; i++) {
294
295
296
297
298 bRegex_[i] = (s = request.getParameter(REGEX_PREFIX + i)) == null ? false : new Boolean(s);
299
300
301
302
303
304 bSortable_[i] = (s = request.getParameter(SORTABLE_PREFIX + i)) == null ? false : new Boolean(s);
305 }
306
307 iSortingCols = (s = request.getParameter(SORTING_COLS)) == null ? 0 : Integer.parseInt(s);
308 iSortCol_ = new int[iSortingCols];
309 sSortDir_ = new String[iSortingCols];
310
311 for (int i = 0; i < iSortingCols; i++) {
312 iSortCol_[i] = (s = request.getParameter(SORT_COL_PREFIX + i)) == null ? 0 : Integer.parseInt(s);
313 sSortDir_[i] = request.getParameter(SORT_DIR_PREFIX + i);
314 }
315
316 mDataProp_ = new String[iColumns];
317
318 for (int i = 0; i < iColumns; i++) {
319 mDataProp_[i] = request.getParameter(DATA_PROP_PREFIX + i);
320 }
321
322 sEcho = (s = request.getParameter(ECHO)) == null ? 0 : Integer.parseInt(s);
323 }
324
325 @Override
326 public String toString() {
327 StringBuilder sb = new StringBuilder(super.toString());
328 sb.append("\n\t" + DISPLAY_START + " = ");
329 sb.append(iDisplayStart);
330 sb.append("\n\t" + DISPLAY_LENGTH + " = ");
331 sb.append(iDisplayLength);
332 sb.append("\n\t" + COLUMNS + " = ");
333 sb.append(iColumns);
334
335
336
337
338 sb.append("\n\t" + REGEX + " = ");
339 sb.append(bRegex);
340
341 for (int i = 0; i < iColumns; i++) {
342
343
344
345
346
347
348
349 sb.append("\n\t").append(REGEX_PREFIX).append(i).append(" = ");
350 sb.append(bRegex_[i]);
351 sb.append("\n\t").append(SORTABLE_PREFIX).append(i).append(" = ");
352 sb.append(bSortable_[i]);
353 }
354
355 sb.append("\n\t").append(SORTING_COLS);
356 sb.append(iSortingCols);
357
358 for (int i = 0; i < iSortingCols; i++) {
359 sb.append("\n\t").append(SORT_COL_PREFIX).append(i).append(" = ");
360 sb.append(iSortCol_[i]);
361 sb.append("\n\t").append(SORT_DIR_PREFIX).append(i).append(" = ");
362 sb.append(sSortDir_[i]);
363 }
364
365 for (int i = 0; i < iColumns; i++) {
366 sb.append("\n\t").append(DATA_PROP_PREFIX).append(i).append(" = ");
367 sb.append(mDataProp_[i]);
368 }
369
370 sb.append("\n\t" + ECHO + " = ");
371 sb.append(sEcho);
372
373 return sb.toString();
374 }
375 }
376 }