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.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.kuali.rice.core.api.mo.common.active.Inactivatable;
23 import org.kuali.rice.kim.api.identity.Person;
24 import org.kuali.rice.krad.uif.UifConstants;
25 import org.kuali.rice.krad.uif.UifParameters;
26 import org.kuali.rice.krad.uif.UifPropertyPaths;
27 import org.kuali.rice.krad.uif.component.Component;
28 import org.kuali.rice.krad.uif.component.ComponentSecurity;
29 import org.kuali.rice.krad.uif.component.DataBinding;
30 import org.kuali.rice.krad.uif.control.Control;
31 import org.kuali.rice.krad.uif.control.ControlBase;
32 import org.kuali.rice.krad.uif.element.Action;
33 import org.kuali.rice.krad.uif.field.Field;
34 import org.kuali.rice.krad.uif.field.FieldGroup;
35 import org.kuali.rice.krad.uif.field.InputField;
36 import org.kuali.rice.krad.uif.field.RemoteFieldsHolder;
37 import org.kuali.rice.krad.uif.layout.CollectionLayoutManager;
38 import org.kuali.rice.krad.uif.util.ComponentUtils;
39 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
40 import org.kuali.rice.krad.uif.util.ScriptUtils;
41 import org.kuali.rice.krad.uif.view.ExpressionEvaluator;
42 import org.kuali.rice.krad.uif.view.View;
43 import org.kuali.rice.krad.uif.view.ViewAuthorizer;
44 import org.kuali.rice.krad.uif.view.ViewModel;
45 import org.kuali.rice.krad.uif.view.ViewPresentationController;
46 import org.kuali.rice.krad.util.GlobalVariables;
47 import org.kuali.rice.krad.util.KRADUtils;
48 import org.kuali.rice.krad.util.ObjectUtils;
49 import org.kuali.rice.krad.web.form.UifFormBase;
50
51 import java.io.Serializable;
52 import java.util.ArrayList;
53 import java.util.Collection;
54 import java.util.HashMap;
55 import java.util.List;
56 import java.util.Map;
57
58
59
60
61
62
63
64
65
66 public class CollectionGroupBuilder implements Serializable {
67 private static final long serialVersionUID = -4762031957079895244L;
68 private static Log LOG = LogFactory.getLog(CollectionGroupBuilder.class);
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 public void build(View view, Object model, CollectionGroup collectionGroup) {
91
92 if (collectionGroup.isRenderAddLine() && !collectionGroup.isReadOnly() &&
93 !collectionGroup.isRenderAddBlankLineButton()) {
94 buildAddLine(view, model, collectionGroup);
95 }
96
97
98 if (collectionGroup.isRenderAddBlankLineButton() && (collectionGroup.getAddBlankLineAction() != null)) {
99 collectionGroup.getAddBlankLineAction().setRefreshId(collectionGroup.getId());
100 }
101
102
103 List<Object> modelCollection = ObjectPropertyUtils.getPropertyValue(model,
104 ((DataBinding) collectionGroup).getBindingInfo().getBindingPath());
105
106 if (modelCollection != null) {
107
108 List<Integer> showIndexes = performCollectionFiltering(view, model, collectionGroup, modelCollection);
109
110 if (collectionGroup.getDisplayCollectionSize() != -1 && showIndexes.size() > collectionGroup
111 .getDisplayCollectionSize()) {
112
113 List<Integer> newShowIndexes = new ArrayList<Integer>();
114 Integer counter = 0;
115
116 for (int index = 0; index < showIndexes.size(); index++) {
117 newShowIndexes.add(showIndexes.get(index));
118
119 counter++;
120
121 if (counter == collectionGroup.getDisplayCollectionSize()) {
122 break;
123 }
124 }
125
126 showIndexes = newShowIndexes;
127 }
128
129 List<IndexedElement> filteredIndexedElements = buildFilteredIndexedCollection(showIndexes, modelCollection);
130
131 collectionGroup.setFilteredCollectionSize(filteredIndexedElements.size());
132 buildLinesForDisplayedRows(filteredIndexedElements, view, model, collectionGroup);
133 }
134 }
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 private List<IndexedElement> buildFilteredIndexedCollection(List<Integer> showIndexes,
152 List<Object> modelCollection) {
153 List<IndexedElement> filteredIndexedElements = new ArrayList<IndexedElement>(modelCollection.size());
154 for (Integer showIndex : showIndexes) {
155 filteredIndexedElements.add(new IndexedElement(showIndex, modelCollection.get(showIndex)));
156 }
157 return filteredIndexedElements;
158 }
159
160
161
162
163
164
165
166
167
168 protected void buildLinesForDisplayedRows(List<IndexedElement> filteredIndexedElements, View view, Object model,
169 CollectionGroup collectionGroup) {
170
171
172 if (collectionGroup.isUseServerPaging() && collectionGroup.getDisplayLength() == -1) {
173 collectionGroup.setDisplayLength(1);
174 }
175
176 final int displayStart = (collectionGroup.getDisplayStart() != -1) ? collectionGroup.getDisplayStart() : 0;
177
178 final int displayLength = (collectionGroup.getDisplayLength() != -1) ? collectionGroup.getDisplayLength() :
179 filteredIndexedElements.size() - displayStart;
180
181
182 final int displayEndExclusive =
183 (displayStart + displayLength > filteredIndexedElements.size()) ? filteredIndexedElements.size() :
184 displayStart + displayLength;
185
186
187 final List<IndexedElement> renderedIndexedElements = filteredIndexedElements.subList(displayStart,
188 displayEndExclusive);
189
190
191 for (IndexedElement indexedElement : renderedIndexedElements) {
192 final Object currentLine = indexedElement.element;
193
194 String bindingPathPrefix =
195 collectionGroup.getBindingInfo().getBindingName() + "[" + indexedElement.index + "]";
196
197 if (StringUtils.isNotBlank(collectionGroup.getBindingInfo().getBindByNamePrefix())) {
198 bindingPathPrefix = collectionGroup.getBindingInfo().getBindByNamePrefix() + "." + bindingPathPrefix;
199 }
200
201 List<Action> lineActions = initializeLineActions(collectionGroup.getLineActions(), view, model,
202 collectionGroup, currentLine, indexedElement.index);
203
204 buildLine(view, model, collectionGroup, bindingPathPrefix, lineActions, false, currentLine,
205 indexedElement.index);
206 }
207 }
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 protected List<Integer> performCollectionFiltering(View view, Object model, CollectionGroup collectionGroup,
225 Collection<?> collection) {
226 List<Integer> filteredIndexes = new ArrayList<Integer>();
227 for (int i = 0; i < collection.size(); i++) {
228 filteredIndexes.add(Integer.valueOf(i));
229 }
230
231 if (Inactivatable.class.isAssignableFrom(collectionGroup.getCollectionObjectClass()) && !collectionGroup
232 .isShowInactiveLines()) {
233 List<Integer> activeIndexes = collectionGroup.getActiveCollectionFilter().filter(view, model,
234 collectionGroup);
235 filteredIndexes = ListUtils.intersection(filteredIndexes, activeIndexes);
236 }
237
238 for (CollectionFilter collectionFilter : collectionGroup.getFilters()) {
239 List<Integer> indexes = collectionFilter.filter(view, model, collectionGroup);
240 filteredIndexes = ListUtils.intersection(filteredIndexes, indexes);
241 if (filteredIndexes.isEmpty()) {
242 break;
243 }
244 }
245
246 return filteredIndexes;
247 }
248
249
250
251
252
253
254
255
256
257
258 protected void buildAddLine(View view, Object model, CollectionGroup collectionGroup) {
259 boolean addLineBindsToForm = false;
260
261
262 initializeNewCollectionLine(view, model, collectionGroup, false);
263
264
265
266 if (StringUtils.isBlank(collectionGroup.getAddLinePropertyName())) {
267 addLineBindsToForm = true;
268 }
269
270 String addLineBindingPath = collectionGroup.getAddLineBindingInfo().getBindingPath();
271 List<Action> actions = getAddLineActions(view, model, collectionGroup);
272
273 Object addLine = ObjectPropertyUtils.getPropertyValue(model, addLineBindingPath);
274 buildLine(view, model, collectionGroup, addLineBindingPath, actions, addLineBindsToForm, addLine, -1);
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295 @SuppressWarnings("unchecked")
296 protected void buildLine(View view, Object model, CollectionGroup collectionGroup, String bindingPath,
297 List<Action> actions, boolean bindToForm, Object currentLine, int lineIndex) {
298 CollectionLayoutManager layoutManager = (CollectionLayoutManager) collectionGroup.getLayoutManager();
299
300
301 List<? extends Component> lineItems = null;
302 String lineSuffix = null;
303 if (lineIndex == -1) {
304 lineItems = ComponentUtils.copyComponentList(collectionGroup.getAddLineItems(), null);
305 lineSuffix = UifConstants.IdSuffixes.ADD_LINE;
306 } else {
307 lineItems = ComponentUtils.copyComponentList(collectionGroup.getItems(), null);
308 lineSuffix = UifConstants.IdSuffixes.LINE + Integer.toString(lineIndex);
309 }
310
311 if (StringUtils.isNotBlank(collectionGroup.getSubCollectionSuffix())) {
312 lineSuffix = collectionGroup.getSubCollectionSuffix() + lineSuffix;
313 }
314
315
316 List<Field> lineFields = processAnyRemoteFieldsHolder(view, model, collectionGroup, lineItems);
317
318
319 ComponentUtils.bindAndIdFieldList(lineFields, bindingPath, lineSuffix);
320
321
322
323 for (Field field : lineFields) {
324 List<CollectionGroup> components = ComponentUtils.getComponentsOfTypeDeep(field, CollectionGroup.class);
325 for (CollectionGroup fieldCollectionGroup : components) {
326 ComponentUtils.prefixBindingPath(fieldCollectionGroup, bindingPath);
327 fieldCollectionGroup.setSubCollectionSuffix(lineSuffix);
328 }
329 }
330
331 boolean readOnlyLine = collectionGroup.isReadOnly();
332
333
334 ComponentUtils.updateContextsForLine(lineFields, currentLine, lineIndex, lineSuffix);
335
336 for (Action action : actions) {
337 if (action != null && StringUtils.isNotBlank(action.getFocusOnIdAfterSubmit()) &&
338 action.getFocusOnIdAfterSubmit().equalsIgnoreCase(UifConstants.Order.LINE_FIRST.toString()) && (
339 lineFields.size()
340 > 0)) {
341 action.setFocusOnIdAfterSubmit(lineFields.get(0).getId() + UifConstants.IdSuffixes.CONTROL);
342 }
343 }
344
345
346 if (lineIndex == -1) {
347
348 } else {
349
350 boolean canViewLine = checkViewLineAuthorizationAndPresentationLogic(view, (ViewModel) model,
351 collectionGroup, currentLine);
352
353
354 if (!canViewLine) {
355 return;
356 }
357
358
359 if (!collectionGroup.isReadOnly()) {
360 readOnlyLine = !checkEditLineAuthorizationAndPresentationLogic(view, (ViewModel) model, collectionGroup,
361 currentLine);
362
363
364 if (!readOnlyLine && !((UifFormBase) model).isAddedCollectionItem(currentLine) &&
365 collectionGroup.isRenderSaveLineActions()) {
366 for (Field f : lineFields) {
367 if (f instanceof InputField && f.isRender()) {
368 ControlBase control = (ControlBase) ((InputField) f).getControl();
369 control.setOnChangeScript(control.getOnChangeScript() == null ?
370 ";collectionLineChanged(this, 'uif-newCollectionItem');" :
371 control.getOnChangeScript()
372 + ";collectionLineChanged(this, 'uif-newCollectionItem');");
373 }
374 }
375 }
376 }
377
378 ComponentUtils.pushObjectToContext(lineFields, UifConstants.ContextVariableNames.READONLY_LINE,
379 readOnlyLine);
380 ComponentUtils.pushObjectToContext(actions, UifConstants.ContextVariableNames.READONLY_LINE, readOnlyLine);
381 }
382
383
384 applyLineFieldAuthorizationAndPresentationLogic(view, (ViewModel) model, collectionGroup, currentLine,
385 readOnlyLine, lineFields, actions);
386
387 if (bindToForm) {
388 ComponentUtils.setComponentsPropertyDeep(lineFields, UifPropertyPaths.BIND_TO_FORM, Boolean.valueOf(true));
389 }
390
391
392 lineFields = removeNonRenderLineFields(view, model, collectionGroup, lineFields, currentLine, lineIndex);
393
394
395 List<FieldGroup> subCollectionFields = new ArrayList<FieldGroup>();
396 if ((lineIndex != -1) && (collectionGroup.getSubCollections() != null)) {
397 for (int subLineIndex = 0; subLineIndex < collectionGroup.getSubCollections().size(); subLineIndex++) {
398 CollectionGroup subCollectionPrototype = collectionGroup.getSubCollections().get(subLineIndex);
399 CollectionGroup subCollectionGroup = ComponentUtils.copy(subCollectionPrototype, lineSuffix);
400
401
402 boolean renderSubCollection = checkSubCollectionRender(view, model, collectionGroup,
403 subCollectionGroup);
404 if (!renderSubCollection) {
405 continue;
406 }
407
408 subCollectionGroup.getBindingInfo().setBindByNamePrefix(bindingPath);
409 if (subCollectionGroup.isRenderAddLine()) {
410 subCollectionGroup.getAddLineBindingInfo().setBindByNamePrefix(bindingPath);
411 }
412
413
414 String subCollectionSuffix = lineSuffix;
415 if (StringUtils.isNotBlank(subCollectionGroup.getSubCollectionSuffix())) {
416 subCollectionSuffix = subCollectionGroup.getSubCollectionSuffix() + lineSuffix;
417 }
418 subCollectionGroup.setSubCollectionSuffix(subCollectionSuffix);
419
420 FieldGroup fieldGroupPrototype = layoutManager.getSubCollectionFieldGroupPrototype();
421
422 FieldGroup subCollectionFieldGroup = ComponentUtils.copy(fieldGroupPrototype,
423 lineSuffix + UifConstants.IdSuffixes.SUB + subLineIndex);
424 subCollectionFieldGroup.setGroup(subCollectionGroup);
425
426 ComponentUtils.updateContextForLine(subCollectionFieldGroup, currentLine, lineIndex,
427 lineSuffix + UifConstants.IdSuffixes.SUB + subLineIndex);
428
429 subCollectionFields.add(subCollectionFieldGroup);
430 }
431 ComponentUtils.pushObjectToContext(subCollectionFields, UifConstants.ContextVariableNames.PARENT_LINE,
432 currentLine);
433 }
434
435
436 layoutManager.buildLine(view, model, collectionGroup, lineFields, subCollectionFields, bindingPath, actions,
437 lineSuffix, currentLine, lineIndex);
438
439
440 String selector = "";
441 if (lineIndex == -1) {
442 List<String> addIds = new ArrayList<String>();
443 for (Field f : lineFields) {
444 if (f instanceof InputField) {
445
446
447 Control control = ((InputField) f).getControl();
448 if (control != null) {
449 control.addStyleClass("ignoreValid");
450 selector = selector + ",#" + f.getId() + UifConstants.IdSuffixes.CONTROL;
451 }
452 } else if (f instanceof FieldGroup) {
453 List<InputField> fields = ComponentUtils.getComponentsOfTypeDeep(((FieldGroup) f).getGroup(),
454 InputField.class);
455 for (InputField nestedField : fields) {
456 Control control = nestedField.getControl();
457 if (control != null) {
458 control.addStyleClass("ignoreValid");
459 selector = selector + ",#" + nestedField.getId() + UifConstants.IdSuffixes.CONTROL;
460 }
461 }
462 }
463 }
464 collectionGroup.addDataAttribute(UifConstants.DataAttributes.ADD_CONTROLS, selector.replaceFirst(",", ""));
465 }
466 }
467
468
469
470
471
472
473
474
475
476
477
478 protected List<Field> processAnyRemoteFieldsHolder(View view, Object model, CollectionGroup group,
479 List<? extends Component> items) {
480 List<Field> processedItems = new ArrayList<Field>();
481
482
483
484 for (Component item : items) {
485 if (item instanceof RemoteFieldsHolder) {
486 List<InputField> translatedFields = ((RemoteFieldsHolder) item).fetchAndTranslateRemoteFields(view,
487 model, group);
488 processedItems.addAll(translatedFields);
489 } else {
490 processedItems.add((Field) item);
491 }
492 }
493
494 return processedItems;
495 }
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513 protected List<Field> removeNonRenderLineFields(View view, Object model, CollectionGroup collectionGroup,
514 List<Field> lineFields, Object currentLine, int lineIndex) {
515 List<Field> fields = new ArrayList<Field>();
516
517 ExpressionEvaluator expressionEvaluator = view.getViewHelperService().getExpressionEvaluator();
518
519 for (Field lineField : lineFields) {
520 String conditionalRender = lineField.getPropertyExpression("render");
521
522
523 if (StringUtils.isNotBlank(conditionalRender)) {
524 Map<String, Object> context = getContextForField(view, collectionGroup, lineField);
525
526
527
528 conditionalRender = expressionEvaluator.replaceBindingPrefixes(view, lineField, conditionalRender);
529
530 Boolean render = (Boolean) expressionEvaluator.evaluateExpression(context, conditionalRender);
531 lineField.setRender(render);
532 }
533
534
535 if (lineField.isRender() || StringUtils.isNotBlank(lineField.getProgressiveRender())) {
536 fields.add(lineField);
537 }
538 }
539
540 return fields;
541 }
542
543
544
545
546
547
548
549
550
551
552
553
554 protected boolean checkViewLineAuthorizationAndPresentationLogic(View view, ViewModel model,
555 CollectionGroup collectionGroup, Object line) {
556 ViewPresentationController presentationController = view.getPresentationController();
557 ViewAuthorizer authorizer = view.getAuthorizer();
558
559 Person user = GlobalVariables.getUserSession().getPerson();
560
561
562 boolean canViewLine = authorizer.canViewLine(view, model, collectionGroup, collectionGroup.getPropertyName(),
563 line, user);
564 if (canViewLine) {
565 canViewLine = presentationController.canViewLine(view, model, collectionGroup,
566 collectionGroup.getPropertyName(), line);
567 }
568
569 return canViewLine;
570 }
571
572
573
574
575
576
577
578
579
580
581
582
583 protected boolean checkEditLineAuthorizationAndPresentationLogic(View view, ViewModel model,
584 CollectionGroup collectionGroup, Object line) {
585 ViewPresentationController presentationController = view.getPresentationController();
586 ViewAuthorizer authorizer = view.getAuthorizer();
587
588 Person user = GlobalVariables.getUserSession().getPerson();
589
590
591 boolean canEditLine = authorizer.canEditLine(view, model, collectionGroup, collectionGroup.getPropertyName(),
592 line, user);
593 if (canEditLine) {
594 canEditLine = presentationController.canEditLine(view, model, collectionGroup,
595 collectionGroup.getPropertyName(), line);
596 }
597
598 return canEditLine;
599 }
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616 protected void applyLineFieldAuthorizationAndPresentationLogic(View view, ViewModel model,
617 CollectionGroup collectionGroup, Object line, boolean readOnlyLine, List<Field> lineFields,
618 List<Action> actions) {
619 ViewPresentationController presentationController = view.getPresentationController();
620 ViewAuthorizer authorizer = view.getAuthorizer();
621
622 Person user = GlobalVariables.getUserSession().getPerson();
623
624 ExpressionEvaluator expressionEvaluator = view.getViewHelperService().getExpressionEvaluator();
625
626 for (Field lineField : lineFields) {
627 String propertyName = null;
628 if (lineField instanceof DataBinding) {
629 propertyName = ((DataBinding) lineField).getPropertyName();
630 }
631
632
633
634 ComponentSecurity componentSecurity = lineField.getComponentSecurity();
635
636 Map<String, Object> context = getContextForField(view, collectionGroup, lineField);
637 expressionEvaluator.evaluateExpressionsOnConfigurable(view, componentSecurity, context);
638
639
640 if (lineField.isRender() && !lineField.isHidden()) {
641 boolean canViewField = authorizer.canViewLineField(view, model, collectionGroup,
642 collectionGroup.getPropertyName(), line, lineField, propertyName, user);
643 if (canViewField) {
644 canViewField = presentationController.canViewLineField(view, model, collectionGroup,
645 collectionGroup.getPropertyName(), line, lineField, propertyName);
646 }
647
648 if (!canViewField) {
649
650
651 lineField.setHidden(true);
652
653 if (lineField.getPropertyExpressions().containsKey("hidden")) {
654 lineField.getPropertyExpressions().remove("hidden");
655 }
656
657 continue;
658 }
659
660
661 boolean canEditField = !readOnlyLine;
662 if (!readOnlyLine) {
663 canEditField = authorizer.canEditLineField(view, model, collectionGroup,
664 collectionGroup.getPropertyName(), line, lineField, propertyName, user);
665 if (canEditField) {
666 canEditField = presentationController.canEditLineField(view, model, collectionGroup,
667 collectionGroup.getPropertyName(), line, lineField, propertyName);
668 }
669 }
670
671 if (readOnlyLine || !canEditField) {
672 lineField.setReadOnly(true);
673
674 if (lineField.getPropertyExpressions().containsKey("readOnly")) {
675 lineField.getPropertyExpressions().remove("readOnly");
676 }
677 }
678 }
679 }
680
681
682 for (Action action : actions) {
683 if (action.isRender()) {
684 boolean canPerformAction = authorizer.canPerformLineAction(view, model, collectionGroup,
685 collectionGroup.getPropertyName(), line, action, action.getActionEvent(), action.getId(), user);
686 if (canPerformAction) {
687 canPerformAction = presentationController.canPerformLineAction(view, model, collectionGroup,
688 collectionGroup.getPropertyName(), line, action, action.getActionEvent(), action.getId());
689 }
690
691 if (!canPerformAction) {
692 action.setRender(false);
693
694 if (action.getPropertyExpressions().containsKey("render")) {
695 action.getPropertyExpressions().remove("render");
696 }
697 }
698 }
699 }
700 }
701
702
703
704
705
706
707
708
709
710
711
712
713 protected boolean checkSubCollectionRender(View view, Object model, CollectionGroup collectionGroup,
714 CollectionGroup subCollectionGroup) {
715 String conditionalRender = subCollectionGroup.getPropertyExpression("render");
716
717
718
719
720 if (StringUtils.isNotBlank(conditionalRender)) {
721 Map<String, Object> context = new HashMap<String, Object>();
722 context.putAll(view.getContext());
723 context.put(UifConstants.ContextVariableNames.PARENT, collectionGroup);
724 context.put(UifConstants.ContextVariableNames.COMPONENT, subCollectionGroup);
725
726 Boolean render = (Boolean) view.getViewHelperService().getExpressionEvaluator().evaluateExpression(context,
727 conditionalRender);
728 subCollectionGroup.setRender(render);
729 }
730
731 return subCollectionGroup.isRender();
732 }
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749 protected List<Action> initializeLineActions(List<Action> lineActions, View view, Object model,
750 CollectionGroup collectionGroup, Object collectionLine, int lineIndex) {
751 String lineSuffix = UifConstants.IdSuffixes.LINE + Integer.toString(lineIndex);
752 if (StringUtils.isNotBlank(collectionGroup.getSubCollectionSuffix())) {
753 lineSuffix = collectionGroup.getSubCollectionSuffix() + lineSuffix;
754 }
755 List<Action> actions = ComponentUtils.copyComponentList(lineActions, lineSuffix);
756
757 for (Action action : actions) {
758 if (ComponentUtils.containsPropertyExpression(action, UifPropertyPaths.ACTION_PARAMETERS, true)) {
759
760 action.getPropertyExpressions().put(
761 UifPropertyPaths.ACTION_PARAMETERS + "['" + UifParameters.SELLECTED_COLLECTION_PATH + "']",
762 UifConstants.EL_PLACEHOLDER_PREFIX + "'" + collectionGroup.getBindingInfo().getBindingPath() +
763 "'" + UifConstants.EL_PLACEHOLDER_SUFFIX);
764 action.getPropertyExpressions().put(
765 UifPropertyPaths.ACTION_PARAMETERS + "['" + UifParameters.SELECTED_LINE_INDEX + "']",
766 UifConstants.EL_PLACEHOLDER_PREFIX + "'" + Integer.toString(lineIndex) +
767 "'" + UifConstants.EL_PLACEHOLDER_SUFFIX);
768 } else {
769 action.addActionParameter(UifParameters.SELLECTED_COLLECTION_PATH,
770 collectionGroup.getBindingInfo().getBindingPath());
771 action.addActionParameter(UifParameters.SELECTED_LINE_INDEX, Integer.toString(lineIndex));
772 }
773
774 action.setJumpToIdAfterSubmit(collectionGroup.getId());
775 action.setRefreshId(collectionGroup.getId());
776
777
778
779 if (action.isPerformClientSideValidation()) {
780 String preSubmitScript = "var valid=validateLine('" +
781 collectionGroup.getBindingInfo().getBindingPath() + "'," + Integer.toString(lineIndex) +
782 ");";
783
784
785 if (StringUtils.isNotBlank(action.getPreSubmitCall())) {
786 preSubmitScript = ScriptUtils.appendScript(preSubmitScript,
787 "if(valid){valid=function(){" + action.getPreSubmitCall() + "}();}");
788 }
789
790 preSubmitScript += " return valid;";
791
792 action.setPreSubmitCall(preSubmitScript);
793 action.setPerformClientSideValidation(false);
794 }
795 }
796
797 ComponentUtils.updateContextsForLine(actions, collectionLine, lineIndex, lineSuffix);
798
799 return actions;
800 }
801
802
803
804
805
806
807
808
809
810
811
812
813
814 protected List<Action> getAddLineActions(View view, Object model, CollectionGroup collectionGroup) {
815 String lineSuffix = UifConstants.IdSuffixes.ADD_LINE;
816 if (StringUtils.isNotBlank(collectionGroup.getSubCollectionSuffix())) {
817 lineSuffix = collectionGroup.getSubCollectionSuffix() + lineSuffix;
818 }
819 List<Action> lineActions = ComponentUtils.copyComponentList(collectionGroup.getAddLineActions(), lineSuffix);
820
821 for (Action action : lineActions) {
822 action.addActionParameter(UifParameters.SELLECTED_COLLECTION_PATH,
823 collectionGroup.getBindingInfo().getBindingPath());
824 action.setJumpToIdAfterSubmit(collectionGroup.getId());
825 action.addActionParameter(UifParameters.ACTION_TYPE, UifParameters.ADD_LINE);
826 action.setRefreshId(collectionGroup.getId());
827
828 String baseId = collectionGroup.getBaseId();
829 if (StringUtils.isNotBlank(collectionGroup.getSubCollectionSuffix())) {
830 baseId += collectionGroup.getSubCollectionSuffix();
831 }
832
833 if (action.isPerformClientSideValidation()) {
834 String preSubmitScript = "var valid=";
835 if (collectionGroup.isAddViaLightBox()) {
836 preSubmitScript += "validateAddLine('" + collectionGroup.getId() + "', true);";
837 } else {
838 preSubmitScript += "validateAddLine('" + collectionGroup.getId() + "');";
839 }
840
841
842 if (StringUtils.isNotBlank(action.getPreSubmitCall())) {
843 preSubmitScript = ScriptUtils.appendScript(preSubmitScript,
844 "if(valid){valid=function(){" + action.getPreSubmitCall() + "}();}");
845 }
846
847 if (collectionGroup.isAddViaLightBox()) {
848 preSubmitScript += " if(valid){closeLightbox();}";
849 }
850 preSubmitScript += "return valid;";
851
852 action.setPreSubmitCall(preSubmitScript);
853 action.setPerformClientSideValidation(false);
854 }
855 }
856
857
858 String addLinePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
859 Object addLine = ObjectPropertyUtils.getPropertyValue(model, addLinePath);
860
861 ComponentUtils.updateContextsForLine(lineActions, addLine, -1, lineSuffix);
862
863 return lineActions;
864 }
865
866
867
868
869
870
871
872
873
874
875 protected Map<String, Object> getContextForField(View view, CollectionGroup collectionGroup, Field field) {
876 Map<String, Object> context = new HashMap<String, Object>();
877
878 context.putAll(view.getContext());
879 context.putAll(field.getContext());
880 context.put(UifConstants.ContextVariableNames.PARENT, collectionGroup);
881 context.put(UifConstants.ContextVariableNames.COMPONENT, field);
882
883 return context;
884 }
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905 public void initializeNewCollectionLine(View view, Object model, CollectionGroup collectionGroup,
906 boolean clearExistingLine) {
907 Object newLine = null;
908
909
910 if (StringUtils.isBlank(collectionGroup.getAddLinePropertyName())) {
911
912 if (!(model instanceof UifFormBase)) {
913 throw new RuntimeException("Cannot create new collection line for group: "
914 + collectionGroup.getPropertyName()
915 + ". Model does not extend "
916 + UifFormBase.class.getName());
917 }
918
919
920 Map<String, Object> newCollectionLines = ObjectPropertyUtils.getPropertyValue(model,
921 UifPropertyPaths.NEW_COLLECTION_LINES);
922 if (newCollectionLines == null) {
923 newCollectionLines = new HashMap<String, Object>();
924 ObjectPropertyUtils.setPropertyValue(model, UifPropertyPaths.NEW_COLLECTION_LINES, newCollectionLines);
925 }
926
927
928 String newCollectionLineKey = KRADUtils.translateToMapSafeKey(
929 collectionGroup.getBindingInfo().getBindingPath());
930 String addLineBindingPath = UifPropertyPaths.NEW_COLLECTION_LINES + "['" + newCollectionLineKey + "']";
931 collectionGroup.getAddLineBindingInfo().setBindingPath(addLineBindingPath);
932
933
934 if (!newCollectionLines.containsKey(newCollectionLineKey) || (newCollectionLines.get(newCollectionLineKey)
935 == null) || clearExistingLine) {
936
937 newLine = ObjectUtils.newInstance(collectionGroup.getCollectionObjectClass());
938 newCollectionLines.put(newCollectionLineKey, newLine);
939 }
940 } else {
941
942 Object addLine = ObjectPropertyUtils.getPropertyValue(model,
943 collectionGroup.getAddLineBindingInfo().getBindingPath());
944 if ((addLine == null) || clearExistingLine) {
945 newLine = ObjectUtils.newInstance(collectionGroup.getCollectionObjectClass());
946 ObjectPropertyUtils.setPropertyValue(model, collectionGroup.getAddLineBindingInfo().getBindingPath(),
947 newLine);
948 }
949 }
950
951
952 if (newLine != null) {
953 view.getViewHelperService().applyDefaultValuesForCollectionLine(view, model, collectionGroup, newLine);
954 }
955 }
956
957
958
959
960 private static class IndexedElement {
961
962
963
964
965 final int index;
966
967
968
969
970 final Object element;
971
972
973
974
975
976
977
978 private IndexedElement(int index, Object element) {
979 this.index = index;
980 this.element = element;
981 }
982 }
983
984 }