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