Coverage Report - org.kuali.rice.krad.uif.layout.TableLayoutManager
 
Classes in this File Line Coverage Branch Coverage Complexity
TableLayoutManager
0%
0/199
0%
0/106
2.375
 
 1  
 /**
 2  
  * Copyright 2005-2011 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.layout;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.kuali.rice.krad.uif.UifConstants;
 20  
 import org.kuali.rice.krad.uif.component.DataBinding;
 21  
 import org.kuali.rice.krad.uif.container.CollectionGroup;
 22  
 import org.kuali.rice.krad.uif.container.Container;
 23  
 import org.kuali.rice.krad.uif.container.Group;
 24  
 import org.kuali.rice.krad.uif.field.DataField;
 25  
 import org.kuali.rice.krad.uif.field.FieldGroup;
 26  
 import org.kuali.rice.krad.uif.field.InputField;
 27  
 import org.kuali.rice.krad.uif.view.View;
 28  
 import org.kuali.rice.krad.uif.component.Component;
 29  
 import org.kuali.rice.krad.uif.field.ActionField;
 30  
 import org.kuali.rice.krad.uif.field.Field;
 31  
 import org.kuali.rice.krad.uif.field.LabelField;
 32  
 import org.kuali.rice.krad.uif.field.MessageField;
 33  
 import org.kuali.rice.krad.uif.util.ComponentFactory;
 34  
 import org.kuali.rice.krad.uif.util.ComponentUtils;
 35  
 import org.kuali.rice.krad.uif.widget.RichTable;
 36  
 import org.kuali.rice.krad.web.form.UifFormBase;
 37  
 
 38  
 import java.util.ArrayList;
 39  
 import java.util.List;
 40  
 
 41  
 /**
 42  
  * Layout manager that works with <code>CollectionGroup</code> components and
 43  
  * renders the collection as a Table
 44  
  * 
 45  
  * <p>
 46  
  * Based on the fields defined, the <code>TableLayoutManager</code> will
 47  
  * dynamically create instances of the fields for each collection row. In
 48  
  * addition, the manager can create standard fields like the action and sequence
 49  
  * fields for each row. The manager supports options inherited from the
 50  
  * <code>GridLayoutManager</code> such as rowSpan, colSpan, and cell width
 51  
  * settings.
 52  
  * </p>
 53  
  * 
 54  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 55  
  */
 56  
 public class TableLayoutManager extends GridLayoutManager implements CollectionLayoutManager {
 57  
         private static final long serialVersionUID = 3622267585541524208L;
 58  
 
 59  
         private boolean useShortLabels;
 60  
         private boolean repeatHeader;
 61  
         private LabelField headerFieldPrototype;
 62  
 
 63  
         private boolean renderSequenceField;
 64  
         private boolean generateAutoSequence;
 65  
         private Field sequenceFieldPrototype;
 66  
 
 67  
         private FieldGroup actionFieldPrototype;
 68  
         private FieldGroup subCollectionFieldGroupPrototype;
 69  
     private Field selectFieldPrototype;
 70  
 
 71  
     private boolean separateAddLine;
 72  
     private Group addLineGroup;
 73  
 
 74  
         // internal counter for the data columns (not including sequence, action)
 75  
         private int numberOfDataColumns;
 76  
 
 77  
         private List<LabelField> headerFields;
 78  
         private List<Field> dataFields;
 79  
 
 80  
         private RichTable richTable;
 81  0
         private boolean headerAdded = false;
 82  
 
 83  0
         public TableLayoutManager() {
 84  0
                 useShortLabels = true;
 85  0
                 repeatHeader = false;
 86  0
                 renderSequenceField = true;
 87  0
                 generateAutoSequence = false;
 88  0
         separateAddLine = false;
 89  
 
 90  0
                 headerFields = new ArrayList<LabelField>();
 91  0
                 dataFields = new ArrayList<Field>();
 92  0
         }
 93  
         
 94  
         /**
 95  
          * The following actions are performed:
 96  
          * 
 97  
          * <ul>
 98  
          * <li>Sets sequence field prototype if auto sequence is true</li>
 99  
          * <li>Initializes the prototypes</li>
 100  
          * </ul>
 101  
          * 
 102  
          * @see org.kuali.rice.krad.uif.layout.BoxLayoutManager#performInitialization(org.kuali.rice.krad.uif.view.View,
 103  
          *      java.lang.Object, org.kuali.rice.krad.uif.container.Container)
 104  
          */
 105  
         @Override
 106  
         public void performInitialization(View view, Object model, Container container) {
 107  0
                 super.performInitialization(view, model, container);
 108  
                 
 109  0
         if (generateAutoSequence && !(sequenceFieldPrototype instanceof MessageField)) {
 110  0
             sequenceFieldPrototype = ComponentFactory.getMessageField();
 111  0
             view.assignComponentIds(sequenceFieldPrototype);
 112  
         }
 113  
 
 114  0
                 view.getViewHelperService().performComponentInitialization(view, model, headerFieldPrototype);
 115  0
                 view.getViewHelperService().performComponentInitialization(view, model, sequenceFieldPrototype);
 116  0
                 view.getViewHelperService().performComponentInitialization(view, model, actionFieldPrototype);
 117  0
                 view.getViewHelperService().performComponentInitialization(view, model, subCollectionFieldGroupPrototype);
 118  0
         view.getViewHelperService().performComponentInitialization(view, model, selectFieldPrototype);
 119  0
         }
 120  
 
 121  
         /**
 122  
          * Sets up the final column count for rendering based on whether the
 123  
          * sequence and action fields have been generated
 124  
          * 
 125  
          * @see org.kuali.rice.krad.uif.layout.LayoutManagerBase#performFinalize(org.kuali.rice.krad.uif.view.View,
 126  
          *      java.lang.Object, org.kuali.rice.krad.uif.container.Container)
 127  
          */
 128  
         @Override
 129  
         public void performFinalize(View view, Object model, Container container) {
 130  0
                 super.performFinalize(view, model, container);
 131  
 
 132  0
         UifFormBase formBase = (UifFormBase) model;
 133  
 
 134  0
                 CollectionGroup collectionGroup = (CollectionGroup) container;
 135  
 
 136  0
                 int totalColumns = getNumberOfDataColumns();
 137  0
                 if (renderSequenceField) {
 138  0
                         totalColumns++;
 139  
                 }
 140  
 
 141  0
         if (collectionGroup.isRenderSelectField()) {
 142  0
             totalColumns++;
 143  
         }
 144  
 
 145  0
                 if (collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly()) {
 146  0
                         totalColumns++;
 147  
                 }
 148  
 
 149  0
         if (collectionGroup.isRenderAddLine()){
 150  0
             if(StringUtils.isBlank(this.getFirstLineStyle()) && !isSeparateAddLine()){
 151  0
                 this.setFirstLineStyle("kr-addLine");
 152  
             }
 153  
         }
 154  
 
 155  
         // if add line event, add highlighting for added row
 156  0
         if (UifConstants.ActionEvents.ADD_LINE.equals(formBase.getActionEvent())) {
 157  0
             String highlightScript =
 158  
                     "jq(\"#" + container.getId() + "_div > tr:first\").effect(\"highlight\",{}, 6000);";
 159  0
             String onReadyScript = collectionGroup.getOnDocumentReadyScript();
 160  0
             if (StringUtils.isNotBlank(onReadyScript)) {
 161  0
                 highlightScript = onReadyScript + highlightScript;
 162  
             }
 163  0
             collectionGroup.setOnDocumentReadyScript(highlightScript);
 164  
         }
 165  0
                 setNumberOfColumns(totalColumns);
 166  0
         }
 167  
 
 168  
         /**
 169  
          * Assembles the field instances for the collection line. The given sequence
 170  
          * field prototype is copied for the line sequence field. Likewise a copy of
 171  
          * the actionFieldPrototype is made and the given actions are set as the
 172  
          * items for the action field. Finally the generated items are assembled
 173  
          * together into the dataFields list with the given lineFields.
 174  
          * 
 175  
          * @see org.kuali.rice.krad.uif.layout.CollectionLayoutManager#buildLine(org.kuali.rice.krad.uif.view.View,
 176  
          *      java.lang.Object, org.kuali.rice.krad.uif.container.CollectionGroup,
 177  
          *      java.util.List, java.util.List, java.lang.String, java.util.List,
 178  
          *      java.lang.String, java.lang.Object, int)
 179  
          */
 180  
         public void buildLine(View view, Object model, CollectionGroup collectionGroup, List<Field> lineFields,
 181  
                         List<FieldGroup> subCollectionFields, String bindingPath, List<ActionField> actions, String idSuffix,
 182  
                         Object currentLine, int lineIndex) {
 183  0
                 boolean isAddLine = lineIndex == -1;
 184  
 
 185  
         // if separate add line prepare the add line group
 186  0
         if (isAddLine && separateAddLine) {
 187  0
             if (StringUtils.isBlank(addLineGroup.getTitle()) && StringUtils.isBlank(
 188  
                     addLineGroup.getHeader().getHeaderText())) {
 189  0
                addLineGroup.getHeader().setHeaderText(collectionGroup.getAddLineLabel());
 190  
             }
 191  
 
 192  0
             addLineGroup.setItems(lineFields);
 193  
 
 194  0
             List<Component> footerItems = new ArrayList<Component>(actions);
 195  0
             footerItems.addAll(addLineGroup.getFooter().getItems());
 196  0
             addLineGroup.getFooter().setItems(footerItems);
 197  
 
 198  0
             return;
 199  
         }
 200  
                 
 201  
         // if add line or first line set number of data columns
 202  0
         if (isAddLine || ((!collectionGroup.isRenderAddLine() || collectionGroup.isReadOnly() || isSeparateAddLine())
 203  
                 && (lineIndex == 0))) {
 204  0
             if (isSuppressLineWrapping()) {
 205  0
                 setNumberOfDataColumns(lineFields.size());
 206  
             } else {
 207  0
                 setNumberOfDataColumns(getNumberOfColumns());
 208  
             }
 209  
         }
 210  
 
 211  
                 // TODO: implement repeat header
 212  0
                 if (!headerAdded) {
 213  0
                         headerFields = new ArrayList<LabelField>();
 214  0
                         dataFields = new ArrayList<Field>();
 215  
 
 216  0
                         buildTableHeaderRows(collectionGroup, lineFields);
 217  0
                         ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.LINE, currentLine);
 218  0
                         ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.INDEX, new Integer(
 219  
                                         lineIndex));
 220  0
                         headerAdded = true;
 221  
                 }
 222  
 
 223  
                 // set label field rendered to true on line fields
 224  0
                 for (Field field : lineFields) {
 225  0
                         field.setLabelFieldRendered(true);
 226  
 
 227  
                         // don't display summary message
 228  
                         // TODO: remove once we have modifier
 229  0
                         ComponentUtils.setComponentPropertyDeep(field, "summaryMessageField.render", new Boolean(false));
 230  
                 }
 231  
 
 232  0
                 int rowCount = calculateNumberOfRows(collectionGroup.getItems());
 233  0
                 int rowSpan = rowCount + subCollectionFields.size();
 234  
 
 235  
                 // sequence field is always first and should span all rows for the line
 236  0
                 if (renderSequenceField) {
 237  0
                         Field sequenceField = null;
 238  0
             if (!isAddLine) {
 239  0
                 sequenceField = ComponentUtils.copy(sequenceFieldPrototype, idSuffix);
 240  
 
 241  0
                 if (generateAutoSequence && (sequenceField instanceof MessageField)) {
 242  0
                     ((MessageField) sequenceField).setMessageText(Integer.toString(lineIndex + 1));
 243  
                 }
 244  
             }
 245  
                         else {
 246  0
                                 sequenceField = ComponentUtils.copy(collectionGroup.getAddLineLabelField(), idSuffix);
 247  
                         }
 248  0
                         sequenceField.setRowSpan(rowSpan);
 249  
 
 250  0
                         if (sequenceField instanceof DataBinding) {
 251  0
                                 ((DataBinding) sequenceField).getBindingInfo().setBindByNamePrefix(bindingPath);
 252  
                         }
 253  
 
 254  0
                         ComponentUtils.updateContextForLine(sequenceField, currentLine, lineIndex);
 255  0
                         dataFields.add(sequenceField);
 256  
                 }
 257  
 
 258  
         // select field will come after sequence field (if enabled) or be first column
 259  0
         if (collectionGroup.isRenderSelectField()) {
 260  0
             Field selectField = ComponentUtils.copy(selectFieldPrototype, idSuffix);
 261  0
             CollectionLayoutUtils.prepareSelectFieldForLine(selectField, collectionGroup, bindingPath, currentLine);
 262  
 
 263  0
             ComponentUtils.updateContextForLine(selectField, currentLine, lineIndex);
 264  0
             dataFields.add(selectField);
 265  
         }
 266  
 
 267  
                 // now add the fields in the correct position
 268  0
                 int cellPosition = 0;
 269  0
                 for (Field lineField : lineFields) {
 270  0
                         dataFields.add(lineField);
 271  
 
 272  0
                         cellPosition += lineField.getColSpan();
 273  
 
 274  
                         // action field should be in last column
 275  0
                         if ((cellPosition == getNumberOfDataColumns()) && collectionGroup.isRenderLineActions()
 276  
                                         && !collectionGroup.isReadOnly()) {
 277  0
                                 FieldGroup lineActionsField = ComponentUtils.copy(actionFieldPrototype, idSuffix);
 278  
 
 279  0
                                 ComponentUtils.updateContextForLine(lineActionsField, currentLine, lineIndex);
 280  0
                                 lineActionsField.setRowSpan(rowSpan);
 281  0
                                 lineActionsField.setItems(actions);
 282  
 
 283  0
                                 dataFields.add(lineActionsField);
 284  0
                         }
 285  
                 }
 286  
 
 287  
                 // update colspan on sub-collection fields
 288  0
                 for (FieldGroup subCollectionField : subCollectionFields) {
 289  0
                         subCollectionField.setColSpan(numberOfDataColumns);
 290  
                 }
 291  
 
 292  
                 // add sub-collection fields to end of data fields
 293  0
                 dataFields.addAll(subCollectionFields);
 294  0
         }
 295  
 
 296  
         /**
 297  
          * Create the <code>LabelField</code> instances that will be used to render
 298  
          * the table header
 299  
          * 
 300  
          * <p>
 301  
          * For each column, a copy of headerFieldPrototype is made that determines
 302  
          * the label configuration. The actual label text comes from the field for
 303  
          * which the header applies to. The first column is always the sequence (if
 304  
          * enabled) and the last column contains the actions. Both the sequence and
 305  
          * action header fields will span all rows for the header.
 306  
          * </p>
 307  
          * 
 308  
          * <p>
 309  
          * The headerFields list will contain the final list of header fields built
 310  
          * </p>
 311  
          * 
 312  
          * @param collectionGroup
 313  
          *            - CollectionGroup container the table applies to
 314  
          * @param lineFields - fields for the data columns from which the headers are pulled
 315  
          */
 316  
         protected void buildTableHeaderRows(CollectionGroup collectionGroup, List<Field> lineFields) {
 317  
                 // row count needed to determine the row span for the sequence and
 318  
                 // action fields, since they should span all rows for the line
 319  0
                 int rowCount = calculateNumberOfRows(collectionGroup.getItems());
 320  
 
 321  
                 // first column is sequence label
 322  0
                 if (renderSequenceField) {
 323  0
                         sequenceFieldPrototype.setLabelFieldRendered(true);
 324  0
                         sequenceFieldPrototype.setRowSpan(rowCount);
 325  0
                         addHeaderField(sequenceFieldPrototype, 1);
 326  
                 }
 327  
 
 328  
         // next is select field
 329  0
         if (collectionGroup.isRenderSelectField()) {
 330  0
             selectFieldPrototype.setLabelFieldRendered(true);
 331  0
             selectFieldPrototype.setRowSpan(rowCount);
 332  0
             addHeaderField(selectFieldPrototype, 1);
 333  
         }
 334  
 
 335  
                 // pull out label fields from the container's items
 336  0
                 int cellPosition = 0;
 337  0
                 for (Field field : lineFields) {
 338  0
                     if (!field.isRender() && StringUtils.isEmpty(field.getProgressiveRender())) {
 339  0
                         continue;
 340  
                     }
 341  
                     
 342  0
                         cellPosition += field.getColSpan();
 343  0
                         addHeaderField(field, cellPosition);
 344  
 
 345  
                         // add action header as last column in row
 346  0
                         if ((cellPosition == getNumberOfDataColumns()) && collectionGroup.isRenderLineActions()
 347  
                                         && !collectionGroup.isReadOnly()) {
 348  0
                                 actionFieldPrototype.setLabelFieldRendered(true);
 349  0
                                 actionFieldPrototype.setRowSpan(rowCount);
 350  0
                                 addHeaderField(actionFieldPrototype, cellPosition);
 351  
                         }
 352  
                 }
 353  0
         }
 354  
 
 355  
         /**
 356  
          * Creates a new instance of the header field prototype and then sets the
 357  
          * label to the short (if useShortLabels is set to true) or long label of
 358  
          * the given component. After created the header field is added to the list
 359  
          * making up the table header
 360  
          * 
 361  
          * @param field
 362  
          *            - field instance the header field is being created for
 363  
          * @param column
 364  
          *            - column number for the header, used for setting the id
 365  
          */
 366  
         protected void addHeaderField(Field field, int column) {
 367  0
                 LabelField headerField = ComponentUtils.copy(headerFieldPrototype, "_c" + column);
 368  0
                 if (useShortLabels) {
 369  0
                         headerField.setLabelText(field.getLabel());
 370  
                 }
 371  
                 else {
 372  0
                         headerField.setLabelText(field.getLabel());
 373  
                 }
 374  
 
 375  0
                 headerField.setRowSpan(field.getRowSpan());
 376  0
                 headerField.setColSpan(field.getColSpan());
 377  
 
 378  0
                 if ((field.getRequired() != null) && field.getRequired().booleanValue()) {
 379  0
                         headerField.getRequiredMessageField().setRender(true);
 380  
                 }
 381  
                 else {
 382  0
                         headerField.getRequiredMessageField().setRender(false);
 383  
                 }
 384  
 
 385  0
                 headerFields.add(headerField);
 386  0
         }
 387  
 
 388  
         /**
 389  
          * Calculates how many rows will be needed per collection line to display
 390  
          * the list of fields. Assumption is made that the total number of cells the
 391  
          * fields take up is evenly divisible by the configured number of columns
 392  
          * 
 393  
          * @param items
 394  
          *            - list of items that make up one collection line
 395  
          * @return int number of rows
 396  
          */
 397  
         protected int calculateNumberOfRows(List<? extends Field> items) {
 398  0
                 int rowCount = 0;
 399  
                 
 400  
                 // check flag that indicates only one row should be created
 401  0
                 if (isSuppressLineWrapping()) {
 402  0
                     return 1;
 403  
                 }
 404  
 
 405  0
                 int cellCount = 0;
 406  0
                 for (Field field : items) {
 407  0
                         cellCount += field.getColSpan() + field.getRowSpan() - 1;
 408  
                 }
 409  
 
 410  0
                 if (cellCount != 0) {
 411  0
                         rowCount = cellCount / getNumberOfDataColumns();
 412  
                 }
 413  
 
 414  0
                 return rowCount;
 415  
         }
 416  
 
 417  
         /**
 418  
          * @see org.kuali.rice.krad.uif.layout.ContainerAware#getSupportedContainer()
 419  
          */
 420  
         @Override
 421  
         public Class<? extends Container> getSupportedContainer() {
 422  0
                 return CollectionGroup.class;
 423  
         }
 424  
 
 425  
         /**
 426  
          * @see org.kuali.rice.krad.uif.layout.LayoutManagerBase#getComponentsForLifecycle()
 427  
          */
 428  
         @Override
 429  
         public List<Component> getComponentsForLifecycle() {
 430  0
                 List<Component> components = super.getComponentsForLifecycle();
 431  
 
 432  0
                 components.add(richTable);
 433  0
         components.add(addLineGroup);
 434  0
                 components.addAll(headerFields);
 435  0
                 components.addAll(dataFields);
 436  
 
 437  0
                 return components;
 438  
         }
 439  
 
 440  
     /**
 441  
      * @see org.kuali.rice.krad.uif.layout.LayoutManager#getComponentPrototypes()
 442  
      */
 443  
     @Override
 444  
     public List<Component> getComponentPrototypes() {
 445  0
         List<Component> components = super.getComponentPrototypes();
 446  
 
 447  0
         components.add(headerFieldPrototype);
 448  0
         components.add(sequenceFieldPrototype);
 449  0
         components.add(actionFieldPrototype);
 450  0
         components.add(subCollectionFieldGroupPrototype);
 451  0
         components.add(selectFieldPrototype);
 452  
 
 453  0
         return components;
 454  
     }
 455  
 
 456  
         /**
 457  
          * Indicates whether the short label for the collection field should be used
 458  
          * as the table header or the regular label
 459  
          * 
 460  
          * @return boolean true if short label should be used, false if long label
 461  
          *         should be used
 462  
          */
 463  
         public boolean isUseShortLabels() {
 464  0
                 return this.useShortLabels;
 465  
         }
 466  
 
 467  
         /**
 468  
          * Setter for the use short label indicator
 469  
          * 
 470  
          * @param useShortLabels
 471  
          */
 472  
         public void setUseShortLabels(boolean useShortLabels) {
 473  0
                 this.useShortLabels = useShortLabels;
 474  0
         }
 475  
 
 476  
         /**
 477  
          * Indicates whether the header should be repeated before each collection
 478  
          * row. If false the header is only rendered at the beginning of the table
 479  
          * 
 480  
          * @return boolean true if header should be repeated, false if it should
 481  
          *         only be rendered once
 482  
          */
 483  
         public boolean isRepeatHeader() {
 484  0
                 return this.repeatHeader;
 485  
         }
 486  
 
 487  
         /**
 488  
          * Setter for the repeat header indicator
 489  
          * 
 490  
          * @param repeatHeader
 491  
          */
 492  
         public void setRepeatHeader(boolean repeatHeader) {
 493  0
                 this.repeatHeader = repeatHeader;
 494  0
         }
 495  
 
 496  
         /**
 497  
          * <code>LabelField</code> instance to use as a prototype for creating the
 498  
          * tables header fields. For each header field the prototype will be copied
 499  
          * and adjusted as necessary
 500  
          * 
 501  
          * @return LabelField instance to serve as prototype
 502  
          */
 503  
         public LabelField getHeaderFieldPrototype() {
 504  0
                 return this.headerFieldPrototype;
 505  
         }
 506  
 
 507  
         /**
 508  
          * Setter for the header field prototype
 509  
          * 
 510  
          * @param headerFieldPrototype
 511  
          */
 512  
         public void setHeaderFieldPrototype(LabelField headerFieldPrototype) {
 513  0
                 this.headerFieldPrototype = headerFieldPrototype;
 514  0
         }
 515  
 
 516  
         /**
 517  
          * List of <code>LabelField</code> instances that should be rendered to make
 518  
          * up the tables header
 519  
          * 
 520  
          * @return List of label field instances
 521  
          */
 522  
         public List<LabelField> getHeaderFields() {
 523  0
                 return this.headerFields;
 524  
         }
 525  
 
 526  
         /**
 527  
          * Indicates whether the sequence field should be rendered for the
 528  
          * collection
 529  
          * 
 530  
          * @return boolean true if sequence field should be rendered, false if not
 531  
          */
 532  
         public boolean isRenderSequenceField() {
 533  0
                 return this.renderSequenceField;
 534  
         }
 535  
 
 536  
         /**
 537  
          * Setter for the render sequence field indicator
 538  
          * 
 539  
          * @param renderSequenceField
 540  
          */
 541  
         public void setRenderSequenceField(boolean renderSequenceField) {
 542  0
                 this.renderSequenceField = renderSequenceField;
 543  0
         }
 544  
 
 545  
         /**
 546  
          * Attribute name to use as sequence value. For each collection line the
 547  
          * value of this field on the line will be retrieved and used as the
 548  
          * sequence value
 549  
          * 
 550  
          * @return String sequence property name
 551  
          */
 552  
     public String getSequencePropertyName() {
 553  0
         if ((sequenceFieldPrototype != null) && (sequenceFieldPrototype instanceof DataField)) {
 554  0
             return ((DataField) sequenceFieldPrototype).getPropertyName();
 555  
         }
 556  
 
 557  0
         return null;
 558  
     }
 559  
 
 560  
     /**
 561  
      * Setter for the sequence property name
 562  
      * 
 563  
      * @param sequencePropertyName
 564  
      */
 565  
     public void setSequencePropertyName(String sequencePropertyName) {
 566  0
         if ((sequenceFieldPrototype != null) && (sequenceFieldPrototype instanceof DataField)) {
 567  0
             ((DataField) sequenceFieldPrototype).setPropertyName(sequencePropertyName);
 568  
         }
 569  0
     }
 570  
         
 571  
     /**
 572  
      * Indicates whether the sequence field should be generated with the current
 573  
      * line number
 574  
      * 
 575  
      * <p>
 576  
      * If set to true the sequence field prototype will be changed to a message
 577  
      * field (if not already a message field) and the text will be set to the
 578  
      * current line number
 579  
      * </p>
 580  
      * 
 581  
      * @return boolean true if the sequence field should be generated from the
 582  
      *         line number, false if not
 583  
      */
 584  
     public boolean isGenerateAutoSequence() {
 585  0
         return this.generateAutoSequence;
 586  
     }
 587  
 
 588  
     /**
 589  
      * Setter for the generate auto sequence field
 590  
      * 
 591  
      * @param generateAutoSequence
 592  
      */
 593  
     public void setGenerateAutoSequence(boolean generateAutoSequence) {
 594  0
         this.generateAutoSequence = generateAutoSequence;
 595  0
     }
 596  
 
 597  
     /**
 598  
          * <code>Field</code> instance to serve as a prototype for the
 599  
          * sequence field. For each collection line this instance is copied and
 600  
          * adjusted as necessary
 601  
          * 
 602  
          * @return Attribute field instance
 603  
          */
 604  
         public Field getSequenceFieldPrototype() {
 605  0
                 return this.sequenceFieldPrototype;
 606  
         }
 607  
 
 608  
         /**
 609  
          * Setter for the sequence field prototype
 610  
          * 
 611  
          * @param sequenceFieldPrototype
 612  
          */
 613  
         public void setSequenceFieldPrototype(Field sequenceFieldPrototype) {
 614  0
                 this.sequenceFieldPrototype = sequenceFieldPrototype;
 615  0
         }
 616  
 
 617  
         /**
 618  
          * <code>FieldGroup</code> instance to serve as a prototype for the actions
 619  
          * column. For each collection line this instance is copied and adjusted as
 620  
          * necessary. Note the actual actions for the group come from the collection
 621  
          * groups actions List
 622  
          * (org.kuali.rice.krad.uif.container.CollectionGroup.getActionFields()). The
 623  
          * FieldGroup prototype is useful for setting styling of the actions column
 624  
          * and for the layout of the action fields. Note also the label associated
 625  
          * with the prototype is used for the action column header
 626  
          * 
 627  
          * @return GroupField instance
 628  
          */
 629  
         public FieldGroup getActionFieldPrototype() {
 630  0
                 return this.actionFieldPrototype;
 631  
         }
 632  
 
 633  
         /**
 634  
          * Setter for the action field prototype
 635  
          * 
 636  
          * @param actionFieldPrototype
 637  
          */
 638  
         public void setActionFieldPrototype(FieldGroup actionFieldPrototype) {
 639  0
                 this.actionFieldPrototype = actionFieldPrototype;
 640  0
         }
 641  
 
 642  
         /**
 643  
          * @see org.kuali.rice.krad.uif.layout.CollectionLayoutManager#getSubCollectionFieldGroupPrototype()
 644  
          */
 645  
         public FieldGroup getSubCollectionFieldGroupPrototype() {
 646  0
                 return this.subCollectionFieldGroupPrototype;
 647  
         }
 648  
 
 649  
         /**
 650  
          * Setter for the sub-collection field group prototype
 651  
          * 
 652  
          * @param subCollectionFieldGroupPrototype
 653  
          */
 654  
         public void setSubCollectionFieldGroupPrototype(FieldGroup subCollectionFieldGroupPrototype) {
 655  0
                 this.subCollectionFieldGroupPrototype = subCollectionFieldGroupPrototype;
 656  0
         }
 657  
 
 658  
     /**
 659  
      * Field instance that serves as a prototype for creating the select field on each line when
 660  
      * {@link org.kuali.rice.krad.uif.container.CollectionGroup#isRenderSelectField()} is true
 661  
      *
 662  
      * <p>
 663  
      * This prototype can be used to set the control used for the select field (generally will be a checkbox control)
 664  
      * in addition to styling and other setting. The binding path will be formed with using the
 665  
      * {@link org.kuali.rice.krad.uif.container.CollectionGroup#getSelectPropertyName()} or if not set the framework
 666  
      * will use {@link org.kuali.rice.krad.web.form.UifFormBase#getSelectedCollectionLines()}
 667  
      * </p>
 668  
      *
 669  
      * @return Field select field prototype instance
 670  
      */
 671  
     public Field getSelectFieldPrototype() {
 672  0
         return selectFieldPrototype;
 673  
     }
 674  
 
 675  
     /**
 676  
      * Setter for the prototype instance for select fields
 677  
      *
 678  
      * @param selectFieldPrototype
 679  
      */
 680  
     public void setSelectFieldPrototype(Field selectFieldPrototype) {
 681  0
         this.selectFieldPrototype = selectFieldPrototype;
 682  0
     }
 683  
 
 684  
     /**
 685  
      * Indicates whether the add line should be rendered in a separate group, or as part of the table (first line)
 686  
      *
 687  
      * <p>
 688  
      * When separate add line is enabled, the fields for the add line will be placed in the {@link #getAddLineGroup()}.
 689  
      * This group can be used to configure the add line presentation. In addition to the fields, the header on the
 690  
      * group (unless already set) will be set to
 691  
      * {@link org.kuali.rice.krad.uif.container.CollectionGroup#getAddLineLabel()} and the add line actions will
 692  
      * be placed into the group's footer.
 693  
      * </p>
 694  
      *
 695  
      * @return boolean true if add line should be separated, false if it should be placed into the table
 696  
      */
 697  
     public boolean isSeparateAddLine() {
 698  0
         return separateAddLine;
 699  
     }
 700  
 
 701  
     /**
 702  
      * Setter for the separate add line indicator
 703  
      *
 704  
      * @param separateAddLine
 705  
      */
 706  
     public void setSeparateAddLine(boolean separateAddLine) {
 707  0
         this.separateAddLine = separateAddLine;
 708  0
     }
 709  
 
 710  
     /**
 711  
      * When {@link #isSeparateAddLine()} is true, this group will be used to render the add line
 712  
      *
 713  
      * <p>
 714  
      * This group can be used to configure how the add line will be rendered. For example the layout manager configured
 715  
      * on the group will be used to rendered the add line fields. If the header (title) is not set on the group, it
 716  
      * will be set from
 717  
      * {@link org.kuali.rice.krad.uif.container.CollectionGroup#getAddLineLabel()}. In addition,
 718  
      * {@link org.kuali.rice.krad.uif.container.CollectionGroup#getAddLineActionFields()} will be added to the group
 719  
      * footer items.
 720  
      * </p>
 721  
      *
 722  
      * @return Group instance for the collection add line
 723  
      */
 724  
     public Group getAddLineGroup() {
 725  0
         return addLineGroup;
 726  
     }
 727  
 
 728  
     /**
 729  
      * Setter for the add line Group
 730  
      *
 731  
      * @param addLineGroup
 732  
      */
 733  
     public void setAddLineGroup(Group addLineGroup) {
 734  0
         this.addLineGroup = addLineGroup;
 735  0
     }
 736  
 
 737  
     /**
 738  
          * List of <code>Field</code> instances that make up the tables body. Pulled
 739  
          * by the layout manager template to send through the Grid layout
 740  
          * 
 741  
          * @return List<Field> table body fields
 742  
          */
 743  
         public List<Field> getDataFields() {
 744  0
                 return this.dataFields;
 745  
         }
 746  
 
 747  
         /**
 748  
          * Widget associated with the table to add functionality such as sorting,
 749  
          * paging, and export
 750  
          * 
 751  
          * @return TableTools instance
 752  
          */
 753  
         public RichTable getRichTable() {
 754  0
                 return this.richTable;
 755  
         }
 756  
 
 757  
         /**
 758  
          * Setter for the table tools widget
 759  
          * 
 760  
          * @param richTable
 761  
          */
 762  
         public void setRichTable(RichTable richTable) {
 763  0
                 this.richTable = richTable;
 764  0
         }
 765  
 
 766  
         /**
 767  
      * @return the numberOfDataColumns
 768  
      */
 769  
     public int getNumberOfDataColumns() {
 770  0
             return this.numberOfDataColumns;
 771  
     }
 772  
 
 773  
         /**
 774  
      * @param numberOfDataColumns the numberOfDataColumns to set
 775  
      */
 776  
     public void setNumberOfDataColumns(int numberOfDataColumns) {
 777  0
             this.numberOfDataColumns = numberOfDataColumns;
 778  0
     }
 779  
 
 780  
 }