View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.uif.container;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.exception.RiceRuntimeException;
20  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
21  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
22  import org.kuali.rice.krad.datadictionary.parse.BeanTags;
23  import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
24  import org.kuali.rice.krad.datadictionary.validator.Validator;
25  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
26  import org.kuali.rice.krad.uif.UifConstants;
27  import org.kuali.rice.krad.uif.UifParameters;
28  import org.kuali.rice.krad.uif.UifPropertyPaths;
29  import org.kuali.rice.krad.uif.component.BindingInfo;
30  import org.kuali.rice.krad.uif.component.ClientSideState;
31  import org.kuali.rice.krad.uif.component.Component;
32  import org.kuali.rice.krad.uif.component.ComponentSecurity;
33  import org.kuali.rice.krad.uif.component.DelayedCopy;
34  import org.kuali.rice.krad.uif.component.KeepExpression;
35  import org.kuali.rice.krad.uif.element.Action;
36  import org.kuali.rice.krad.uif.element.Message;
37  import org.kuali.rice.krad.uif.field.DataField;
38  import org.kuali.rice.krad.uif.field.FieldGroup;
39  import org.kuali.rice.krad.uif.field.InputField;
40  import org.kuali.rice.krad.uif.layout.CollectionLayoutManager;
41  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
42  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleRestriction;
43  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleUtils;
44  import org.kuali.rice.krad.uif.util.ComponentFactory;
45  import org.kuali.rice.krad.uif.util.ComponentUtils;
46  import org.kuali.rice.krad.uif.util.ContextUtils;
47  import org.kuali.rice.krad.uif.util.LifecycleElement;
48  import org.kuali.rice.krad.uif.util.ScriptUtils;
49  import org.kuali.rice.krad.uif.view.View;
50  import org.kuali.rice.krad.uif.view.ViewModel;
51  import org.kuali.rice.krad.uif.widget.QuickFinder;
52  import org.kuali.rice.krad.util.KRADUtils;
53  
54  import java.util.ArrayList;
55  import java.util.Collection;
56  import java.util.Collections;
57  import java.util.List;
58  
59  /**
60   * Group that holds a collection of objects and configuration for presenting the
61   * collection in the UI. Supports functionality such as add line, line actions,
62   * and nested collections.
63   *
64   * <p>
65   * Note the standard header/footer can be used to give a header to the
66   * collection as a whole, or to provide actions that apply to the entire
67   * collection
68   * </p>
69   *
70   * <p>
71   * For binding purposes the binding path of each row field is indexed. The name
72   * property inherited from <code>ComponentBase</code> is used as the collection
73   * name. The collectionObjectClass property is used to lookup attributes from
74   * the data dictionary.
75   * </p>
76   *
77   * @author Kuali Rice Team (rice.collab@kuali.org)
78   */
79  @BeanTags({@BeanTag(name = "collectionGroup", parent = "Uif-CollectionGroupBase"),
80          @BeanTag(name = "stacked", parent = "Uif-StackedCollectionGroup"),
81          @BeanTag(name = "stackedSection", parent = "Uif-StackedCollectionSection"),
82          @BeanTag(name = "stackedSubSection", parent = "Uif-StackedCollectionSubSection"),
83          @BeanTag(name = "stackedSubCollection-withinSection", parent = "Uif-StackedSubCollection-WithinSection"),
84          @BeanTag(name = "stackedSubCollection-withinSubSection",
85                  parent = "Uif-StackedSubCollection-WithinSubSection"),
86          @BeanTag(name = "disclosureStackedSection", parent = "Uif-Disclosure-StackedCollectionSection"),
87          @BeanTag(name = "disclosureStackedSubSection",
88                  parent = "Uif-Disclosure-StackedCollectionSubSection"),
89          @BeanTag(name = "disclosureStackedSubCollection-withinSection",
90                  parent = "Uif-Disclosure-StackedSubCollection-WithinSection"),
91          @BeanTag(name = "disclosureStackedSubCollection-withinSubSection",
92                  parent = "Uif-Disclosure-StackedSubCollection-WithinSubSection"),
93          @BeanTag(name = "table", parent = "Uif-TableCollectionGroup"),
94          @BeanTag(name = "tableSection", parent = "Uif-TableCollectionSection"),
95          @BeanTag(name = "tableSubSection", parent = "Uif-TableCollectionSubSection"),
96          @BeanTag(name = "tableSubCollection-withinSection", parent = "Uif-TableSubCollection-WithinSection"),
97          @BeanTag(name = "tableSubCollection-withinSubSection", parent = "Uif-TableSubCollection-WithinSubSection"),
98          @BeanTag(name = "disclosureTableSection", parent = "Uif-Disclosure-TableCollectionSection"),
99          @BeanTag(name = "disclosureTableSubSection",
100                 parent = "Uif-Disclosure-TableCollectionSubSection"),
101         @BeanTag(name = "disclosureTableSubCollection-withinSection",
102                 parent = "Uif-Disclosure-TableSubCollection-WithinSection"),
103         @BeanTag(name = "disclosureTableSubCollection-withinSubSection",
104                 parent = "Uif-Disclosure-TableSubCollection-WithinSubSection"),
105         @BeanTag(name = "listCollection", parent = "Uif-ListCollectionGroup"),
106         @BeanTag(name = "listCollectionSection", parent = "Uif-ListCollectionSection"),
107         @BeanTag(name = "listCollectionSubSection", parent = "Uif-ListCollectionSubSection"),
108         @BeanTag(name = "maintenanceStackedSection", parent = "Uif-MaintenanceStackedCollectionSection"),
109         @BeanTag(name = "maintenanceStackedSubCollection-withinSection",
110                 parent = "Uif-MaintenanceStackedSubCollection-WithinSection"),
111         @BeanTag(name = "maintenanceTableSection", parent = "Uif-MaintenanceTableCollectionSection"),
112         @BeanTag(name = "maintenanceTableSubCollection-withinSection",
113                 parent = "Uif-MaintenanceTableSubCollection-WithinSection")})
114 public class CollectionGroupBase extends GroupBase implements CollectionGroup {
115 
116     private static final long serialVersionUID = -6496712566071542452L;
117 
118     private Class<?> collectionObjectClass;
119 
120     private String propertyName;
121     private BindingInfo bindingInfo;
122 
123     private boolean renderAddLine;
124     private String addLinePropertyName;
125     private BindingInfo addLineBindingInfo;
126 
127     private Message addLineLabel;
128 
129     private List<? extends Component> addLineItems;
130     private List<? extends Component> addLineActions;
131 
132     @KeepExpression
133     private String addLineEnterKeyAction;
134 
135     @KeepExpression
136     private String lineEnterKeyAction;
137 
138     private boolean renderLineActions;
139     private List<? extends Component> lineActions;
140 
141     private boolean includeLineSelectionField;
142     private String lineSelectPropertyName;
143 
144     private QuickFinder collectionLookup;
145 
146     private boolean renderInactiveToggleButton;
147     @ClientSideState(variableName = "inactive")
148     private boolean showInactiveLines;
149     private CollectionFilter activeCollectionFilter;
150     private List<CollectionFilter> filters;
151 
152     private List<String> duplicateLinePropertyNames;
153 
154     private List<BindingInfo> unauthorizedLineBindingInfos;
155 
156     @DelayedCopy
157     private List<CollectionGroup> subCollections;
158 
159     private CollectionGroupBuilder collectionGroupBuilder;
160 
161     private int displayCollectionSize = -1;
162 
163     private boolean highlightNewItems;
164     private boolean highlightAddItem;
165     private String newItemsCssClass;
166     private String addItemCssClass;
167 
168     private boolean renderAddBlankLineButton;
169     private Action addBlankLineAction;
170     private String addLinePlacement;
171 
172     private boolean renderSaveLineActions;
173 
174     // edit line properties
175     private boolean editWithDialog;
176     private boolean customEditLineDialog;
177     private DialogGroup editLineDialogPrototype;
178     private Action editWithDialogActionPrototype;
179     private Action editInDialogSaveActionPrototype;
180 
181     private List<DialogGroup> lineDialogs;
182 
183     private boolean addWithDialog;
184     private Action addWithDialogAction;
185     private DialogGroup addLineDialog;
186 
187     private boolean useServerPaging = false;
188     private int pageSize;
189     private int displayStart = -1;
190     private int displayLength = -1;
191     private int filteredCollectionSize = -1;
192     private int totalCollectionSize = -1;
193 
194     private List<String> totalColumns;
195 
196     public CollectionGroupBase() {
197         renderAddLine = true;
198         renderLineActions = true;
199         renderInactiveToggleButton = true;
200         highlightNewItems = true;
201         highlightAddItem = true;
202         addLinePlacement = "TOP";
203 
204         filters = Collections.emptyList();
205         duplicateLinePropertyNames = Collections.emptyList();
206         lineActions = Collections.emptyList();
207         addLineItems = Collections.emptyList();
208         addLineActions = Collections.emptyList();
209         subCollections = Collections.emptyList();
210         lineDialogs = Collections.emptyList();
211     }
212 
213     /**
214      * @{inheritDoc}
215      */
216     @Override
217     public void performInitialization(Object model) {
218         View view = ViewLifecycle.getView();
219 
220         setFieldBindingObjectPath(getBindingInfo().getBindingObjectPath());
221 
222         super.performInitialization(model);
223 
224         if (bindingInfo != null) {
225             bindingInfo.setDefaults(view, getPropertyName());
226         }
227 
228         if (addLineBindingInfo != null) {
229             // add line binds to model property
230             if (StringUtils.isNotBlank(addLinePropertyName)) {
231                 addLineBindingInfo.setDefaults(view, getPropertyName());
232                 addLineBindingInfo.setBindingName(addLinePropertyName);
233 
234                 if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
235                     addLineBindingInfo.setBindByNamePrefix(getFieldBindByNamePrefix());
236                 }
237             }
238         }
239 
240         // if no add line items specified then assume same items showing
241         if ((addLineItems == null) || addLineItems.isEmpty()) {
242             addLineItems = getItems();
243         }
244 
245         // if addWithDialog...
246         if (addWithDialog) {
247             // if not defined use default
248             if (addLineDialog == null) {
249                 addLineDialog = (DialogGroup) ComponentFactory.getNewComponentInstance(
250                         ComponentFactory.ADD_LINE_DIALOG);
251             }
252             // assign this group to the layout manager
253             ((CollectionLayoutManager) getLayoutManager()).setAddLineGroup(addLineDialog);
254             // if the add dialog group had items then use them
255             if (!addLineDialog.getItems().isEmpty()) {
256                 addLineItems = addLineDialog.getItems();
257             }
258         }
259 
260         // if its a edit line in dialog, then set the edit line dialog and edit line action if not supplied
261         if (editWithDialog) {
262 
263             // initialize edit line dialog prototype if not set
264             if (editLineDialogPrototype == null) {
265                 editLineDialogPrototype = (DialogGroup) ComponentUtils.copy(ComponentFactory.
266                         getNewComponentInstance(ComponentFactory.EDIT_LINE_DIALOG));
267             } else if (editLineDialogPrototype.getItems() != null && !editLineDialogPrototype.getItems().isEmpty()) {
268                 // set custom dialog flag
269                 customEditLineDialog = true;
270             }
271 
272             // initialize the edit line action prototype if not set
273             if (editWithDialogActionPrototype == null) {
274                 editWithDialogActionPrototype = (Action) ComponentUtils.copy(ComponentFactory.
275                         getNewComponentInstance(ComponentFactory.EDIT_LINE_IN_DIALOG_ACTION));
276             }
277 
278             // initialize the edit line dialog's save action prototype
279             if (editInDialogSaveActionPrototype == null) {
280                 editInDialogSaveActionPrototype = ComponentUtils.copy((Action) ComponentFactory.
281                         getNewComponentInstance(ComponentFactory.EDIT_LINE_IN_DIALOG_SAVE_ACTION));
282             }
283         }
284 
285         // if active collection filter not set use default
286         if (activeCollectionFilter == null) {
287             activeCollectionFilter = new ActiveCollectionFilter();
288         }
289 
290         // set static collection path on items
291         String collectionPath = "";
292         if (StringUtils.isNotBlank(getBindingInfo().getCollectionPath())) {
293             collectionPath += getBindingInfo().getCollectionPath() + ".";
294         }
295 
296         // Check to see if binding prefix path starts the same as the collection path,
297         // and if it does just start with that instead
298         if (StringUtils.isNotBlank(getBindingInfo().getBindByNamePrefix()) && StringUtils.isNotBlank(
299                 getBindingInfo().getCollectionPath()) && getBindingInfo().getBindByNamePrefix().startsWith(
300                 getBindingInfo().getCollectionPath())) {
301             collectionPath = getBindingInfo().getBindByNamePrefix() + ".";
302         } else if (StringUtils.isNotBlank(getBindingInfo().getBindByNamePrefix())) {
303             collectionPath += getBindingInfo().getBindByNamePrefix() + ".";
304         }
305 
306         collectionPath += getBindingInfo().getBindingName();
307 
308         List<DataField> collectionFields = ComponentUtils.getNestedNonCollectionComponents((List<Component>) getItems(),
309                 DataField.class);
310         List<DataField> addLineCollectionFields = ComponentUtils.getNestedNonCollectionComponents(
311                 (List<Component>) addLineItems, DataField.class);
312         if (addLineCollectionFields != null) {
313             collectionFields.addAll(addLineCollectionFields);
314         }
315 
316         for (DataField collectionField : collectionFields) {
317             collectionField.getBindingInfo().setCollectionPath(collectionPath);
318 
319             if (StringUtils.isBlank(collectionField.getDictionaryObjectEntry())) {
320                 collectionField.setDictionaryObjectEntry(collectionObjectClass.getName());
321             }
322         }
323 
324         for (CollectionGroup collectionGroup : getSubCollections()) {
325             collectionGroup.getBindingInfo().setCollectionPath(collectionPath);
326         }
327 
328         // add collection entry to abstract classes
329         if (!view.getObjectPathToConcreteClassMapping().containsKey(collectionPath)) {
330             view.getObjectPathToConcreteClassMapping().put(collectionPath, getCollectionObjectClass());
331         }
332     }
333 
334     /**
335      * {@inheritDoc}
336      */
337     @Override
338     public void performApplyModel(Object model, LifecycleElement parent) {
339         super.performApplyModel(model, parent);
340 
341         ViewModel viewModel = (ViewModel) model;
342         View view = ViewLifecycle.getView();
343 
344         // if server paging is enabled get the display start from post data so we build the correct page
345         if (this.isUseServerPaging()) {
346             Object displayStart = ViewLifecycle.getViewPostMetadata().getComponentPostData(this.getId(),
347                     UifConstants.PostMetadata.COLL_DISPLAY_START);
348             if (displayStart != null) {
349                 this.setDisplayStart(((Integer) displayStart).intValue());
350             }
351 
352             Object displayLength = ViewLifecycle.getViewPostMetadata().getComponentPostData(this.getId(),
353                     UifConstants.PostMetadata.COLL_DISPLAY_LENGTH);
354             if (displayLength != null) {
355                 this.setDisplayLength(((Integer) displayLength).intValue());
356             }
357         }
358 
359         // if we are processing a paging request for this component, invoke the layout managers to carry out the paging
360         if (viewModel.isCollectionPagingRequest() && StringUtils.equals(viewModel.getUpdateComponentId(), getId())) {
361             ((CollectionLayoutManager) getLayoutManager()).processPagingRequest(model, this);
362         }
363 
364         if (StringUtils.isNotBlank(this.getId()) && viewModel.getViewPostMetadata() != null
365                 && viewModel.getViewPostMetadata().getAddedCollectionObjects().get(this.getId()) != null) {
366             List<Object> newLines = viewModel.getViewPostMetadata().getAddedCollectionObjects().get(this.getId());
367 
368             // if newLines is empty this means its an addLine case (no additional processing) so init collection line
369             if (newLines.isEmpty()) {
370                 initializeNewCollectionLine(view, model, this, true);
371             }
372 
373             for (Object newLine : newLines) {
374                 ViewLifecycle.getHelper().applyDefaultValuesForCollectionLine(this, newLine);
375             }
376         }
377 
378         // adds the script to the add line buttons to keep collection on the same page
379         if (this.renderAddBlankLineButton) {
380             if (this.addBlankLineAction == null) {
381                 this.addBlankLineAction = (Action) ComponentFactory.getNewComponentInstance(
382                         ComponentFactory.ADD_BLANK_LINE_ACTION);
383             }
384 
385             if (addLinePlacement.equals(UifConstants.Position.BOTTOM.name())) {
386                 this.addBlankLineAction.setOnClickScript("writeCurrentPageToSession(this, 'last');");
387             } else {
388                 this.addBlankLineAction.setOnClickScript("writeCurrentPageToSession(this, 'first');");
389             }
390         } else if (this.addWithDialog) {
391             setupAddLineDialog();
392         }
393 
394         pushCollectionGroupToReference();
395 
396         // set up action validation scripts to avoid bind errors
397         List<Component> allComponents = new ArrayList<Component>(getItems());
398         allComponents.addAll(getAddLineItems());
399         List<Component> allActionComponents = new ArrayList<Component>(getLineActions());
400         allActionComponents.addAll(getAddLineActions());
401         setupLineActionValidationScripts(allComponents, allActionComponents);
402 
403         // if rendering the collection group, build out the lines
404         if (isRender()) {
405             getCollectionGroupBuilder().build(view, model, this);
406         }
407     }
408 
409     /**
410      * Helper method to set action validation script for every action component provided to validate every
411      * input field component.
412      *
413      * @param components the components with input fields
414      * @param actionComponents the components with actions
415      */
416     protected void setupLineActionValidationScripts(List<Component> components, List<Component> actionComponents) {
417         List<InputField> inputFields = new ArrayList<InputField>();
418         for (Component component : components) {
419             if (component instanceof InputField) {
420                 inputFields.add((InputField) component);
421             }
422         }
423 
424         String script = buildInputFieldValidationActionScript(inputFields, null);
425         for (Component actionComponent : actionComponents) {
426             if (actionComponent instanceof Action) {
427                 Action action = (Action) actionComponent;
428                 String onClickScript = action.getOnClickScript();
429                 if (StringUtils.isNotEmpty(onClickScript)) {
430                     script = ScriptUtils.appendScript(script, onClickScript);
431                 }
432                 action.setOnClickScript(script);
433             }
434         }
435     }
436 
437     /**
438      * When add via dialog is true, initialize the add with dialog action (if necessary) and sets up the
439      * action script for opening the dialog.
440      */
441     protected void setupAddLineDialog() {
442         if (addWithDialogAction == null) {
443             addWithDialogAction = (Action) ComponentFactory.getNewComponentInstance(
444                     ComponentFactory.ADD_WITH_DIALOG_ACTION);
445         }
446 
447         String sessionPage = "first";
448         if (addLinePlacement.equals(UifConstants.Position.BOTTOM.name())) {
449             sessionPage = "last";
450         }
451 
452         String dialogId = addLineDialog.getId();
453         if (StringUtils.isNotBlank(this.getContainerIdSuffix())) {
454             dialogId = dialogId + this.getContainerIdSuffix();
455         }
456 
457         // add the dialog id as additional parameters to the actions in the dialog
458         String additionalData =
459                 "{ '" + UifPropertyPaths.ACTION_PARAMETERS + "[" + UifParameters.SELECTED_COLLECTION_PATH + "]' : '"
460                         + propertyName + "', '" + UifPropertyPaths.ACTION_PARAMETERS + "["
461                         + UifParameters.SELECTED_LINE_INDEX + "]' : '0', '" + UifPropertyPaths.ACTION_PARAMETERS + "["
462                         + UifParameters.DIALOG_ID + "]' : '" + dialogId + "' }";
463         String actionScript = UifConstants.JsFunctions.WRITE_CURRENT_PAGE_TO_SESSION + "(this, '" + sessionPage + "');";
464 
465         actionScript = ScriptUtils.appendScript(addWithDialogAction.getActionScript(), actionScript);
466         final String showDialogScript = "showDialog('" + dialogId + "', " + additionalData + ");";
467         actionScript = ScriptUtils.appendScript(actionScript, showDialogScript);
468 
469         addWithDialogAction.setActionScript(actionScript);
470     }
471 
472     /**
473      * {@inheritDoc}
474      */
475     @Override
476     public void performFinalize(Object model, LifecycleElement parent) {
477         super.performFinalize(model, parent);
478 
479         addCollectionPostMetadata();
480 
481         // set fields to send if adding with dialog
482         if (addWithDialog && addLineDialog != null && addLineDialog.getFooter() != null) {
483             List<String> fieldsToSend = new ArrayList<String>();
484             fieldsToSend.add("#" + addLineDialog.getId());
485 
486             for (Component cmpnt : addLineDialog.getFooter().getItems()) {
487                 if (cmpnt instanceof  Action) {
488                     ((Action)cmpnt).setFieldsToSend(fieldsToSend);
489                 }
490             }
491         }
492     }
493 
494     /**
495      * Add the metadata about this collection to the ViewPostMetadata
496      * that is to be kept in memory between posts for use by other methods
497      */
498     protected void addCollectionPostMetadata() {
499         if (this.getCollectionLookup() != null) {
500             ViewLifecycle.getViewPostMetadata().addComponentPostData(this,
501                     UifConstants.PostMetadata.COLL_LOOKUP_FIELD_CONVERSIONS,
502                     this.getCollectionLookup().getFieldConversions());
503         }
504 
505         ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.COLL_OBJECT_CLASS,
506                 this.getCollectionObjectClass());
507 
508         ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.BINDING_INFO,
509                 this.getBindingInfo());
510 
511         ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.ADD_LINE_BINDING_INFO,
512                 this.getAddLineBindingInfo());
513 
514         ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.ADD_LINE_PLACEMENT,
515                 this.getAddLinePlacement());
516 
517         if (this.getHeader() != null) {
518             ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.COLL_LABEL,
519                     this.getCollectionLabel());
520         }
521 
522         if (this.getDuplicateLinePropertyNames() != null) {
523             ViewLifecycle.getViewPostMetadata().addComponentPostData(this,
524                     UifConstants.PostMetadata.DUPLICATE_LINE_PROPERTY_NAMES, this.getDuplicateLinePropertyNames());
525             ViewLifecycle.getViewPostMetadata().addComponentPostData(this,
526                     UifConstants.PostMetadata.DUPLICATE_LINE_LABEL_STRING, this.getDuplicateLineLabelString(
527                             this.getDuplicateLinePropertyNames())
528             );
529         }
530 
531         boolean hasBindingPath = getBindingInfo() != null && getBindingInfo().getBindingPath() != null;
532         if (hasBindingPath) {
533             ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.BINDING_PATH,
534                     getBindingInfo().getBindingPath());
535         }
536 
537         ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.COLL_DISPLAY_START,
538                 getDisplayStart());
539         ViewLifecycle.getViewPostMetadata().addComponentPostData(this, UifConstants.PostMetadata.COLL_DISPLAY_LENGTH,
540                 getDisplayLength());
541     }
542 
543     /**
544      * {@inheritDoc}
545      */
546     @Override
547     public void pushCollectionGroupToReference() {
548         Collection<LifecycleElement> components = ViewLifecycleUtils.getElementsForLifecycle(this).values();
549         ContextUtils.pushObjectToContextDeep(components, UifConstants.ContextVariableNames.COLLECTION_GROUP, this);
550 
551         List<Action> actions = ViewLifecycleUtils.getElementsOfTypeDeep(components, Action.class);
552         for (Action action : actions) {
553             action.addActionParameter(UifParameters.SELECTED_COLLECTION_PATH, this.getBindingInfo().getBindingPath());
554             action.addActionParameter(UifParameters.SELECTED_COLLECTION_ID, this.getId());
555         }
556     }
557 
558     /**
559      * Gets the label for the collection in a human-friendly format.
560      *
561      * @return a human-friendly collection label
562      */
563     protected String getCollectionLabel() {
564         String collectionLabel = this.getHeaderText();
565 
566         if (StringUtils.isBlank(collectionLabel)) {
567             String propertyName = this.getPropertyName();
568             collectionLabel = KRADServiceLocatorWeb.getUifDefaultingService().deriveHumanFriendlyNameFromPropertyName(
569                     propertyName);
570         }
571 
572         return collectionLabel;
573     }
574 
575     /**
576      * Gets a comma-separated list of the data field labels that are keyed a duplicates.
577      *
578      * @param duplicateLinePropertyNames the property names to check for duplicates
579      * @return a comma-separated list of labels
580      */
581     protected String getDuplicateLineLabelString(List<String> duplicateLinePropertyNames) {
582         List<String> duplicateLineLabels = new ArrayList<String>();
583 
584         List<DataField> fields = new ArrayList<DataField>();
585 
586         for (Component addLineItem : getAddLineItems()) {
587             if (addLineItem instanceof DataField) {
588                 fields.add((DataField) addLineItem);
589             } else if (addLineItem instanceof FieldGroup) {
590                 Group group = ((FieldGroup) addLineItem).getGroup();
591                 List<DataField> nestedAddLineItems = ViewLifecycleUtils.getElementsOfTypeDeep(group, DataField.class);
592                 fields.addAll(nestedAddLineItems);
593             }
594         }
595 
596         for (DataField field : fields) {
597             if (duplicateLinePropertyNames.contains(field.getPropertyName())) {
598                 String label = field.getLabel();
599                 String shortLabel = field.getShortLabel();
600                 duplicateLineLabels.add(StringUtils.isNotBlank(label) ? label : shortLabel);
601             }
602         }
603 
604         return StringUtils.join(duplicateLineLabels, ", ");
605     }
606 
607     /**
608      * New collection lines are handled in the framework by maintaining a map on
609      * the form. The map contains as a key the collection name, and as value an
610      * instance of the collection type. An entry is created here for the
611      * collection represented by the <code>CollectionGroup</code> if an instance
612      * is not available (clearExistingLine will force a new instance). The given
613      * model must be a subclass of <code>UifFormBase</code> in order to find the
614      * Map.
615      *
616      * @param model Model instance that contains the new collection lines Map
617      * @param clearExistingLine boolean that indicates whether the line should be set to a
618      * new instance if it already exists
619      */
620     @Override
621     public void initializeNewCollectionLine(View view, Object model, CollectionGroup collectionGroup,
622             boolean clearExistingLine) {
623         getCollectionGroupBuilder().initializeNewCollectionLine(view, model, collectionGroup, clearExistingLine);
624     }
625 
626     /**
627      * Do not process remote field holders for collections. Collection items will be processed as
628      * the lines are built.
629      *
630      * {@inheritDoc}
631      */
632     @Override
633     public boolean isProcessRemoteFieldHolders() {
634         return false;
635     }
636 
637     /**
638      * {@inheritDoc}
639      */
640     @Override
641     @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
642     @BeanTagAttribute
643     public List<? extends Component> getItems() {
644         return super.getItems();
645     }
646 
647     /**
648      * {@inheritDoc}
649      */
650     @Override
651     @BeanTagAttribute
652     public Class<?> getCollectionObjectClass() {
653         return this.collectionObjectClass;
654     }
655 
656     /**
657      * {@inheritDoc}
658      */
659     @Override
660     public void setCollectionObjectClass(Class<?> collectionObjectClass) {
661         this.collectionObjectClass = collectionObjectClass;
662     }
663 
664     /**
665      * {@inheritDoc}
666      */
667     @Override
668     @BeanTagAttribute
669     public String getPropertyName() {
670         return this.propertyName;
671     }
672 
673     /**
674      * {@inheritDoc}
675      */
676     @Override
677     public void setPropertyName(String propertyName) {
678         this.propertyName = propertyName;
679     }
680 
681     /**
682      * {@inheritDoc}
683      */
684     @Override
685     @BeanTagAttribute
686     public BindingInfo getBindingInfo() {
687         return this.bindingInfo;
688     }
689 
690     /**
691      * {@inheritDoc}
692      */
693     @Override
694     public void setBindingInfo(BindingInfo bindingInfo) {
695         this.bindingInfo = bindingInfo;
696     }
697 
698     /**
699      * {@inheritDoc}
700      */
701     @Override
702     @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
703     @BeanTagAttribute
704     public List<? extends Component> getLineActions() {
705         return this.lineActions;
706     }
707 
708     /**
709      * {@inheritDoc}
710      */
711     @Override
712     public void setLineActions(List<? extends Component> lineActions) {
713         this.lineActions = lineActions;
714     }
715 
716     /**
717      * {@inheritDoc}
718      */
719     @Override
720     @BeanTagAttribute
721     public String getAddLineEnterKeyAction() {
722         return this.addLineEnterKeyAction;
723     }
724 
725     /**
726      * {@inheritDoc}
727      */
728     @Override
729     public void setAddLineEnterKeyAction(String addLineEnterKeyAction) {
730         this.addLineEnterKeyAction = addLineEnterKeyAction;
731     }
732 
733     /**
734      * {@inheritDoc}
735      */
736     @Override
737     @BeanTagAttribute
738     public String getLineEnterKeyAction() {
739         return this.lineEnterKeyAction;
740     }
741 
742     /**
743      * {@inheritDoc}
744      */
745     @Override
746     public void setLineEnterKeyAction(String lineEnterKeyAction) {
747         this.lineEnterKeyAction = lineEnterKeyAction;
748     }
749 
750     /**
751      * {@inheritDoc}
752      */
753     @Override
754     @BeanTagAttribute
755     public boolean isRenderLineActions() {
756         return this.renderLineActions;
757     }
758 
759     /**
760      * {@inheritDoc}
761      */
762     @Override
763     public void setRenderLineActions(boolean renderLineActions) {
764         this.renderLineActions = renderLineActions;
765     }
766 
767     /**
768      * {@inheritDoc}
769      */
770     @Override
771     @BeanTagAttribute
772     public boolean isRenderAddLine() {
773         if (this.useServerPaging && this.renderAddLine) {
774             return this.displayStart == 0 ? true : false;
775         }
776         return this.renderAddLine;
777     }
778 
779     /**
780      * {@inheritDoc}
781      */
782     @Override
783     public void setRenderAddLine(boolean renderAddLine) {
784         this.renderAddLine = renderAddLine;
785     }
786 
787     /**
788      * {@inheritDoc}
789      */
790     @Override
791     @BeanTagAttribute
792     public String getAddLabel() {
793         if (getAddLineLabel() != null) {
794             return getAddLineLabel().getMessageText();
795         }
796 
797         return null;
798     }
799 
800     /**
801      * {@inheritDoc}
802      */
803     @Override
804     public void setAddLabel(String addLabelText) {
805         if (getAddLineLabel() != null) {
806             getAddLineLabel().setMessageText(addLabelText);
807         }
808     }
809 
810     /**
811      * {@inheritDoc}
812      */
813     @Override
814     @BeanTagAttribute
815     public Message getAddLineLabel() {
816         return this.addLineLabel;
817     }
818 
819     /**
820      * {@inheritDoc}
821      */
822     @Override
823     public void setAddLineLabel(Message addLineLabel) {
824         this.addLineLabel = addLineLabel;
825     }
826 
827     /**
828      * {@inheritDoc}
829      */
830     @Override
831     @BeanTagAttribute
832     public String getAddLinePropertyName() {
833         return this.addLinePropertyName;
834     }
835 
836     /**
837      * {@inheritDoc}
838      */
839     @Override
840     public void setAddLinePropertyName(String addLinePropertyName) {
841         this.addLinePropertyName = addLinePropertyName;
842     }
843 
844     /**
845      * {@inheritDoc}
846      */
847     @Override
848     @BeanTagAttribute
849     public BindingInfo getAddLineBindingInfo() {
850         return this.addLineBindingInfo;
851     }
852 
853     /**
854      * {@inheritDoc}
855      */
856     @Override
857     public void setAddLineBindingInfo(BindingInfo addLineBindingInfo) {
858         this.addLineBindingInfo = addLineBindingInfo;
859     }
860 
861     /**
862      * {@inheritDoc}
863      */
864     @Override
865     @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
866     @BeanTagAttribute
867     public List<? extends Component> getAddLineItems() {
868         return this.addLineItems;
869     }
870 
871     /**
872      * {@inheritDoc}
873      */
874     @Override
875     public void setAddLineItems(List<? extends Component> addLineItems) {
876         this.addLineItems = addLineItems;
877     }
878 
879     /**
880      * {@inheritDoc}
881      */
882     @Override
883     @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
884     @BeanTagAttribute
885     public List<? extends Component> getAddLineActions() {
886         return this.addLineActions;
887     }
888 
889     /**
890      * {@inheritDoc}
891      */
892     @Override
893     public void setAddLineActions(List<? extends Component> addLineActions) {
894         this.addLineActions = addLineActions;
895     }
896 
897     /**
898      * {@inheritDoc}
899      */
900     @Override
901     @BeanTagAttribute
902     public boolean isIncludeLineSelectionField() {
903         return includeLineSelectionField;
904     }
905 
906     /**
907      * {@inheritDoc}
908      */
909     @Override
910     public void setIncludeLineSelectionField(boolean includeLineSelectionField) {
911         this.includeLineSelectionField = includeLineSelectionField;
912     }
913 
914     /**
915      * {@inheritDoc}
916      */
917     @Override
918     @BeanTagAttribute
919     public String getLineSelectPropertyName() {
920         return lineSelectPropertyName;
921     }
922 
923     /**
924      * {@inheritDoc}
925      */
926     @Override
927     public void setLineSelectPropertyName(String lineSelectPropertyName) {
928         this.lineSelectPropertyName = lineSelectPropertyName;
929     }
930 
931     /**
932      * {@inheritDoc}
933      */
934     @Override
935     @BeanTagAttribute(type = BeanTagAttribute.AttributeType.BYTYPE)
936     public QuickFinder getCollectionLookup() {
937         return collectionLookup;
938     }
939 
940     /**
941      * {@inheritDoc}
942      */
943     @Override
944     public void setCollectionLookup(QuickFinder collectionLookup) {
945         this.collectionLookup = collectionLookup;
946     }
947 
948     /**
949      * {@inheritDoc}
950      */
951     @Override
952     @BeanTagAttribute
953     public boolean isShowInactiveLines() {
954         return showInactiveLines;
955     }
956 
957     /**
958      * {@inheritDoc}
959      */
960     @Override
961     public void setShowInactiveLines(boolean showInactiveLines) {
962         this.showInactiveLines = showInactiveLines;
963     }
964 
965     /**
966      * {@inheritDoc}
967      */
968     @Override
969     @BeanTagAttribute
970     public CollectionFilter getActiveCollectionFilter() {
971         return activeCollectionFilter;
972     }
973 
974     /**
975      * {@inheritDoc}
976      */
977     @Override
978     public void setActiveCollectionFilter(CollectionFilter activeCollectionFilter) {
979         this.activeCollectionFilter = activeCollectionFilter;
980     }
981 
982     /**
983      * {@inheritDoc}
984      */
985     @Override
986     @BeanTagAttribute
987     public List<CollectionFilter> getFilters() {
988         return filters;
989     }
990 
991     /**
992      * {@inheritDoc}
993      */
994     @Override
995     public void setFilters(List<CollectionFilter> filters) {
996         this.filters = filters;
997     }
998 
999     /**
1000      * {@inheritDoc}
1001      */
1002     @Override
1003     @BeanTagAttribute
1004     public List<String> getDuplicateLinePropertyNames() {
1005         return this.duplicateLinePropertyNames;
1006     }
1007 
1008     /**
1009      * {@inheritDoc}
1010      */
1011     public void setDuplicateLinePropertyNames(List<String> duplicateLinePropertyNames) {
1012         this.duplicateLinePropertyNames = duplicateLinePropertyNames;
1013     }
1014 
1015     /**
1016      * {@inheritDoc}
1017      */
1018     @Override
1019     public List<BindingInfo> getUnauthorizedLineBindingInfos() {
1020         return this.unauthorizedLineBindingInfos;
1021     }
1022 
1023     /**
1024      * {@inheritDoc}
1025      */
1026     @Override
1027     public void setUnauthorizedLineBindingInfos(List<BindingInfo> unauthorizedLineBindingInfos) {
1028         this.unauthorizedLineBindingInfos = unauthorizedLineBindingInfos;
1029     }
1030 
1031     /**
1032      * List of <code>CollectionGroup</code> instances that are sub-collections
1033      * of the collection represented by this collection group
1034      *
1035      * @return sub collections
1036      */
1037     @Override
1038     @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
1039     @BeanTagAttribute
1040     public List<CollectionGroup> getSubCollections() {
1041         return this.subCollections;
1042     }
1043 
1044     /**
1045      * Setter for the sub collection list
1046      */
1047     @Override
1048     public void setSubCollections(List<CollectionGroup> subCollections) {
1049         this.subCollections = subCollections;
1050     }
1051 
1052     /**
1053      * {@inheritDoc}
1054      */
1055     @Override
1056     public CollectionGroupSecurity getCollectionGroupSecurity() {
1057         return (CollectionGroupSecurity) super.getComponentSecurity();
1058     }
1059 
1060     /**
1061      * {@inheritDoc}
1062      */
1063     @Override
1064     public void setComponentSecurity(ComponentSecurity componentSecurity) {
1065         if ((componentSecurity != null) && !(componentSecurity instanceof CollectionGroupSecurity)) {
1066             throw new RiceRuntimeException(
1067                     "Component security for CollectionGroup should be instance of CollectionGroupSecurity");
1068         }
1069 
1070         super.setComponentSecurity(componentSecurity);
1071     }
1072 
1073     /**
1074      * {@inheritDoc}
1075      */
1076     @Override
1077     protected void initializeComponentSecurity() {
1078         if (getComponentSecurity() == null) {
1079             setComponentSecurity(KRADUtils.createNewObjectFromClass(CollectionGroupSecurity.class));
1080         }
1081     }
1082 
1083     /**
1084      * {@inheritDoc}
1085      */
1086     @Override
1087     @BeanTagAttribute
1088     public boolean isEditLineAuthz() {
1089         initializeComponentSecurity();
1090 
1091         return getCollectionGroupSecurity().isEditLineAuthz();
1092     }
1093 
1094     /**
1095      * {@inheritDoc}
1096      */
1097     @Override
1098     public void setEditLineAuthz(boolean editLineAuthz) {
1099         initializeComponentSecurity();
1100 
1101         getCollectionGroupSecurity().setEditLineAuthz(editLineAuthz);
1102     }
1103 
1104     /**
1105      * {@inheritDoc}
1106      */
1107     @Override
1108     @BeanTagAttribute
1109     public boolean isViewLineAuthz() {
1110         initializeComponentSecurity();
1111 
1112         return getCollectionGroupSecurity().isViewLineAuthz();
1113     }
1114 
1115     /**
1116      * {@inheritDoc}
1117      */
1118     @Override
1119     public void setViewLineAuthz(boolean viewLineAuthz) {
1120         initializeComponentSecurity();
1121 
1122         getCollectionGroupSecurity().setViewLineAuthz(viewLineAuthz);
1123     }
1124 
1125     /**
1126      * {@inheritDoc}
1127      */
1128     @Override
1129     @BeanTagAttribute
1130     public CollectionGroupBuilder getCollectionGroupBuilder() {
1131         if (this.collectionGroupBuilder == null) {
1132             this.collectionGroupBuilder = new CollectionGroupBuilder();
1133         }
1134         return this.collectionGroupBuilder;
1135     }
1136 
1137     /**
1138      * {@inheritDoc}
1139      */
1140     @Override
1141     public void setCollectionGroupBuilder(CollectionGroupBuilder collectionGroupBuilder) {
1142         this.collectionGroupBuilder = collectionGroupBuilder;
1143     }
1144 
1145     /**
1146      * {@inheritDoc}
1147      */
1148     @Override
1149     @BeanTagAttribute
1150     public boolean isRenderInactiveToggleButton() {
1151         return renderInactiveToggleButton;
1152     }
1153 
1154     /**
1155      * {@inheritDoc}
1156      */
1157     @Override
1158     public void setRenderInactiveToggleButton(boolean renderInactiveToggleButton) {
1159         this.renderInactiveToggleButton = renderInactiveToggleButton;
1160     }
1161 
1162     /**
1163      * {@inheritDoc}
1164      */
1165     @Override
1166     @BeanTagAttribute
1167     public int getDisplayCollectionSize() {
1168         return this.displayCollectionSize;
1169     }
1170 
1171     /**
1172      * {@inheritDoc}
1173      */
1174     @Override
1175     public void setDisplayCollectionSize(int displayCollectionSize) {
1176         this.displayCollectionSize = displayCollectionSize;
1177     }
1178 
1179     /**
1180      * {@inheritDoc}
1181      */
1182     @Override
1183     @BeanTagAttribute
1184     public boolean isHighlightNewItems() {
1185         return highlightNewItems;
1186     }
1187 
1188     /**
1189      * {@inheritDoc}
1190      */
1191     @Override
1192     public void setHighlightNewItems(boolean highlightNewItems) {
1193         this.highlightNewItems = highlightNewItems;
1194     }
1195 
1196     /**
1197      * {@inheritDoc}
1198      */
1199     @Override
1200     @BeanTagAttribute
1201     public String getNewItemsCssClass() {
1202         return newItemsCssClass;
1203     }
1204 
1205     /**
1206      * {@inheritDoc}
1207      */
1208     @Override
1209     public void setNewItemsCssClass(String newItemsCssClass) {
1210         this.newItemsCssClass = newItemsCssClass;
1211     }
1212 
1213     /**
1214      * {@inheritDoc}
1215      */
1216     @Override
1217     @BeanTagAttribute
1218     public String getAddItemCssClass() {
1219         return addItemCssClass;
1220     }
1221 
1222     /**
1223      * {@inheritDoc}
1224      */
1225     @Override
1226     public void setAddItemCssClass(String addItemCssClass) {
1227         this.addItemCssClass = addItemCssClass;
1228     }
1229 
1230     /**
1231      * {@inheritDoc}
1232      */
1233     @Override
1234     @BeanTagAttribute
1235     public boolean isHighlightAddItem() {
1236         return highlightAddItem;
1237     }
1238 
1239     /**
1240      * {@inheritDoc}
1241      */
1242     @Override
1243     public void setHighlightAddItem(boolean highlightAddItem) {
1244         this.highlightAddItem = highlightAddItem;
1245     }
1246 
1247     /**
1248      * {@inheritDoc}
1249      */
1250     @Override
1251     @BeanTagAttribute
1252     public boolean isRenderAddBlankLineButton() {
1253         return renderAddBlankLineButton;
1254     }
1255 
1256     /**
1257      * {@inheritDoc}
1258      */
1259     @Override
1260     public void setRenderAddBlankLineButton(boolean renderAddBlankLineButton) {
1261         this.renderAddBlankLineButton = renderAddBlankLineButton;
1262     }
1263 
1264     /**
1265      * {@inheritDoc}
1266      */
1267     @Override
1268     @BeanTagAttribute
1269     public Action getAddBlankLineAction() {
1270         return addBlankLineAction;
1271     }
1272 
1273     /**
1274      * {@inheritDoc}
1275      */
1276     @Override
1277     public void setAddBlankLineAction(Action addBlankLineAction) {
1278         this.addBlankLineAction = addBlankLineAction;
1279     }
1280 
1281     /**
1282      * {@inheritDoc}
1283      */
1284     @Override
1285     @BeanTagAttribute
1286     public String getAddLinePlacement() {
1287         return addLinePlacement;
1288     }
1289 
1290     /**
1291      * {@inheritDoc}
1292      */
1293     @Override
1294     public void setAddLinePlacement(String addLinePlacement) {
1295         this.addLinePlacement = addLinePlacement;
1296     }
1297 
1298     /**
1299      * {@inheritDoc}
1300      */
1301     @Override
1302     @BeanTagAttribute
1303     public boolean isRenderSaveLineActions() {
1304         return renderSaveLineActions;
1305     }
1306 
1307     /**
1308      * {@inheritDoc}
1309      */
1310     @Override
1311     public void setRenderSaveLineActions(boolean renderSaveLineActions) {
1312         this.renderSaveLineActions = renderSaveLineActions;
1313     }
1314 
1315     /**
1316      * {@inheritDoc}
1317      */
1318     @Override
1319     @BeanTagAttribute
1320     public boolean isAddWithDialog() {
1321         return addWithDialog;
1322     }
1323 
1324     /**
1325      * {@inheritDoc}
1326      */
1327     @Override
1328     public void setAddWithDialog(boolean addWithDialog) {
1329         this.addWithDialog = addWithDialog;
1330     }
1331 
1332     /**
1333      * {@inheritDoc}
1334      */
1335     @Override
1336     @BeanTagAttribute
1337     public Action getAddWithDialogAction() {
1338         return addWithDialogAction;
1339     }
1340 
1341     /**
1342      * {@inheritDoc}
1343      */
1344     @Override
1345     public void setAddWithDialogAction(Action addWithDialogAction) {
1346         this.addWithDialogAction = addWithDialogAction;
1347     }
1348 
1349     /**
1350      * {@inheritDoc}
1351      */
1352     @Override
1353     @BeanTagAttribute
1354     public DialogGroup getAddLineDialog() {
1355         return addLineDialog;
1356     }
1357 
1358     /**
1359      * {@inheritDoc}
1360      */
1361     @Override
1362     public void setAddLineDialog(DialogGroup addLineDialog) {
1363         this.addLineDialog = addLineDialog;
1364     }
1365 
1366     /**
1367      * {@inheritDoc}
1368      */
1369     @Override
1370     @BeanTagAttribute
1371     public boolean isUseServerPaging() {
1372         return useServerPaging;
1373     }
1374 
1375     /**
1376      * {@inheritDoc}
1377      */
1378     @Override
1379     public void setUseServerPaging(boolean useServerPaging) {
1380         this.useServerPaging = useServerPaging;
1381     }
1382 
1383     /**
1384      * {@inheritDoc}
1385      */
1386     @Override
1387     public int getPageSize() {
1388         return pageSize;
1389     }
1390 
1391     /**
1392      * {@inheritDoc}
1393      */
1394     @Override
1395     public void setPageSize(int pageSize) {
1396         this.pageSize = pageSize;
1397     }
1398 
1399     /**
1400      * {@inheritDoc}
1401      */
1402     @Override
1403     public int getDisplayStart() {
1404         return displayStart;
1405     }
1406 
1407     /**
1408      * {@inheritDoc}
1409      */
1410     @Override
1411     public void setDisplayStart(int displayStart) {
1412         this.displayStart = displayStart;
1413     }
1414 
1415     /**
1416      * {@inheritDoc}
1417      */
1418     @Override
1419     public int getDisplayLength() {
1420         return displayLength;
1421     }
1422 
1423     /**
1424      * {@inheritDoc}
1425      */
1426     @Override
1427     public void setDisplayLength(int displayLength) {
1428         this.displayLength = displayLength;
1429     }
1430 
1431     /**
1432      * {@inheritDoc}
1433      */
1434     @Override
1435     public int getFilteredCollectionSize() {
1436         return filteredCollectionSize;
1437     }
1438 
1439     /**
1440      * {@inheritDoc}
1441      */
1442     @Override
1443     public void setFilteredCollectionSize(int filteredCollectionSize) {
1444         this.filteredCollectionSize = filteredCollectionSize;
1445     }
1446 
1447     public int getTotalCollectionSize() {
1448         return totalCollectionSize;
1449     }
1450 
1451     public void setTotalCollectionSize(int totalCollectionSize) {
1452         this.totalCollectionSize = totalCollectionSize;
1453     }
1454 
1455     /**
1456      * @return list of total columns
1457      */
1458     @BeanTagAttribute
1459     protected List<String> getTotalColumns() {
1460         return totalColumns;
1461     }
1462 
1463     /**
1464      * Setter for the total columns
1465      */
1466     protected void setTotalColumns(List<String> totalColumns) {
1467         this.totalColumns = totalColumns;
1468     }
1469 
1470     /**
1471      * {@inheritDoc}
1472      */
1473     @Override
1474     public void completeValidation(ValidationTrace tracer) {
1475         tracer.addBean(this);
1476 
1477         // Checking if collectionObjectClass is set
1478         if (getCollectionObjectClass() == null) {
1479             if (Validator.checkExpressions(this, UifConstants.PostMetadata.COLL_OBJECT_CLASS)) {
1480                 String currentValues[] = {"collectionObjectClass = " + getCollectionObjectClass()};
1481                 tracer.createWarning("CollectionObjectClass is not set (disregard if part of an abstract)",
1482                         currentValues);
1483             }
1484         }
1485 
1486         super.completeValidation(tracer.getCopy());
1487     }
1488 
1489     /**
1490      * {@inheritDoc}
1491      */
1492     @Override
1493     @BeanTagAttribute
1494     public boolean isEditWithDialog() {
1495         return editWithDialog;
1496     }
1497 
1498     /**
1499      * {@inheritDoc}
1500      */
1501     @Override
1502     public void setEditWithDialog(boolean editWithDialog) {
1503         this.editWithDialog = editWithDialog;
1504     }
1505 
1506     /**
1507      * {@inheritDoc}
1508      */
1509     @Override
1510     @BeanTagAttribute
1511     public boolean isCustomEditLineDialog() {
1512         return customEditLineDialog;
1513     }
1514 
1515     /**
1516      * {@inheritDoc}
1517      */
1518     @Override
1519     public void setCustomEditLineDialog(boolean customEditLineDialog) {
1520         this.customEditLineDialog = customEditLineDialog;
1521     }
1522 
1523     /**
1524      * {@inheritDoc}
1525      */
1526     @Override
1527     @BeanTagAttribute
1528     public DialogGroup getEditLineDialogPrototype() {
1529         return editLineDialogPrototype;
1530     }
1531 
1532     /**
1533      * {@inheritDoc}
1534      */
1535     @Override
1536     public void setEditLineDialogPrototype(DialogGroup editLineDialogPrototype) {
1537         this.editLineDialogPrototype = editLineDialogPrototype;
1538     }
1539 
1540     /**
1541      * {@inheritDoc}
1542      */
1543     @Override
1544     @BeanTagAttribute
1545     public Action getEditWithDialogActionPrototype() {
1546         return editWithDialogActionPrototype;
1547     }
1548 
1549     /**
1550      * {@inheritDoc}
1551      */
1552     @Override
1553     public void setEditWithDialogActionPrototype(Action editWithDialogActionPrototype) {
1554         this.editWithDialogActionPrototype = editWithDialogActionPrototype;
1555     }
1556 
1557     /**
1558      * {@inheritDoc}
1559      */
1560     @Override
1561     @BeanTagAttribute
1562     public Action getEditInDialogSaveActionPrototype() {
1563         return editInDialogSaveActionPrototype;
1564     }
1565 
1566     /**
1567      * {@inheritDoc}
1568      */
1569     @Override
1570     public void setEditInDialogSaveActionPrototype(Action editInDialogSaveActionPrototype) {
1571         this.editInDialogSaveActionPrototype = editInDialogSaveActionPrototype;
1572     }
1573 
1574     /**
1575      * {@inheritDoc}
1576      */
1577     public List<DialogGroup> getLineDialogs() {
1578         return lineDialogs;
1579     }
1580 
1581     /**
1582      * {@inheritDoc}
1583      */
1584     public void setLineDialogs(List<DialogGroup> dialogGroups) {
1585         this.lineDialogs = dialogGroups;
1586     }
1587 }