1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.container;
17
18 import org.apache.commons.collections.ListUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.mo.common.active.Inactivatable;
21 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
22 import org.kuali.rice.krad.uif.UifConstants;
23 import org.kuali.rice.krad.uif.UifParameters;
24 import org.kuali.rice.krad.uif.UifPropertyPaths;
25 import org.kuali.rice.krad.uif.control.Control;
26 import org.kuali.rice.krad.uif.component.DataBinding;
27 import org.kuali.rice.krad.uif.field.ActionField;
28 import org.kuali.rice.krad.uif.field.InputField;
29 import org.kuali.rice.krad.uif.field.Field;
30 import org.kuali.rice.krad.uif.field.FieldGroup;
31 import org.kuali.rice.krad.uif.layout.CollectionLayoutManager;
32 import org.kuali.rice.krad.uif.service.ExpressionEvaluatorService;
33 import org.kuali.rice.krad.uif.util.ComponentUtils;
34 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
35 import org.kuali.rice.krad.uif.view.View;
36 import org.kuali.rice.krad.util.KRADUtils;
37 import org.kuali.rice.krad.util.ObjectUtils;
38 import org.kuali.rice.krad.web.form.UifFormBase;
39
40 import java.io.Serializable;
41 import java.util.ArrayList;
42 import java.util.Collection;
43 import java.util.HashMap;
44 import java.util.List;
45 import java.util.Map;
46
47
48
49
50
51
52
53
54
55 public class CollectionGroupBuilder implements Serializable {
56 private static final long serialVersionUID = -4762031957079895244L;
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public void build(View view, Object model, CollectionGroup collectionGroup) {
79
80 if (collectionGroup.isRenderAddLine() && !collectionGroup.isReadOnly()) {
81 buildAddLine(view, model, collectionGroup);
82 }
83
84
85 List<Object> modelCollection = ObjectPropertyUtils.getPropertyValue(model, ((DataBinding) collectionGroup)
86 .getBindingInfo().getBindingPath());
87
88 if (modelCollection != null) {
89
90 List<Integer> showIndexes = performCollectionFiltering(view, model, collectionGroup, modelCollection);
91
92
93 for (int index = 0; index < modelCollection.size(); index++) {
94
95 if (showIndexes.contains(index)) {
96 String bindingPathPrefix = collectionGroup.getBindingInfo().getBindingName() + "[" + index + "]";
97 if (StringUtils.isNotBlank(collectionGroup.getBindingInfo().getBindByNamePrefix())) {
98 bindingPathPrefix =
99 collectionGroup.getBindingInfo().getBindByNamePrefix() + "." + bindingPathPrefix;
100 }
101
102 Object currentLine = modelCollection.get(index);
103
104 List<ActionField> actions = getLineActions(view, model, collectionGroup, currentLine, index);
105 buildLine(view, model, collectionGroup, bindingPathPrefix, actions, false, currentLine, index);
106 }
107 }
108 }
109 }
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 protected List<Integer> performCollectionFiltering(View view, Object model, CollectionGroup collectionGroup,
127 Collection<?> collection) {
128 List<Integer> filteredIndexes = new ArrayList<Integer>();
129 for (int i = 0; i < collection.size(); i++) {
130 filteredIndexes.add(new Integer(i));
131 }
132
133 if (Inactivatable.class.isAssignableFrom(collectionGroup.getCollectionObjectClass()) && !collectionGroup
134 .isShowInactive()) {
135 List<Integer> activeIndexes = collectionGroup.getActiveCollectionFilter().filter(view, model,
136 collectionGroup);
137 filteredIndexes = ListUtils.intersection(filteredIndexes, activeIndexes);
138 }
139
140 for (CollectionFilter collectionFilter : collectionGroup.getFilters()) {
141 List<Integer> indexes = collectionFilter.filter(view, model, collectionGroup);
142 filteredIndexes = ListUtils.intersection(filteredIndexes, indexes);
143 if (filteredIndexes.isEmpty()) {
144 break;
145 }
146 }
147
148 return filteredIndexes;
149 }
150
151
152
153
154
155
156
157
158
159
160
161
162
163 protected void buildAddLine(View view, Object model, CollectionGroup collectionGroup) {
164 boolean addLineBindsToForm = false;
165
166
167 initializeNewCollectionLine(view, model, collectionGroup, false);
168
169
170
171 if (StringUtils.isBlank(collectionGroup.getAddLinePropertyName())) {
172 addLineBindsToForm = true;
173 }
174
175 String addLineBindingPath = collectionGroup.getAddLineBindingInfo().getBindingPath();
176 List<ActionField> actions = getAddLineActions(view, model, collectionGroup);
177
178 Object addLine = ObjectPropertyUtils.getPropertyValue(model, addLineBindingPath);
179 buildLine(view, model, collectionGroup, addLineBindingPath, actions, addLineBindsToForm, addLine, -1);
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
205
206
207
208 @SuppressWarnings("unchecked")
209 protected void buildLine(View view, Object model, CollectionGroup collectionGroup, String bindingPath,
210 List<ActionField> actions, boolean bindToForm, Object currentLine, int lineIndex) {
211 CollectionLayoutManager layoutManager = (CollectionLayoutManager) collectionGroup.getLayoutManager();
212
213
214 List<Field> lineFields = (List<Field>) collectionGroup.getItems();
215 String lineSuffix = UifConstants.IdSuffixes.LINE + Integer.toString(lineIndex);
216 if (lineIndex == -1) {
217 lineFields = (List<Field>) collectionGroup.getAddLineFields();
218 lineSuffix = UifConstants.IdSuffixes.ADD_LINE;
219 }
220 if (StringUtils.isNotBlank(collectionGroup.getSubCollectionSuffix())) {
221 lineSuffix = collectionGroup.getSubCollectionSuffix() + lineSuffix;
222 }
223
224 lineFields = (List<Field>) ComponentUtils.copyFieldList(lineFields, bindingPath, lineSuffix);
225
226 if(lineIndex == -1 && !lineFields.isEmpty()){
227 for(Field f: lineFields){
228 if(f instanceof InputField){
229
230
231 Control control = ((InputField) f).getControl();
232 if (control != null) {
233 control.addStyleClass(collectionGroup.getFactoryId() + "-addField");
234 control.addStyleClass("ignoreValid");
235 }
236 }
237 }
238 for(ActionField action: actions){
239 if(action.getActionParameter(UifParameters.ACTION_TYPE).equals(UifParameters.ADD_LINE)){
240 action.setFocusOnAfterSubmit(lineFields.get(0).getId());
241 }
242 }
243 }
244
245 ComponentUtils.updateContextsForLine(lineFields, currentLine, lineIndex);
246
247 if (bindToForm) {
248 ComponentUtils.setComponentsPropertyDeep(lineFields, UifPropertyPaths.BIND_TO_FORM, new Boolean(true));
249 }
250
251
252 lineFields = removeNonRenderLineFields(view, model, collectionGroup, lineFields, currentLine, lineIndex);
253
254
255 List<FieldGroup> subCollectionFields = new ArrayList<FieldGroup>();
256 if ((lineIndex != -1) && (collectionGroup.getSubCollections() != null)) {
257 for (int subLineIndex = 0; subLineIndex < collectionGroup.getSubCollections().size(); subLineIndex++) {
258 CollectionGroup subCollectionPrototype = collectionGroup.getSubCollections().get(subLineIndex);
259 CollectionGroup subCollectionGroup = ComponentUtils.copy(subCollectionPrototype, lineSuffix);
260
261
262 boolean renderSubCollection = checkSubCollectionRender(view, model, collectionGroup,
263 subCollectionGroup);
264 if (!renderSubCollection) {
265 continue;
266 }
267
268 subCollectionGroup.getBindingInfo().setBindByNamePrefix(bindingPath);
269 if (subCollectionGroup.isRenderAddLine()) {
270 subCollectionGroup.getAddLineBindingInfo().setBindByNamePrefix(bindingPath);
271 }
272
273
274 String subCollectionSuffix = lineSuffix;
275 if (StringUtils.isNotBlank(subCollectionGroup.getSubCollectionSuffix())) {
276 subCollectionSuffix = subCollectionGroup.getSubCollectionSuffix() + lineSuffix;
277 }
278 subCollectionGroup.setSubCollectionSuffix(subCollectionSuffix);
279
280 FieldGroup fieldGroupPrototype = layoutManager.getSubCollectionFieldGroupPrototype();
281 FieldGroup subCollectionFieldGroup = ComponentUtils.copy(fieldGroupPrototype,
282 lineSuffix + UifConstants.IdSuffixes.SUB + subLineIndex);
283 subCollectionFieldGroup.setGroup(subCollectionGroup);
284
285 subCollectionFields.add(subCollectionFieldGroup);
286 }
287 }
288
289
290 layoutManager.buildLine(view, model, collectionGroup, lineFields, subCollectionFields, bindingPath, actions,
291 lineSuffix, currentLine, lineIndex);
292 }
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 protected List<Field> removeNonRenderLineFields(View view, Object model, CollectionGroup collectionGroup,
318 List<Field> lineFields, Object currentLine, int lineIndex) {
319 List<Field> fields = new ArrayList<Field>();
320
321 for (Field lineField : lineFields) {
322 String conditionalRender = lineField.getPropertyExpression("render");
323
324
325 if (StringUtils.isNotBlank(conditionalRender)) {
326 Map<String, Object> context = new HashMap<String, Object>();
327 context.putAll(view.getContext());
328 context.put(UifConstants.ContextVariableNames.PARENT, collectionGroup);
329 context.put(UifConstants.ContextVariableNames.COMPONENT, lineField);
330 context.put(UifConstants.ContextVariableNames.LINE, currentLine);
331 context.put(UifConstants.ContextVariableNames.INDEX, new Integer(lineIndex));
332 context.put(UifConstants.ContextVariableNames.IS_ADD_LINE, new Boolean(lineIndex == -1));
333
334 Boolean render = (Boolean) getExpressionEvaluatorService().evaluateExpression(model, context,
335 conditionalRender);
336 lineField.setRender(render);
337 }
338
339
340 if (lineField.isRender() || StringUtils.isNotBlank(lineField.getProgressiveRender())) {
341 fields.add(lineField);
342 }
343 }
344
345 return fields;
346 }
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363 protected boolean checkSubCollectionRender(View view, Object model, CollectionGroup collectionGroup,
364 CollectionGroup subCollectionGroup) {
365 String conditionalRender = subCollectionGroup.getPropertyExpression("render");
366
367
368 if (StringUtils.isNotBlank(conditionalRender)) {
369 Map<String, Object> context = new HashMap<String, Object>();
370 context.putAll(view.getContext());
371 context.put(UifConstants.ContextVariableNames.PARENT, collectionGroup);
372 context.put(UifConstants.ContextVariableNames.COMPONENT, subCollectionGroup);
373
374 Boolean render = (Boolean) getExpressionEvaluatorService().evaluateExpression(model, context,
375 conditionalRender);
376 subCollectionGroup.setRender(render);
377 }
378
379 return subCollectionGroup.isRender();
380 }
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 protected List<ActionField> getLineActions(View view, Object model, CollectionGroup collectionGroup,
402 Object collectionLine, int lineIndex) {
403 List<ActionField> lineActions = ComponentUtils.copyFieldList(collectionGroup.getActionFields(), Integer.toString(lineIndex));
404 for (ActionField actionField : lineActions) {
405 actionField.addActionParameter(UifParameters.SELLECTED_COLLECTION_PATH, collectionGroup.getBindingInfo()
406 .getBindingPath());
407 actionField.addActionParameter(UifParameters.SELECTED_LINE_INDEX, Integer.toString(lineIndex));
408 actionField.setJumpToIdAfterSubmit(collectionGroup.getId() + "_div");
409
410 actionField.setClientSideJs("performCollectionAction('"+collectionGroup.getId()+"');");
411 }
412
413 ComponentUtils.updateContextsForLine(lineActions, collectionLine, lineIndex);
414
415 return lineActions;
416 }
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433 protected List<ActionField> getAddLineActions(View view, Object model, CollectionGroup collectionGroup) {
434 List<ActionField> lineActions = ComponentUtils.copyFieldList(collectionGroup.getAddLineActionFields(), "_add");
435 for (ActionField actionField : lineActions) {
436 actionField.addActionParameter(UifParameters.SELLECTED_COLLECTION_PATH, collectionGroup.getBindingInfo()
437 .getBindingPath());
438
439 actionField.setJumpToIdAfterSubmit(collectionGroup.getId() + "_div");
440 actionField.addActionParameter(UifParameters.ACTION_TYPE, UifParameters.ADD_LINE);
441
442 String baseId = collectionGroup.getFactoryId();
443 if (StringUtils.isNotBlank(collectionGroup.getSubCollectionSuffix())) {
444 baseId += collectionGroup.getSubCollectionSuffix();
445 }
446
447 actionField.setClientSideJs("addLineToCollection('"+collectionGroup.getId()+"', '"+ baseId +"');");
448 }
449
450
451 String addLinePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
452 Object addLine = ObjectPropertyUtils.getPropertyValue(model, addLinePath);
453
454 ComponentUtils.updateContextsForLine(lineActions, addLine, -1);
455
456 return lineActions;
457 }
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478 public void initializeNewCollectionLine(View view, Object model, CollectionGroup collectionGroup,
479 boolean clearExistingLine) {
480 Object newLine = null;
481
482
483 if (StringUtils.isBlank(collectionGroup.getAddLinePropertyName())) {
484
485 if (!(model instanceof UifFormBase)) {
486 throw new RuntimeException("Cannot create new collection line for group: "
487 + collectionGroup.getPropertyName() + ". Model does not extend " + UifFormBase.class.getName());
488 }
489
490
491 Map<String, Object> newCollectionLines = ObjectPropertyUtils.getPropertyValue(model,
492 UifPropertyPaths.NEW_COLLECTION_LINES);
493 if (newCollectionLines == null) {
494 newCollectionLines = new HashMap<String, Object>();
495 ObjectPropertyUtils.setPropertyValue(model, UifPropertyPaths.NEW_COLLECTION_LINES, newCollectionLines);
496 }
497
498
499 String newCollectionLineKey = KRADUtils
500 .translateToMapSafeKey(collectionGroup.getBindingInfo().getBindingPath());
501 String addLineBindingPath = UifPropertyPaths.NEW_COLLECTION_LINES + "['" + newCollectionLineKey + "']";
502 collectionGroup.getAddLineBindingInfo().setBindingPath(addLineBindingPath);
503
504
505
506 if (!newCollectionLines.containsKey(newCollectionLineKey)
507 || (newCollectionLines.get(newCollectionLineKey) == null) || clearExistingLine) {
508
509 newLine = ObjectUtils.newInstance(collectionGroup.getCollectionObjectClass());
510 newCollectionLines.put(newCollectionLineKey, newLine);
511 }
512 } else {
513
514 Object addLine = ObjectPropertyUtils.getPropertyValue(model, collectionGroup.getAddLineBindingInfo()
515 .getBindingPath());
516 if ((addLine == null) || clearExistingLine) {
517 newLine = ObjectUtils.newInstance(collectionGroup.getCollectionObjectClass());
518 ObjectPropertyUtils.setPropertyValue(model, collectionGroup.getAddLineBindingInfo().getBindingPath(),
519 newLine);
520 }
521 }
522
523
524 if (newLine != null) {
525 view.getViewHelperService().applyDefaultValuesForCollectionLine(view, model, collectionGroup, newLine);
526 }
527 }
528
529 protected ExpressionEvaluatorService getExpressionEvaluatorService() {
530 return KRADServiceLocatorWeb.getExpressionEvaluatorService();
531 }
532
533 }