1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.layout;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.framework.util.ReflectionUtils;
20 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
21 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
22 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
23 import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
24 import org.kuali.rice.krad.uif.CssConstants;
25 import org.kuali.rice.krad.uif.UifConstants;
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.DataBinding;
29 import org.kuali.rice.krad.uif.component.KeepExpression;
30 import org.kuali.rice.krad.uif.container.CollectionGroup;
31 import org.kuali.rice.krad.uif.container.Container;
32 import org.kuali.rice.krad.uif.container.DialogGroup;
33 import org.kuali.rice.krad.uif.container.Group;
34 import org.kuali.rice.krad.uif.container.collections.LineBuilderContext;
35 import org.kuali.rice.krad.uif.element.Action;
36 import org.kuali.rice.krad.uif.element.Label;
37 import org.kuali.rice.krad.uif.element.Message;
38 import org.kuali.rice.krad.uif.field.DataField;
39 import org.kuali.rice.krad.uif.field.Field;
40 import org.kuali.rice.krad.uif.field.FieldGroup;
41 import org.kuali.rice.krad.uif.field.InputField;
42 import org.kuali.rice.krad.uif.field.MessageField;
43 import org.kuali.rice.krad.uif.layout.collections.CollectionLayoutManagerBase;
44 import org.kuali.rice.krad.uif.layout.collections.CollectionPagingHelper;
45 import org.kuali.rice.krad.uif.layout.collections.DataTablesPagingHelper;
46 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
47 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleRestriction;
48 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleUtils;
49 import org.kuali.rice.krad.uif.util.ColumnCalculationInfo;
50 import org.kuali.rice.krad.uif.util.ComponentFactory;
51 import org.kuali.rice.krad.uif.util.ComponentUtils;
52 import org.kuali.rice.krad.uif.util.ContextUtils;
53 import org.kuali.rice.krad.uif.util.CopyUtils;
54 import org.kuali.rice.krad.uif.util.LifecycleElement;
55 import org.kuali.rice.krad.uif.view.ExpressionEvaluator;
56 import org.kuali.rice.krad.uif.view.View;
57 import org.kuali.rice.krad.uif.view.ViewModel;
58 import org.kuali.rice.krad.uif.widget.RichTable;
59 import org.kuali.rice.krad.util.KRADConstants;
60 import org.kuali.rice.krad.util.KRADUtils;
61 import org.kuali.rice.krad.web.form.UifFormBase;
62
63 import java.util.ArrayList;
64 import java.util.Arrays;
65 import java.util.Collections;
66 import java.util.HashMap;
67 import java.util.List;
68 import java.util.Map;
69 import java.util.Set;
70 import java.util.TreeMap;
71
72
73
74
75
76
77
78
79
80
81
82
83
84 @BeanTag(name = "tableCollectionLayout-bean", parent = "Uif-TableCollectionLayout")
85 public class TableLayoutManagerBase extends CollectionLayoutManagerBase implements TableLayoutManager {
86
87 private static final long serialVersionUID = 3622267585541524208L;
88
89 private int numberOfColumns;
90 private boolean suppressLineWrapping;
91 private Boolean autoTruncateColumns;
92
93 private boolean applyAlternatingRowStyles;
94 private boolean applyDefaultCellWidths;
95
96 private List<String> rowCssClasses;
97 private List<String> rowDataAttributes;
98
99 private boolean useShortLabels;
100 private boolean repeatHeader;
101 private Label headerLabelPrototype;
102
103 private boolean renderSequenceField;
104 private boolean generateAutoSequence;
105 private Field sequenceFieldPrototype;
106
107 private FieldGroup actionFieldPrototype;
108
109 private boolean separateAddLine;
110
111
112 private int numberOfDataColumns;
113
114 private List<Label> headerLabels;
115 private List<Field> allRowFields;
116 private List<Field> firstRowFields;
117
118 private RichTable richTable;
119 private boolean headerAdded;
120
121 private int actionColumnIndex = -1;
122 private String actionColumnPlacement;
123
124
125 private Group rowDetailsGroup;
126 private boolean rowDetailsOpen;
127 private boolean showToggleAllDetails;
128 private Action toggleAllDetailsAction;
129 private boolean ajaxDetailsRetrieval;
130 private Action expandDetailsActionPrototype;
131
132
133 @KeepExpression
134 private String groupingTitle;
135 private String groupingPrefix;
136 private int groupingColumnIndex;
137 private List<String> groupingPropertyNames;
138
139
140 private boolean renderOnlyLeftTotalLabels;
141 private boolean showTotal;
142 private boolean showPageTotal;
143 private boolean showGroupTotal;
144 private boolean generateGroupTotalRows;
145 private Label totalLabel;
146 private Label pageTotalLabel;
147 private Label groupTotalLabelPrototype;
148
149 private List<String> columnsToCalculate;
150 private List<ColumnCalculationInfo> columnCalculations;
151 private List<Component> footerCalculationComponents;
152
153
154 private Map<String, String> conditionalRowCssClasses;
155
156 public TableLayoutManagerBase() {
157 useShortLabels = false;
158 repeatHeader = false;
159 renderSequenceField = true;
160 generateAutoSequence = false;
161 separateAddLine = false;
162 rowDetailsOpen = false;
163
164 rowCssClasses = new ArrayList<String>();
165 rowDataAttributes = new ArrayList<String>();
166 headerLabels = new ArrayList<Label>();
167 allRowFields = new ArrayList<Field>();
168 firstRowFields = new ArrayList<Field>();
169 columnsToCalculate = new ArrayList<String>();
170 columnCalculations = new ArrayList<ColumnCalculationInfo>();
171 conditionalRowCssClasses = new HashMap<String, String>();
172 }
173
174
175
176
177 @Override
178 public void performInitialization(Object model) {
179 CollectionGroup collectionGroup = (CollectionGroup) ViewLifecycle.getPhase().getElement();
180
181 if (Boolean.TRUE.equals(collectionGroup.getReadOnly())) {
182 getAddLineGroup().setReadOnly(true);
183 actionFieldPrototype.setReadOnly(true);
184 }
185
186 this.setupDetails(collectionGroup);
187 this.setupGrouping(model, collectionGroup);
188
189 if (collectionGroup.isAddWithDialog()) {
190 setSeparateAddLine(true);
191 }
192
193 super.performInitialization(model);
194
195 getRowCssClasses().clear();
196
197 if (generateAutoSequence && !(getSequenceFieldPrototype() instanceof MessageField)) {
198 sequenceFieldPrototype = ComponentFactory.getMessageField();
199 }
200 }
201
202
203
204
205
206
207
208 @Override
209 public void performApplyModel(Object model, LifecycleElement parent) {
210 super.performApplyModel(model, parent);
211
212 for (ColumnCalculationInfo cInfo : columnCalculations) {
213 ViewLifecycle.getExpressionEvaluator().populatePropertyExpressionsFromGraph(cInfo, false);
214 }
215
216
217 if (isAutoTruncateColumns() == null) {
218 setAutoTruncateColumns(CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
219 KRADConstants.KRAD_NAMESPACE, KRADConstants.DetailTypes.ALL_DETAIL_TYPE,
220 KRADConstants.SystemGroupParameterNames.AUTO_TRUNCATE_COLUMNS, false));
221 }
222 }
223
224
225
226
227 @Override
228 public void performFinalize(Object model, LifecycleElement parent) {
229 super.performFinalize(model, parent);
230
231 UifFormBase formBase = (UifFormBase) model;
232
233 CollectionGroup collectionGroup = (CollectionGroup) ViewLifecycle.getPhase().getElement();
234
235 int totalColumns = getNumberOfDataColumns();
236 if (renderSequenceField) {
237 totalColumns++;
238 }
239
240 if (collectionGroup.isIncludeLineSelectionField()) {
241 totalColumns++;
242 }
243
244 if (collectionGroup.isRenderLineActions() && !Boolean.TRUE.equals(collectionGroup.getReadOnly())) {
245 totalColumns++;
246 }
247
248 setNumberOfColumns(totalColumns);
249
250
251 if (this.isApplyDefaultCellWidths() || Boolean.TRUE.equals(this.isAutoTruncateColumns())) {
252 this.addStyleClass("uif-table-fixed");
253 }
254
255
256 if (UifConstants.ActionEvents.ADD_LINE.equals(formBase.getActionEvent())) {
257 String highlightScript = "jQuery(\"#" + parent.getId() + " tr:first\").effect(\"highlight\",{}, 6000);";
258 String onReadyScript = collectionGroup.getOnDocumentReadyScript();
259 if (StringUtils.isNotBlank(onReadyScript)) {
260 highlightScript = onReadyScript + highlightScript;
261 }
262 collectionGroup.setOnDocumentReadyScript(highlightScript);
263 }
264
265
266 if (columnCalculations != null && !columnCalculations.isEmpty() && richTable != null &&
267 this.getAllRowFields() != null && !this.getAllRowFields().isEmpty()) {
268 setupColumnCalculations(model, collectionGroup, totalColumns);
269 }
270
271
272 if ((groupingPropertyNames != null || StringUtils.isNotBlank(this.getGroupingTitle())) && richTable != null) {
273 richTable.setGroupingOptionsJSString(
274 "{iGroupingColumnIndex: " + groupingColumnIndex + ", bGenerateGroupTotalRows:"
275 + this.generateGroupTotalRows + ", bSetGroupingClassOnTR: true"
276 + ", sGroupingClass: 'uif-groupRow'" + (this.getGroupingPrefix() != null ?
277 ", sGroupLabelPrefix: '" + this.getGroupingPrefix() + "'" : "") + "}"
278 );
279 }
280
281
282 if ((this.getRichTable() == null || !this.getRichTable().isRender()) &&
283 collectionGroup.isUseServerPaging() && this.getPagerWidget() != null) {
284
285 CollectionLayoutUtils.setupPagerWidget(getPagerWidget(), collectionGroup, model);
286 }
287
288 setupEditDetails();
289 }
290
291
292
293
294 private void setupEditDetails() {
295
296
297
298 List<FieldGroup> fieldGroups = ViewLifecycleUtils.getElementsOfTypeDeep(allRowFields, FieldGroup.class);
299 for (FieldGroup fieldGroup : fieldGroups) {
300 Group group = fieldGroup.getGroup();
301
302 if (group != null) {
303 List<DialogGroup> dialogGroups = ViewLifecycleUtils.getElementsOfTypeDeep(group.getItems(),
304 DialogGroup.class);
305
306 for (DialogGroup dialogGroup : dialogGroups) {
307 List<FieldGroup> fieldGroupsList = ViewLifecycleUtils.getElementsOfTypeDeep(dialogGroup.getItems(),
308 FieldGroup.class);
309
310 for (FieldGroup fieldGroupItem : fieldGroupsList) {
311 Group group1 = fieldGroupItem.getGroup();
312
313 if (group1 != null && group1 instanceof CollectionGroup) {
314
315
316 dialogGroup.setDialogCssClass("modal-lg");
317 }
318 }
319 }
320 }
321 }
322 }
323
324
325
326
327
328
329
330
331 protected void setupGrouping(Object model, CollectionGroup collectionGroup) {
332 String groupingTitleExpression = "";
333
334 if (StringUtils.isNotBlank(this.getPropertyExpression(UifPropertyPaths.GROUPING_TITLE))) {
335 groupingTitleExpression = this.getPropertyExpression(UifPropertyPaths.GROUPING_TITLE);
336
337 this.setGroupingTitle(this.getPropertyExpression(UifPropertyPaths.GROUPING_TITLE));
338 } else if (this.getGroupingPropertyNames() != null) {
339 for (String propertyName : this.getGroupingPropertyNames()) {
340 groupingTitleExpression = groupingTitleExpression + ", " + propertyName;
341 }
342
343 groupingTitleExpression = groupingTitleExpression.replaceFirst(", ",
344 "@{" + UifConstants.LINE_PATH_BIND_ADJUST_PREFIX);
345 groupingTitleExpression = groupingTitleExpression.replace(", ",
346 "}, @{" + UifConstants.LINE_PATH_BIND_ADJUST_PREFIX);
347 groupingTitleExpression = groupingTitleExpression.trim() + "}";
348 }
349
350 if (StringUtils.isNotBlank(groupingTitleExpression)) {
351 MessageField groupingMessageField = ComponentFactory.getColGroupingField();
352
353 groupingMessageField.getMessage().getPropertyExpressions().put(UifPropertyPaths.MESSAGE_TEXT,
354 groupingTitleExpression);
355
356 groupingMessageField.addDataAttribute(UifConstants.DataAttributes.ROLE,
357 UifConstants.RoleTypes.ROW_GROUPING);
358
359 List<Component> theItems = new ArrayList<Component>();
360 theItems.add(groupingMessageField);
361 theItems.addAll(collectionGroup.getItems());
362 collectionGroup.setItems(theItems);
363 }
364 }
365
366
367
368
369
370
371
372
373 protected void setupColumnCalculations(Object model, Container container, int totalColumns) {
374 footerCalculationComponents = new ArrayList<Component>(totalColumns);
375
376
377 for (int i = 0; i < totalColumns; i++) {
378 footerCalculationComponents.add(null);
379 }
380
381 int leftLabelColumnIndex = 0;
382 if (groupingPropertyNames != null || StringUtils.isNotBlank(this.getGroupingTitle())) {
383 leftLabelColumnIndex = 1;
384 }
385
386
387 for (ColumnCalculationInfo cInfo : columnCalculations) {
388
389 if (StringUtils.isNotBlank(cInfo.getPropertyName())) {
390 for (int i = 0; i < this.getNumberOfColumns(); i++) {
391 Component component = this.getAllRowFields().get(i);
392 if (component != null && component instanceof DataField &&
393 ((DataField) component).getPropertyName().equals(cInfo.getPropertyName())) {
394 cInfo.setColumnNumber(i);
395 }
396 }
397
398 this.getColumnsToCalculate().add(cInfo.getColumnNumber().toString());
399 } else {
400 throw new RuntimeException("TableLayoutManager(" + container.getId() + "->" + this.getId() +
401 ") ColumnCalculationInfo MUST have a propertyName set");
402 }
403
404
405 FieldGroup calculationFieldGroup = ComponentFactory.getFieldGroup();
406 calculationFieldGroup.addDataAttribute(UifConstants.DataAttributes.ROLE,
407 UifConstants.RoleTypes.TOTALS_BLOCK);
408
409 List<Component> calculationFieldGroupItems = new ArrayList<Component>();
410
411
412 if (cInfo.isShowPageTotal()) {
413 Field pageTotalDataField = CopyUtils.copy(cInfo.getPageTotalField());
414 setupTotalField(pageTotalDataField, cInfo, this.isShowPageTotal(), getPageTotalLabel(),
415 UifConstants.RoleTypes.PAGE_TOTAL, leftLabelColumnIndex);
416 calculationFieldGroupItems.add(pageTotalDataField);
417 }
418
419
420 if (cInfo.isShowTotal()) {
421 Field totalDataField = CopyUtils.copy(cInfo.getTotalField());
422 setupTotalField(totalDataField, cInfo, this.isShowTotal(), getTotalLabel(),
423 UifConstants.RoleTypes.TOTAL, leftLabelColumnIndex);
424
425 if (!cInfo.isRecalculateTotalClientSide()) {
426 totalDataField.addDataAttribute(UifConstants.DataAttributes.SKIP_TOTAL, "true");
427 }
428
429 calculationFieldGroupItems.add(totalDataField);
430 }
431
432
433
434 if (cInfo.isShowGroupTotal()) {
435 Field groupTotalDataField = CopyUtils.copy(cInfo.getGroupTotalFieldPrototype());
436 setupTotalField(groupTotalDataField, cInfo, this.isShowGroupTotal(), getGroupTotalLabelPrototype(),
437 UifConstants.RoleTypes.GROUP_TOTAL, leftLabelColumnIndex);
438 groupTotalDataField.setId(container.getId() + "_gTotal" + cInfo.getColumnNumber());
439 groupTotalDataField.setStyle("display: none;");
440
441 calculationFieldGroupItems.add(groupTotalDataField);
442
443 if (this.isRenderOnlyLeftTotalLabels() && !this.isShowGroupTotal()) {
444 generateGroupTotalRows = false;
445 } else {
446 generateGroupTotalRows = true;
447 }
448 }
449
450 calculationFieldGroup.setItems(calculationFieldGroupItems);
451
452
453
454
455 Component component = footerCalculationComponents.get(cInfo.getColumnNumber());
456 if (component != null && component instanceof FieldGroup) {
457 Group verticalComboCalcGroup = ComponentFactory.getVerticalBoxGroup();
458
459 List<Component> comboGroupItems = new ArrayList<Component>();
460 comboGroupItems.add(component);
461 comboGroupItems.add(calculationFieldGroup);
462 verticalComboCalcGroup.setItems(comboGroupItems);
463
464 footerCalculationComponents.set(cInfo.getColumnNumber(), verticalComboCalcGroup);
465 } else if (component != null && component instanceof Group) {
466 List<Component> comboGroupItems = new ArrayList<Component>();
467 comboGroupItems.addAll(((Group) component).getItems());
468 comboGroupItems.add(calculationFieldGroup);
469
470 ((Group) component).setItems(comboGroupItems);
471
472 footerCalculationComponents.set(cInfo.getColumnNumber(), component);
473 } else {
474 footerCalculationComponents.set(cInfo.getColumnNumber(), calculationFieldGroup);
475 }
476 }
477
478
479
480 if (this.renderOnlyLeftTotalLabels && footerCalculationComponents.get(leftLabelColumnIndex) == null) {
481
482 List<Component> groupItems = new ArrayList<Component>();
483 Group labelGroup = ComponentFactory.getVerticalBoxGroup();
484
485 if (this.isShowGroupTotal()) {
486
487 Label groupTotalLabel = CopyUtils.copy(groupTotalLabelPrototype);
488 groupTotalLabel.setViewStatus(UifConstants.ViewStatus.CREATED);
489 groupTotalLabel.setStyle("display: none;");
490 groupTotalLabel.addDataAttribute(UifConstants.DataAttributes.ROLE, "groupTotalLabel");
491 groupItems.add(groupTotalLabel);
492 }
493
494 if (this.isShowPageTotal()) {
495 Label pageTotalLabel = CopyUtils.copy(this.pageTotalLabel);
496 pageTotalLabel.setViewStatus(UifConstants.ViewStatus.CREATED);
497 pageTotalLabel.addDataAttribute(UifConstants.DataAttributes.ROLE, "pageTotal");
498 groupItems.add(pageTotalLabel);
499 }
500
501 if (this.isShowTotal()) {
502 Label totalLabel = CopyUtils.copy(this.totalLabel);
503 totalLabel.setViewStatus(UifConstants.ViewStatus.CREATED);
504 groupItems.add(totalLabel);
505 }
506
507 labelGroup.setItems(groupItems);
508
509 footerCalculationComponents.set(leftLabelColumnIndex, labelGroup);
510 }
511 }
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527 protected Field setupTotalField(Field totalField, ColumnCalculationInfo cInfo, boolean show, Label leftLabel,
528 String type, int leftLabelColumnIndex) {
529
530 Field totalDataField = totalField;
531 totalDataField.addDataAttribute(UifConstants.DataAttributes.ROLE, type);
532 totalDataField.addDataAttribute("function", cInfo.getCalculationFunctionName());
533 totalDataField.addDataAttribute("params", cInfo.getCalculationFunctionExtraData());
534
535 if (cInfo.getColumnNumber() != leftLabelColumnIndex) {
536
537
538 totalDataField.getFieldLabel().setRender(!this.isRenderOnlyLeftTotalLabels());
539 } else if (cInfo.getColumnNumber() == leftLabelColumnIndex && this.isRenderOnlyLeftTotalLabels()) {
540
541
542 totalDataField.setFieldLabel((Label) CopyUtils.copy(leftLabel));
543 }
544
545 if (this.isRenderOnlyLeftTotalLabels()) {
546 totalDataField.setRender(show);
547 }
548
549 return totalDataField;
550 }
551
552
553
554
555
556
557
558
559
560
561
562 @Override
563 public void buildLine(LineBuilderContext lineBuilderContext) {
564 View view = ViewLifecycle.getView();
565
566 List<Field> lineFields = lineBuilderContext.getLineFields();
567 CollectionGroup collectionGroup = lineBuilderContext.getCollectionGroup();
568 int lineIndex = lineBuilderContext.getLineIndex();
569 String idSuffix = lineBuilderContext.getIdSuffix();
570 Object currentLine = lineBuilderContext.getCurrentLine();
571 List<? extends Component> actions = lineBuilderContext.getLineActions();
572 String bindingPath = lineBuilderContext.getBindingPath();
573
574
575
576 ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
577 for (Field lineField : lineFields) {
578 lineField.pushObjectToContext(UifConstants.ContextVariableNames.PARENT, collectionGroup);
579 lineField.pushAllToContext(view.getContext());
580 lineField.pushObjectToContext(UifConstants.ContextVariableNames.THEME_IMAGES,
581 view.getTheme().getImageDirectory());
582 lineField.pushObjectToContext(UifConstants.ContextVariableNames.COMPONENT, lineField);
583
584 expressionEvaluator.evaluatePropertyExpression(view, lineField.getContext(), lineField,
585 UifPropertyPaths.ROW_SPAN, true);
586 expressionEvaluator.evaluatePropertyExpression(view, lineField.getContext(), lineField,
587 UifPropertyPaths.COL_SPAN, true);
588 expressionEvaluator.evaluatePropertyExpression(view, lineField.getContext(), lineField,
589 UifPropertyPaths.REQUIRED, true);
590 expressionEvaluator.evaluatePropertyExpression(view, lineField.getContext(), lineField,
591 UifPropertyPaths.READ_ONLY, true);
592
593 if (lineField instanceof DataField && this.isAutoTruncateColumns() != null && this.isAutoTruncateColumns()
594 .equals(Boolean.TRUE)) {
595 lineField.addStyleClass(CssConstants.Classes.TRUNCATE);
596 }
597 }
598
599 if (this.isAutoTruncateColumns() != null && this.isAutoTruncateColumns().equals(Boolean.TRUE)) {
600 String onReadyScript = collectionGroup.getOnDocumentReadyScript();
601 if (StringUtils.isBlank(onReadyScript)) {
602 onReadyScript = "";
603 }
604 collectionGroup.setOnDocumentReadyScript(onReadyScript + "createTruncateTooltips();");
605 }
606
607
608 if (allRowFields.isEmpty()) {
609 if (isSuppressLineWrapping()) {
610 setNumberOfDataColumns(lineFields.size());
611 } else {
612 setNumberOfDataColumns(getNumberOfColumns());
613 }
614 }
615
616 boolean isAddLine = false;
617
618
619 if (lineIndex == -1 || (lineFields.size() != numberOfDataColumns
620 && ((lineIndex + 1) * numberOfDataColumns) < lineFields.size())) {
621 isAddLine = true;
622 }
623
624
625 if (lineIndex == 0 || this.firstRowFields.isEmpty()) {
626 this.firstRowFields = lineFields;
627 }
628
629 boolean renderActions = collectionGroup.isRenderLineActions() && !Boolean.TRUE.equals(
630 collectionGroup.getReadOnly());
631 int extraColumns = 0;
632 String rowCss = "";
633 boolean addLineInTable = collectionGroup.isRenderAddLine() && !Boolean.TRUE.equals(
634 collectionGroup.getReadOnly()) && !isSeparateAddLine();
635
636 if (collectionGroup.isHighlightNewItems() && ((UifFormBase) lineBuilderContext.getModel())
637 .isAddedCollectionItem(currentLine)) {
638 rowCss = collectionGroup.getNewItemsCssClass();
639 } else if (isAddLine && addLineInTable) {
640 rowCss = collectionGroup.getAddItemCssClass();
641 this.addStyleClass(CssConstants.Classes.HAS_ADD_LINE);
642 }
643
644
645 if (rowCss == null) {
646 rowCss = "";
647 }
648
649 Map<String, Object> lineContext = new HashMap<String, Object>();
650 lineContext.putAll(this.getContext());
651 lineContext.put(UifConstants.ContextVariableNames.LINE, currentLine);
652 lineContext.put(UifConstants.ContextVariableNames.MANAGER, this);
653 lineContext.put(UifConstants.ContextVariableNames.VIEW, view);
654 lineContext.put(UifConstants.ContextVariableNames.LINE_SUFFIX, idSuffix);
655 lineContext.put(UifConstants.ContextVariableNames.INDEX, Integer.valueOf(lineIndex));
656 lineContext.put(UifConstants.ContextVariableNames.COLLECTION_GROUP, collectionGroup);
657 lineContext.put(UifConstants.ContextVariableNames.IS_ADD_LINE, isAddLine && !isSeparateAddLine());
658 lineContext.put(UifConstants.ContextVariableNames.READONLY_LINE, Boolean.TRUE.equals(
659 collectionGroup.getReadOnly()));
660
661
662 if (conditionalRowCssClasses != null && !conditionalRowCssClasses.isEmpty()) {
663 int oddRemainder = 1;
664 if (!addLineInTable) {
665 oddRemainder = 0;
666 }
667
668 boolean isOdd = lineIndex % 2 == oddRemainder || lineIndex == -1;
669
670
671 rowCss = rowCss + " " + KRADUtils.generateRowCssClassString(conditionalRowCssClasses, lineIndex, isOdd,
672 lineContext, expressionEvaluator);
673 }
674
675
676 String rowDataAttributes = "";
677
678
679 if (isAddLine) {
680 if (StringUtils.isNotBlank(collectionGroup.getAddLineEnterKeyAction())) {
681 String addLineEnterKeyAction = collectionGroup.getAddLineEnterKeyAction();
682 if (addLineEnterKeyAction.indexOf("@{") != -1) {
683 addLineEnterKeyAction = expressionEvaluator.evaluateExpressionTemplate(lineContext,
684 collectionGroup.getAddLineEnterKeyAction());
685 }
686 rowDataAttributes = "data-" + UifConstants.DataAttributes.ENTER_KEY + "=\"" + KRADUtils
687 .convertToHTMLAttributeSafeString(addLineEnterKeyAction) + "\"";
688 }
689 }
690
691 else {
692 if (StringUtils.isNotBlank(collectionGroup.getLineEnterKeyAction())) {
693 String lineEnterKeyAction = collectionGroup.getLineEnterKeyAction();
694 if (lineEnterKeyAction.indexOf("@{") != -1) {
695 lineEnterKeyAction = expressionEvaluator.evaluateExpressionTemplate(lineContext,
696 collectionGroup.getLineEnterKeyAction());
697 }
698 rowDataAttributes = "data-" + UifConstants.DataAttributes.ENTER_KEY + "=\"" + KRADUtils
699 .convertToHTMLAttributeSafeString(lineEnterKeyAction) + "\"";
700 }
701 }
702
703 this.getRowDataAttributes().add(rowDataAttributes);
704
705
706 if (isAddLine && separateAddLine) {
707
708 addEnterKeyDataAttributeToGroup(getAddLineGroup(), lineContext, expressionEvaluator,
709 collectionGroup.getAddLineEnterKeyAction());
710
711 if (getAddLineGroup().getHeader() != null && StringUtils.isBlank(getAddLineGroup().getTitle())
712 && StringUtils.isBlank(getAddLineGroup().getHeader().getHeaderText())) {
713 getAddLineGroup().getHeader().setHeaderText(collectionGroup.getAddLabel());
714 }
715
716 getAddLineGroup().setItems(lineFields);
717
718 if ((getAddLineGroup().getFooter() != null) && ((getAddLineGroup().getFooter().getItems() == null)
719 || getAddLineGroup().getFooter().getItems().isEmpty())) {
720 getAddLineGroup().getFooter().setItems(new ArrayList<Component>(actions));
721 }
722
723
724 return;
725 }
726
727 rowCss = StringUtils.removeStart(rowCss, " ");
728 this.getRowCssClasses().add(rowCss);
729
730
731 if (!headerAdded) {
732 headerLabels = new ArrayList<Label>();
733 allRowFields = new ArrayList<Field>();
734
735 buildTableHeaderRows(collectionGroup, lineFields);
736 ContextUtils.pushObjectToContextDeep(headerLabels, UifConstants.ContextVariableNames.LINE, currentLine);
737 ContextUtils.pushObjectToContextDeep(headerLabels, UifConstants.ContextVariableNames.INDEX, new Integer(
738 lineIndex));
739 headerAdded = true;
740 }
741
742
743 for (Field field : lineFields) {
744 field.setLabelRendered(true);
745 field.setFieldLabel(null);
746
747 setCellAttributes(field);
748 }
749
750 int rowCount = calculateNumberOfRows(lineFields);
751 int rowSpan = rowCount;
752
753 List<FieldGroup> subCollectionFields = lineBuilderContext.getSubCollectionFields();
754 if (subCollectionFields != null) {
755 rowSpan += subCollectionFields.size();
756 }
757
758 if (actionColumnIndex == 1 && renderActions) {
759 addActionColumn(collectionGroup, idSuffix, currentLine, lineIndex, rowSpan, actions);
760 }
761
762
763 if (renderSequenceField) {
764 Field sequenceField = null;
765 if (!isAddLine) {
766 sequenceField = ComponentUtils.copy(getSequenceFieldPrototype(), idSuffix);
767
768
769 sequenceField.addDataAttribute(UifConstants.DataAttributes.VIGNORE, "yes");
770
771 if (generateAutoSequence && (sequenceField instanceof MessageField)) {
772 ((MessageField) sequenceField).setMessageText(Integer.toString(lineIndex + 1));
773 }
774 } else {
775 sequenceField = ComponentFactory.getMessageField();
776
777 String value = null;
778 Field copyField = ComponentUtils.copy(getSequenceFieldPrototype(), idSuffix);
779 java.lang.reflect.Field field = ReflectionUtils.findField(copyField.getClass(), "propertyName", String.class);
780 if (field!=null) {
781 ReflectionUtils.makeAccessible(field);
782 String propertyName = (String) ReflectionUtils.getField(field, copyField);
783 value = ReflectionUtils.getField(currentLine, propertyName, String.class);
784 }
785 if (value==null){
786 Message sequenceMessage = ComponentUtils.copy(collectionGroup.getAddLineLabel(), idSuffix);
787 ((MessageField) sequenceField).setMessage(sequenceMessage);
788 } else {
789 ((MessageField) sequenceField).setMessageText(value);
790 }
791
792
793 sequenceField.setCellWidth(getSequenceFieldPrototype().getCellWidth());
794 sequenceField.setWrapperStyle(getSequenceFieldPrototype().getWrapperStyle());
795 }
796
797 sequenceField.setRowSpan(rowSpan);
798
799 if (sequenceField instanceof DataBinding) {
800 ((DataBinding) sequenceField).getBindingInfo().setBindByNamePrefix(bindingPath);
801 }
802
803 setCellAttributes(sequenceField);
804
805 ContextUtils.updateContextForLine(sequenceField, collectionGroup, currentLine, lineIndex, idSuffix);
806 allRowFields.add(sequenceField);
807
808 extraColumns++;
809
810 if (actionColumnIndex == 2 && renderActions) {
811 addActionColumn(collectionGroup, idSuffix, currentLine, lineIndex, rowSpan, actions);
812 }
813 }
814
815
816 if (collectionGroup.isIncludeLineSelectionField()) {
817 Field selectField = ComponentUtils.copy(getSelectFieldPrototype(), idSuffix);
818 CollectionLayoutUtils.prepareSelectFieldForLine(selectField, collectionGroup, bindingPath, currentLine);
819
820 ContextUtils.updateContextForLine(selectField, collectionGroup, currentLine, lineIndex, idSuffix);
821 setCellAttributes(selectField);
822
823 allRowFields.add(selectField);
824
825 extraColumns++;
826
827 if (renderActions) {
828 if ((actionColumnIndex == 3 && renderSequenceField) || (actionColumnIndex == 2
829 && !renderSequenceField)) {
830 addActionColumn(collectionGroup, idSuffix, currentLine, lineIndex, rowSpan, actions);
831 }
832 }
833 }
834
835
836 int cellPosition = 0;
837
838 boolean renderActionsLast = actionColumnIndex == -1 || actionColumnIndex > lineFields.size() + extraColumns;
839 boolean hasGrouping = (groupingPropertyNames != null || StringUtils.isNotBlank(this.getGroupingTitle()));
840 boolean insertActionField = false;
841
842 for (Field lineField : lineFields) {
843
844
845
846
847
848 insertActionField = (cellPosition != 0 && lineFields.size() != numberOfDataColumns) && renderActions
849 && renderActionsLast && ((cellPosition % numberOfDataColumns) == 0);
850
851 cellPosition += lineField.getColSpan();
852
853
854 Map<String, String> lineFieldDataAttributes = lineField.getDataAttributes();
855 if (hasGrouping && (lineField instanceof MessageField) &&
856 lineFieldDataAttributes != null && UifConstants.RoleTypes.ROW_GROUPING.equals(
857 lineFieldDataAttributes.get(UifConstants.DataAttributes.ROLE))) {
858 int groupFieldIndex = allRowFields.size() - extraColumns;
859 allRowFields.add(groupFieldIndex, lineField);
860 groupingColumnIndex = 0;
861 if (isAddLine) {
862 ((MessageField) lineField).getMessage().getPropertyExpressions().remove(
863 UifPropertyPaths.MESSAGE_TEXT);
864 ((MessageField) lineField).getMessage().setMessageText("addLine");
865 }
866 } else {
867
868 if (insertActionField) {
869 addActionColumn(collectionGroup, idSuffix, currentLine, lineIndex, rowSpan, actions);
870 }
871
872 allRowFields.add(lineField);
873 }
874
875
876 if (!renderActionsLast && cellPosition == (actionColumnIndex - extraColumns - 1)) {
877 addActionColumn(collectionGroup, idSuffix, currentLine, lineIndex, rowSpan, actions);
878 }
879
880
881 if (lineField instanceof FieldGroup) {
882 FieldGroup lineFieldGroup = (FieldGroup) lineField;
883
884 List<? extends Component> lineFieldItems = lineFieldGroup.getItems();
885 if (lineFieldItems != null) {
886 for (Component component : lineFieldItems) {
887 if (component != null && component instanceof Action && (component.getDataAttributes() != null)
888 && component.getDataAttributes().get("role") != null && component.getDataAttributes()
889 .get("role").equals("detailsLink") && StringUtils.isBlank(
890 ((Action) component).getActionScript())) {
891 ((Action) component).setActionScript(
892 "rowDetailsActionHandler(this,'" + this.getId() + "');");
893 }
894 }
895 }
896
897
898 if (collectionGroup.isEditWithDialog()) {
899 if (!isAddLine && lineFieldGroup.getDataAttributes() != null) {
900 String role = lineFieldGroup.getDataAttributes().get(UifConstants.DataAttributes.ROLE);
901 if (role != null && role.equals("detailsFieldGroup")) {
902 lineFieldGroup.setReadOnly(true);
903 }
904 }
905 }
906 }
907
908
909
910 if (lineField instanceof InputField && columnCalculations != null) {
911 for (ColumnCalculationInfo cInfo : columnCalculations) {
912 if (cInfo.getPropertyName().equals(((InputField) lineField).getPropertyName())) {
913 if (cInfo.isCalculateOnKeyUp()) {
914 lineField.addDataAttribute(UifConstants.DataAttributes.TOTAL, "keyup");
915 } else {
916 lineField.addDataAttribute(UifConstants.DataAttributes.TOTAL, "change");
917 }
918 lineField.addStyleClass("uif-calculationField");
919 }
920 }
921 }
922 }
923
924 if (lineFields.size() == numberOfDataColumns && renderActions && renderActionsLast) {
925 addActionColumn(collectionGroup, idSuffix, currentLine, lineIndex, rowSpan, actions);
926 }
927
928
929 if (subCollectionFields != null) {
930 for (FieldGroup subCollectionField : subCollectionFields) {
931 subCollectionField.setColSpan(numberOfDataColumns);
932 }
933
934
935 allRowFields.addAll(subCollectionFields);
936 }
937 }
938
939
940
941
942
943
944
945
946
947
948
949
950 protected void addActionColumn(CollectionGroup collectionGroup, String idSuffix, Object currentLine, int lineIndex,
951 int rowSpan, List<? extends Component> actions) {
952 FieldGroup lineActionsField = ComponentUtils.copy(getActionFieldPrototype(), idSuffix);
953
954 ContextUtils.updateContextForLine(lineActionsField, collectionGroup, currentLine, lineIndex, idSuffix);
955
956 lineActionsField.setRowSpan(rowSpan);
957 lineActionsField.setItems(actions);
958 if (lineActionsField.getWrapperCssClasses() != null && !lineActionsField.getWrapperCssClasses().contains(
959 CssConstants.Classes.ACTION_COLUMN_STYLE_CLASS)) {
960 lineActionsField.getWrapperCssClasses().add(CssConstants.Classes.ACTION_COLUMN_STYLE_CLASS);
961 } else {
962 lineActionsField.setWrapperCssClasses(Arrays.asList(CssConstants.Classes.ACTION_COLUMN_STYLE_CLASS));
963 }
964
965 setCellAttributes(lineActionsField);
966
967 allRowFields.add(lineActionsField);
968 }
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987 protected void buildTableHeaderRows(CollectionGroup collectionGroup, List<Field> lineFields) {
988
989
990 int rowCount = calculateNumberOfRows(lineFields);
991
992 boolean renderActions = collectionGroup.isRenderLineActions() && !Boolean.TRUE.equals(
993 collectionGroup.getReadOnly());
994
995 int extraColumns = 0;
996
997 if (actionColumnIndex == 1 && renderActions) {
998 addActionHeader(rowCount, 1);
999 }
1000
1001
1002 if (renderSequenceField) {
1003 getSequenceFieldPrototype().setLabelRendered(true);
1004 getSequenceFieldPrototype().setRowSpan(rowCount);
1005 addHeaderField(getSequenceFieldPrototype(), 1);
1006 extraColumns++;
1007
1008 if (actionColumnIndex == 2 && renderActions) {
1009 addActionHeader(rowCount, 2);
1010 }
1011 }
1012
1013
1014 if (collectionGroup.isIncludeLineSelectionField()) {
1015 getSelectFieldPrototype().setLabelRendered(true);
1016 getSelectFieldPrototype().setRowSpan(rowCount);
1017 addHeaderField(getSelectFieldPrototype(), 1);
1018 extraColumns++;
1019
1020 if (actionColumnIndex == 3 && renderActions && renderSequenceField) {
1021 addActionHeader(rowCount, 3);
1022 } else if (actionColumnIndex == 2 && renderActions) {
1023 addActionHeader(rowCount, 2);
1024 }
1025 }
1026
1027
1028 int cellPosition = 0;
1029 boolean renderActionsLast = actionColumnIndex == -1 || actionColumnIndex > lineFields.size() + extraColumns;
1030 boolean insertActionHeader = false;
1031 for (Field field : lineFields) {
1032 if (!field.isRender() && StringUtils.isEmpty(field.getProgressiveRender())) {
1033 continue;
1034 }
1035
1036
1037
1038
1039
1040
1041 insertActionHeader =
1042 (cellPosition != 0 && lineFields.size() != numberOfDataColumns && renderActions && renderActionsLast
1043 && ((cellPosition % numberOfDataColumns) == 0));
1044
1045 if (insertActionHeader) {
1046 addActionHeader(rowCount, cellPosition);
1047 }
1048
1049 cellPosition += field.getColSpan();
1050 addHeaderField(field, cellPosition);
1051
1052
1053 if (renderActions && !renderActionsLast && cellPosition == actionColumnIndex - extraColumns - 1) {
1054 cellPosition += 1;
1055 addActionHeader(rowCount, cellPosition);
1056 }
1057 }
1058
1059 if (lineFields.size() == numberOfDataColumns && renderActions && renderActionsLast) {
1060 cellPosition += 1;
1061 addActionHeader(rowCount, cellPosition);
1062 }
1063 }
1064
1065
1066
1067
1068 protected void addActionHeader(int rowCount, int cellPosition) {
1069 getActionFieldPrototype().setLabelRendered(true);
1070 getActionFieldPrototype().setRowSpan(rowCount);
1071 if (getActionFieldPrototype().getWrapperCssClasses() != null && !getActionFieldPrototype()
1072 .getWrapperCssClasses().contains(CssConstants.Classes.ACTION_COLUMN_STYLE_CLASS)) {
1073 getActionFieldPrototype().getWrapperCssClasses().add(CssConstants.Classes.ACTION_COLUMN_STYLE_CLASS);
1074 } else {
1075 getActionFieldPrototype().setWrapperCssClasses(Arrays.asList(
1076 CssConstants.Classes.ACTION_COLUMN_STYLE_CLASS));
1077 }
1078
1079 addHeaderField(getActionFieldPrototype(), cellPosition);
1080 }
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091 protected void addHeaderField(Field field, int column) {
1092 String labelSuffix = UifConstants.IdSuffixes.COLUMN + column;
1093
1094 Label headerLabel = ComponentUtils.copy(getHeaderLabelPrototype(), labelSuffix);
1095
1096 if (useShortLabels) {
1097 headerLabel.setLabelText(field.getShortLabel());
1098 } else {
1099 headerLabel.setLabelText(field.getLabel());
1100 }
1101
1102 if (field.getExpressionGraph() != null && field.getExpressionGraph().containsKey("label")) {
1103 if (headerLabel.getExpressionGraph() == null) {
1104 headerLabel.setExpressionGraph(new HashMap<String, String>());
1105 }
1106 headerLabel.getExpressionGraph().put("labelText", field.getExpressionGraph().get("label"));
1107 field.getExpressionGraph().remove("label");
1108 if (headerLabel.getPropertyExpressions() == null) {
1109 headerLabel.setPropertyExpressions(new HashMap<String, String>());
1110 }
1111 headerLabel.getPropertyExpressions().put("labelText", field.getPropertyExpressions().get("label"));
1112 field.getPropertyExpressions().remove("label");
1113 }
1114
1115 headerLabel.setInlineComponents(field.getFieldLabel().getInlineComponents());
1116
1117 headerLabel.setRowSpan(field.getRowSpan());
1118 headerLabel.setColSpan(field.getColSpan());
1119
1120 if ((field.getRequired() != null) && field.getRequired().booleanValue()) {
1121 headerLabel.setRenderRequiredIndicator(!Boolean.TRUE.equals(field.getReadOnly()));
1122 } else {
1123 headerLabel.setRenderRequiredIndicator(false);
1124 }
1125
1126 setCellAttributes(field);
1127
1128
1129 headerLabel.setWrapperCssClasses(field.getWrapperCssClasses());
1130 headerLabel.setWrapperStyle(field.getWrapperStyle());
1131 headerLabel.setCellWidth(field.getCellWidth());
1132
1133 headerLabels.add(headerLabel);
1134 }
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144 protected int calculateNumberOfRows(List<? extends Field> items) {
1145 int rowCount = 0;
1146
1147
1148 if (isSuppressLineWrapping()) {
1149 return 1;
1150 }
1151
1152
1153 if (items.size() % getNumberOfDataColumns() > 0) {
1154
1155 Field field = items.get(items.size() - 1);
1156
1157 int colSize = 0;
1158 for (Field f : items) {
1159 colSize += f.getColSpan();
1160 }
1161
1162 field.setColSpan(1 + (numberOfDataColumns - (colSize % numberOfDataColumns)));
1163 rowCount = ((items.size() / getNumberOfDataColumns()) + 1);
1164 } else {
1165 rowCount = items.size() / getNumberOfDataColumns();
1166 }
1167 return rowCount;
1168 }
1169
1170
1171
1172
1173
1174
1175
1176 protected void setCellAttributes(Component component) {
1177 if (StringUtils.isNotBlank(component.getWidth()) && StringUtils.isBlank(component.getCellWidth())) {
1178 component.setCellWidth(component.getWidth());
1179 component.setWidth("");
1180 }
1181
1182 if (StringUtils.isNotBlank(component.getAlign()) && !StringUtils.contains(component.getWrapperStyle(),
1183 CssConstants.TEXT_ALIGN)) {
1184 if (component.getWrapperStyle() == null) {
1185 component.setWrapperStyle("");
1186 }
1187
1188 component.setWrapperStyle(
1189 component.getWrapperStyle() + CssConstants.TEXT_ALIGN + component.getAlign() + ";");
1190 component.setAlign("");
1191 }
1192
1193 if (StringUtils.isNotBlank(component.getValign()) && !StringUtils.contains(component.getWrapperStyle(),
1194 CssConstants.VERTICAL_ALIGN)) {
1195 if (component.getWrapperStyle() == null) {
1196 component.setWrapperStyle("");
1197 }
1198
1199 component.setWrapperStyle(
1200 component.getWrapperStyle() + CssConstants.VERTICAL_ALIGN + component.getValign() + ";");
1201 component.setValign("");
1202 }
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214 @Override
1215 public void processPagingRequest(Object model, CollectionGroup collectionGroup) {
1216 boolean richTableEnabled = ((getRichTable() != null) && (getRichTable().isRender()));
1217
1218 if (richTableEnabled) {
1219 DataTablesPagingHelper.DataTablesInputs dataTablesInputs = new DataTablesPagingHelper.DataTablesInputs(
1220 ViewLifecycle.getRequest());
1221
1222 DataTablesPagingHelper.processPagingRequest(ViewLifecycle.getView(), (ViewModel) model, collectionGroup,
1223 dataTablesInputs);
1224 } else {
1225 String pageNumber = ViewLifecycle.getRequest().getParameter(UifConstants.PageRequest.PAGE_NUMBER);
1226
1227 CollectionPagingHelper pagingHelper = new CollectionPagingHelper();
1228 pagingHelper.processPagingRequest(ViewLifecycle.getView(), collectionGroup, (UifFormBase) model,
1229 pageNumber);
1230 }
1231 }
1232
1233
1234
1235
1236 @Override
1237 public Class<? extends Container> getSupportedContainer() {
1238 return CollectionGroup.class;
1239 }
1240
1241
1242
1243
1244 @Override
1245 public List<Component> getColumnCalculationComponents() {
1246 if (columnCalculations == null) {
1247 return Collections.emptyList();
1248 }
1249
1250 List<Component> components = new ArrayList<Component>(columnCalculations.size() * 3);
1251 for (ColumnCalculationInfo cInfo : columnCalculations) {
1252 components.add(cInfo.getTotalField());
1253 components.add(cInfo.getPageTotalField());
1254 components.add(cInfo.getGroupTotalFieldPrototype());
1255 }
1256 return components;
1257 }
1258
1259
1260
1261
1262 @Override
1263 @BeanTagAttribute
1264 public int getNumberOfColumns() {
1265 return numberOfColumns;
1266 }
1267
1268
1269
1270
1271 @Override
1272 public void setNumberOfColumns(int numberOfColumns) {
1273 this.numberOfColumns = numberOfColumns;
1274 }
1275
1276
1277
1278
1279 @Override
1280 @BeanTagAttribute
1281 public boolean isSuppressLineWrapping() {
1282 return suppressLineWrapping;
1283 }
1284
1285
1286
1287
1288 @Override
1289 public void setSuppressLineWrapping(boolean suppressLineWrapping) {
1290 this.suppressLineWrapping = suppressLineWrapping;
1291 }
1292
1293
1294
1295
1296 @Override
1297 @BeanTagAttribute
1298 public Boolean isAutoTruncateColumns() {
1299 return autoTruncateColumns;
1300 }
1301
1302
1303
1304
1305 @Override
1306 public void setAutoTruncateColumns(Boolean autoTruncateColumns) {
1307 this.autoTruncateColumns = autoTruncateColumns;
1308 }
1309
1310
1311
1312
1313 @Override
1314 @BeanTagAttribute
1315 public boolean isApplyAlternatingRowStyles() {
1316 return applyAlternatingRowStyles;
1317 }
1318
1319
1320
1321
1322 @Override
1323 public void setApplyAlternatingRowStyles(boolean applyAlternatingRowStyles) {
1324 this.applyAlternatingRowStyles = applyAlternatingRowStyles;
1325 }
1326
1327
1328
1329
1330 @Override
1331 @BeanTagAttribute
1332 public boolean isApplyDefaultCellWidths() {
1333 return applyDefaultCellWidths;
1334 }
1335
1336
1337
1338
1339 @Override
1340 public void setApplyDefaultCellWidths(boolean applyDefaultCellWidths) {
1341 this.applyDefaultCellWidths = applyDefaultCellWidths;
1342 }
1343
1344
1345
1346
1347 @Override
1348 @BeanTagAttribute
1349 public List<String> getRowCssClasses() {
1350 return rowCssClasses;
1351 }
1352
1353
1354
1355
1356 @Override
1357 public void setRowCssClasses(List<String> rowCssClasses) {
1358 this.rowCssClasses = rowCssClasses;
1359 }
1360
1361
1362
1363
1364 @Override
1365 @BeanTagAttribute
1366 public List<String> getRowDataAttributes() {
1367 return rowDataAttributes;
1368 }
1369
1370
1371
1372
1373 @Override
1374 public void setRowDataAttributes(List<String> rowDataAttributes) {
1375 this.rowDataAttributes = rowDataAttributes;
1376 }
1377
1378
1379
1380
1381 @Override
1382 @BeanTagAttribute
1383 public boolean isUseShortLabels() {
1384 return this.useShortLabels;
1385 }
1386
1387
1388
1389
1390 @Override
1391 public void setUseShortLabels(boolean useShortLabels) {
1392 this.useShortLabels = useShortLabels;
1393 }
1394
1395
1396
1397
1398 @Override
1399 @BeanTagAttribute
1400 public boolean isRepeatHeader() {
1401 return this.repeatHeader;
1402 }
1403
1404
1405
1406
1407 @Override
1408 public void setRepeatHeader(boolean repeatHeader) {
1409 this.repeatHeader = repeatHeader;
1410 }
1411
1412
1413
1414
1415 @Override
1416 @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
1417 @BeanTagAttribute
1418 public Label getHeaderLabelPrototype() {
1419 return this.headerLabelPrototype;
1420 }
1421
1422
1423
1424
1425 @Override
1426 public void setHeaderLabelPrototype(Label headerLabelPrototype) {
1427 this.headerLabelPrototype = headerLabelPrototype;
1428 }
1429
1430
1431
1432
1433 @Override
1434 public List<Label> getHeaderLabels() {
1435 return this.headerLabels;
1436 }
1437
1438
1439
1440
1441 @Override
1442 @BeanTagAttribute
1443 public boolean isRenderSequenceField() {
1444 return this.renderSequenceField;
1445 }
1446
1447
1448
1449
1450 @Override
1451 public void setRenderSequenceField(boolean renderSequenceField) {
1452 this.renderSequenceField = renderSequenceField;
1453 }
1454
1455
1456
1457
1458 @Override
1459 @BeanTagAttribute
1460 public String getSequencePropertyName() {
1461 if ((getSequenceFieldPrototype() != null) && (getSequenceFieldPrototype() instanceof DataField)) {
1462 return ((DataField) getSequenceFieldPrototype()).getPropertyName();
1463 }
1464
1465 return null;
1466 }
1467
1468
1469
1470
1471 @Override
1472 public void setSequencePropertyName(String sequencePropertyName) {
1473 if ((getSequenceFieldPrototype() != null) && (getSequenceFieldPrototype() instanceof DataField)) {
1474 ((DataField) getSequenceFieldPrototype()).setPropertyName(sequencePropertyName);
1475 }
1476 }
1477
1478
1479
1480
1481 @Override
1482 @BeanTagAttribute
1483 public boolean isGenerateAutoSequence() {
1484 return this.generateAutoSequence;
1485 }
1486
1487
1488
1489
1490 @Override
1491 public void setGenerateAutoSequence(boolean generateAutoSequence) {
1492 this.generateAutoSequence = generateAutoSequence;
1493 }
1494
1495
1496
1497
1498 @Override
1499 @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
1500 @BeanTagAttribute
1501 public Field getSequenceFieldPrototype() {
1502 return this.sequenceFieldPrototype;
1503 }
1504
1505
1506
1507
1508 @Override
1509 public void setSequenceFieldPrototype(Field sequenceFieldPrototype) {
1510 this.sequenceFieldPrototype = sequenceFieldPrototype;
1511 }
1512
1513
1514
1515
1516 @Override
1517 @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
1518 @BeanTagAttribute
1519 public FieldGroup getActionFieldPrototype() {
1520 return this.actionFieldPrototype;
1521 }
1522
1523
1524
1525
1526 @Override
1527 public void setActionFieldPrototype(FieldGroup actionFieldPrototype) {
1528 this.actionFieldPrototype = actionFieldPrototype;
1529 }
1530
1531
1532
1533
1534 @Override
1535 @BeanTagAttribute
1536 public boolean isSeparateAddLine() {
1537 return separateAddLine;
1538 }
1539
1540
1541
1542
1543 @Override
1544 public void setSeparateAddLine(boolean separateAddLine) {
1545 this.separateAddLine = separateAddLine;
1546 }
1547
1548
1549
1550
1551 @Override
1552 public List<Field> getAllRowFields() {
1553 return this.allRowFields;
1554 }
1555
1556
1557
1558
1559 @Override
1560 @ViewLifecycleRestriction
1561 public List<Field> getFirstRowFields() {
1562 return firstRowFields;
1563 }
1564
1565
1566
1567
1568 @Override
1569 @BeanTagAttribute(type = BeanTagAttribute.AttributeType.DIRECTORBYTYPE)
1570 public RichTable getRichTable() {
1571 return this.richTable;
1572 }
1573
1574
1575
1576
1577 @Override
1578 public void setRichTable(RichTable richTable) {
1579 this.richTable = richTable;
1580 }
1581
1582
1583
1584
1585 @Override
1586 @BeanTagAttribute
1587 public int getNumberOfDataColumns() {
1588 return this.numberOfDataColumns;
1589 }
1590
1591
1592
1593
1594 @Override
1595 public void setNumberOfDataColumns(int numberOfDataColumns) {
1596 this.numberOfDataColumns = numberOfDataColumns;
1597 }
1598
1599
1600
1601
1602 @Override
1603 @BeanTagAttribute(type = BeanTagAttribute.AttributeType.SETVALUE)
1604 public Set<String> getHiddenColumns() {
1605 if (richTable != null) {
1606 return richTable.getHiddenColumns();
1607 }
1608
1609 return null;
1610 }
1611
1612
1613
1614
1615 @Override
1616 public void setHiddenColumns(Set<String> hiddenColumns) {
1617 if (richTable != null) {
1618 richTable.setHiddenColumns(hiddenColumns);
1619 }
1620 }
1621
1622
1623
1624
1625 @Override
1626 @BeanTagAttribute(type = BeanTagAttribute.AttributeType.SETVALUE)
1627 public Set<String> getSortableColumns() {
1628 if (richTable != null) {
1629 return richTable.getSortableColumns();
1630 }
1631
1632 return null;
1633 }
1634
1635
1636
1637
1638 @Override
1639 public void setSortableColumns(Set<String> sortableColumns) {
1640 if (richTable != null) {
1641 richTable.setSortableColumns(sortableColumns);
1642 }
1643 }
1644
1645
1646
1647
1648 @Override
1649 public int getActionColumnIndex() {
1650 return actionColumnIndex;
1651 }
1652
1653
1654
1655
1656 @Override
1657 @BeanTagAttribute
1658 public String getActionColumnPlacement() {
1659 return actionColumnPlacement;
1660 }
1661
1662
1663
1664
1665 @Override
1666 public void setActionColumnPlacement(String actionColumnPlacement) {
1667 this.actionColumnPlacement = actionColumnPlacement;
1668
1669 if ("LEFT".equals(actionColumnPlacement)) {
1670 actionColumnIndex = 1;
1671 } else if ("RIGHT".equals(actionColumnPlacement)) {
1672 actionColumnIndex = -1;
1673 } else if (StringUtils.isNumeric(actionColumnPlacement)) {
1674 actionColumnIndex = Integer.parseInt(actionColumnPlacement);
1675 }
1676 }
1677
1678
1679
1680
1681 @Override
1682 @ViewLifecycleRestriction(UifConstants.ViewPhases.PRE_PROCESS)
1683 @BeanTagAttribute
1684 public Group getRowDetailsGroup() {
1685 return rowDetailsGroup;
1686 }
1687
1688
1689
1690
1691 @Override
1692 public void setRowDetailsGroup(Group rowDetailsGroup) {
1693 this.rowDetailsGroup = rowDetailsGroup;
1694 }
1695
1696
1697
1698
1699
1700
1701
1702
1703 public void setupDetails(CollectionGroup collectionGroup) {
1704 if (getRowDetailsGroup() == null || this.getRichTable() == null || !this.getRichTable().isRender()) {
1705 return;
1706 }
1707
1708
1709 collectionGroup.addDataAttribute(UifConstants.DataAttributes.DETAILS_DEFAULT_OPEN, Boolean.toString(
1710 this.rowDetailsOpen));
1711
1712 toggleAllDetailsAction.addDataAttribute("open", Boolean.toString(this.rowDetailsOpen));
1713 toggleAllDetailsAction.addDataAttribute("tableid", this.getId());
1714
1715 FieldGroup detailsFieldGroup = ComponentFactory.getFieldGroup();
1716
1717 TreeMap<String, String> dataAttributes = new TreeMap<String, String>();
1718 dataAttributes.put(UifConstants.DataAttributes.ROLE, "detailsFieldGroup");
1719 detailsFieldGroup.setDataAttributes(dataAttributes);
1720
1721 Action rowDetailsAction = this.getExpandDetailsActionPrototype();
1722 rowDetailsAction.addDataAttribute(UifConstants.DataAttributes.ROLE, "detailsLink");
1723 rowDetailsAction.setId(collectionGroup.getId() + UifConstants.IdSuffixes.DETAIL_LINK);
1724
1725 List<Component> detailsItems = new ArrayList<Component>();
1726 detailsItems.add(rowDetailsAction);
1727
1728 dataAttributes = new TreeMap<String, String>();
1729 dataAttributes.put("role", "details");
1730 dataAttributes.put("open", Boolean.toString(this.rowDetailsOpen));
1731 this.getRowDetailsGroup().setDataAttributes(dataAttributes);
1732
1733 detailsItems.add(getRowDetailsGroup());
1734 detailsFieldGroup.setItems(detailsItems);
1735 detailsFieldGroup.setId(collectionGroup.getId() + UifConstants.IdSuffixes.DETAIL_GROUP);
1736 this.getRowDetailsGroup().setHidden(true);
1737
1738 if (ajaxDetailsRetrieval) {
1739 this.getRowDetailsGroup().setRetrieveViaAjax(true);
1740 }
1741
1742 detailsFieldGroup.setReadOnly(collectionGroup.getReadOnly());
1743
1744 List<Component> theItems = new ArrayList<Component>();
1745 theItems.add(detailsFieldGroup);
1746 theItems.addAll(collectionGroup.getItems());
1747
1748 collectionGroup.setItems(theItems);
1749 }
1750
1751
1752
1753
1754 @Override
1755 public List<String> getColumnsToCalculate() {
1756 return columnsToCalculate;
1757 }
1758
1759
1760
1761
1762 @Override
1763 @BeanTagAttribute
1764 public boolean isShowTotal() {
1765 return showTotal;
1766 }
1767
1768
1769
1770
1771 @Override
1772 public void setShowTotal(boolean showTotal) {
1773 this.showTotal = showTotal;
1774 }
1775
1776
1777
1778
1779 @Override
1780 @BeanTagAttribute
1781 public boolean isShowPageTotal() {
1782 return showPageTotal;
1783 }
1784
1785
1786
1787
1788 @Override
1789 public void setShowPageTotal(boolean showPageTotal) {
1790 this.showPageTotal = showPageTotal;
1791 }
1792
1793
1794
1795
1796 @Override
1797 @BeanTagAttribute
1798 public boolean isShowGroupTotal() {
1799 return showGroupTotal;
1800 }
1801
1802
1803
1804
1805 @Override
1806 public void setShowGroupTotal(boolean showGroupTotal) {
1807 this.showGroupTotal = showGroupTotal;
1808 }
1809
1810
1811
1812
1813 @Override
1814 @BeanTagAttribute
1815 public Label getTotalLabel() {
1816 return totalLabel;
1817 }
1818
1819
1820
1821
1822 @Override
1823 public void setTotalLabel(Label totalLabel) {
1824 this.totalLabel = totalLabel;
1825 }
1826
1827
1828
1829
1830 @Override
1831 @BeanTagAttribute
1832 public Label getPageTotalLabel() {
1833 return pageTotalLabel;
1834 }
1835
1836
1837
1838
1839 @Override
1840 public void setPageTotalLabel(Label pageTotalLabel) {
1841 this.pageTotalLabel = pageTotalLabel;
1842 }
1843
1844
1845
1846
1847 @Override
1848 @BeanTagAttribute
1849 public Label getGroupTotalLabelPrototype() {
1850 return groupTotalLabelPrototype;
1851 }
1852
1853
1854
1855
1856 @Override
1857 public void setGroupTotalLabelPrototype(Label groupTotalLabelPrototype) {
1858 this.groupTotalLabelPrototype = groupTotalLabelPrototype;
1859 }
1860
1861
1862
1863
1864 @Override
1865 @BeanTagAttribute
1866 public List<ColumnCalculationInfo> getColumnCalculations() {
1867 return columnCalculations;
1868 }
1869
1870
1871
1872
1873 @Override
1874 public void setColumnCalculations(List<ColumnCalculationInfo> columnCalculations) {
1875 this.columnCalculations = columnCalculations;
1876 }
1877
1878
1879
1880
1881 @Override
1882 @BeanTagAttribute
1883 public boolean isRenderOnlyLeftTotalLabels() {
1884 return renderOnlyLeftTotalLabels;
1885 }
1886
1887
1888
1889
1890 @Override
1891 public void setRenderOnlyLeftTotalLabels(boolean renderOnlyLeftTotalLabels) {
1892 this.renderOnlyLeftTotalLabels = renderOnlyLeftTotalLabels;
1893 }
1894
1895
1896
1897
1898 @Override
1899 public List<Component> getFooterCalculationComponents() {
1900 return footerCalculationComponents;
1901 }
1902
1903
1904
1905
1906 @Override
1907 @BeanTagAttribute
1908 public List<String> getGroupingPropertyNames() {
1909 return groupingPropertyNames;
1910 }
1911
1912
1913
1914
1915 @Override
1916 public void setGroupingPropertyNames(List<String> groupingPropertyNames) {
1917 this.groupingPropertyNames = groupingPropertyNames;
1918 }
1919
1920
1921
1922
1923 @Override
1924 @BeanTagAttribute
1925 public String getGroupingTitle() {
1926 return groupingTitle;
1927 }
1928
1929
1930
1931
1932 @Override
1933 public void setGroupingTitle(String groupingTitle) {
1934 if (groupingTitle != null && !groupingTitle.contains("@{")) {
1935 throw new RuntimeException("groupingTitle MUST contain a springEL expression to uniquely"
1936 + " identify a collection group (often related to some value of the line). " + "Value provided: "
1937 + this.getGroupingTitle());
1938 }
1939 this.groupingTitle = groupingTitle;
1940 }
1941
1942
1943
1944
1945 @Override
1946 @BeanTagAttribute
1947 public String getGroupingPrefix() {
1948 return groupingPrefix;
1949 }
1950
1951
1952
1953
1954 @Override
1955 public void setGroupingPrefix(String groupingPrefix) {
1956 this.groupingPrefix = groupingPrefix;
1957 }
1958
1959
1960
1961
1962 @Override
1963 @BeanTagAttribute
1964 public boolean isRowDetailsOpen() {
1965 return rowDetailsOpen;
1966 }
1967
1968
1969
1970
1971 @Override
1972 public void setRowDetailsOpen(boolean rowDetailsOpen) {
1973 this.rowDetailsOpen = rowDetailsOpen;
1974 }
1975
1976
1977
1978
1979 @Override
1980 @BeanTagAttribute
1981 public boolean isShowToggleAllDetails() {
1982 return showToggleAllDetails;
1983 }
1984
1985
1986
1987
1988 @Override
1989 public void setShowToggleAllDetails(boolean showToggleAllDetails) {
1990 this.showToggleAllDetails = showToggleAllDetails;
1991 }
1992
1993
1994
1995
1996 @Override
1997 @BeanTagAttribute
1998 public Action getToggleAllDetailsAction() {
1999 return toggleAllDetailsAction;
2000 }
2001
2002
2003
2004
2005 @Override
2006 public void setToggleAllDetailsAction(Action toggleAllDetailsAction) {
2007 this.toggleAllDetailsAction = toggleAllDetailsAction;
2008 }
2009
2010
2011
2012
2013 @Override
2014 @BeanTagAttribute
2015 public boolean isAjaxDetailsRetrieval() {
2016 return ajaxDetailsRetrieval;
2017 }
2018
2019
2020
2021
2022 @Override
2023 public void setAjaxDetailsRetrieval(boolean ajaxDetailsRetrieval) {
2024 this.ajaxDetailsRetrieval = ajaxDetailsRetrieval;
2025 }
2026
2027
2028
2029
2030 @Override
2031 @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
2032 @BeanTagAttribute
2033 public Action getExpandDetailsActionPrototype() {
2034 return expandDetailsActionPrototype;
2035 }
2036
2037
2038
2039
2040 @Override
2041 public int getGroupingColumnIndex() {
2042 return groupingColumnIndex;
2043 }
2044
2045
2046
2047
2048 @Override
2049 public void setExpandDetailsActionPrototype(Action expandDetailsActionPrototype) {
2050 this.expandDetailsActionPrototype = expandDetailsActionPrototype;
2051 }
2052
2053
2054
2055
2056 protected void setHeaderLabels(List<Label> headerLabels) {
2057 this.headerLabels = headerLabels;
2058 }
2059
2060
2061
2062
2063 protected void setAllRowFields(List<Field> allRowFields) {
2064 this.allRowFields = allRowFields;
2065 }
2066
2067
2068
2069
2070 protected void setFirstRowFields(List<Field> firstRowFields) {
2071 this.firstRowFields = firstRowFields;
2072 }
2073
2074
2075
2076
2077 protected void setHeaderAdded(boolean headerAdded) {
2078 this.headerAdded = headerAdded;
2079 }
2080
2081
2082
2083
2084 protected void setActionColumnIndex(int actionColumnIndex) {
2085 this.actionColumnIndex = actionColumnIndex;
2086 }
2087
2088
2089
2090
2091 protected void setGroupingColumnIndex(int groupingColumnIndex) {
2092 this.groupingColumnIndex = groupingColumnIndex;
2093 }
2094
2095
2096
2097
2098 protected void setGenerateGroupTotalRows(boolean generateGroupTotalRows) {
2099 this.generateGroupTotalRows = generateGroupTotalRows;
2100 }
2101
2102
2103
2104
2105 protected void setColumnsToCalculate(List<String> columnsToCalculate) {
2106 this.columnsToCalculate = columnsToCalculate;
2107 }
2108
2109
2110
2111
2112 protected void setFooterCalculationComponents(List<Component> footerCalculationComponents) {
2113 this.footerCalculationComponents = footerCalculationComponents;
2114 }
2115
2116
2117
2118
2119 @BeanTagAttribute
2120 public Map<String, String> getConditionalRowCssClasses() {
2121 return conditionalRowCssClasses;
2122 }
2123
2124
2125
2126
2127 @Override
2128 public void setConditionalRowCssClasses(Map<String, String> conditionalRowCssClasses) {
2129 this.conditionalRowCssClasses = conditionalRowCssClasses;
2130 }
2131
2132
2133
2134
2135
2136
2137
2138 public void completeValidation(ValidationTrace tracer) {
2139 tracer.addBean("TableLayoutManager", getId());
2140
2141 if (getRowDetailsGroup() != null) {
2142 boolean validTable = false;
2143 if (getRichTable() != null) {
2144 if (getRichTable().isRender()) {
2145 validTable = true;
2146 }
2147 }
2148 if (!validTable) {
2149 String currentValues[] = {"rowDetailsGroup =" + getRowDetailsGroup(), "richTable =" + getRichTable()};
2150 tracer.createError("If rowDetailsGroup is set richTable must be set and its render true", currentValues);
2151 }
2152 }
2153 }
2154 }