Coverage Report - org.kuali.rice.krad.uif.layout.TableLayoutManager
 
Classes in this File Line Coverage Branch Coverage Complexity
TableLayoutManager
0%
0/153
0%
0/80
2.171
 
 1  
 /*
 2  
  * Copyright 2007 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 1.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/ecl1.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.container.CollectionGroup;
 21  
 import org.kuali.rice.krad.uif.container.Container;
 22  
 import org.kuali.rice.krad.uif.container.View;
 23  
 import org.kuali.rice.krad.uif.core.Component;
 24  
 import org.kuali.rice.krad.uif.field.ActionField;
 25  
 import org.kuali.rice.krad.uif.field.AttributeField;
 26  
 import org.kuali.rice.krad.uif.field.Field;
 27  
 import org.kuali.rice.krad.uif.field.GroupField;
 28  
 import org.kuali.rice.krad.uif.field.LabelField;
 29  
 import org.kuali.rice.krad.uif.field.MessageField;
 30  
 import org.kuali.rice.krad.uif.util.ComponentFactory;
 31  
 import org.kuali.rice.krad.uif.util.ComponentUtils;
 32  
 import org.kuali.rice.krad.uif.widget.TableTools;
 33  
 
 34  
 import java.util.ArrayList;
 35  
 import java.util.List;
 36  
 
 37  
 /**
 38  
  * Layout manager that works with <code>CollectionGroup</code> components and
 39  
  * renders the collection as a Table
 40  
  * 
 41  
  * <p>
 42  
  * Based on the fields defined, the <code>TableLayoutManager</code> will
 43  
  * dynamically create instances of the fields for each collection row. In
 44  
  * addition, the manager can create standard fields like the action and sequence
 45  
  * fields for each row. The manager supports options inherited from the
 46  
  * <code>GridLayoutManager</code> such as rowSpan, colSpan, and cell width
 47  
  * settings.
 48  
  * </p>
 49  
  * 
 50  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 51  
  */
 52  
 public class TableLayoutManager extends GridLayoutManager implements CollectionLayoutManager {
 53  
         private static final long serialVersionUID = 3622267585541524208L;
 54  
 
 55  
         private boolean useShortLabels;
 56  
         private boolean repeatHeader;
 57  
         private LabelField headerFieldPrototype;
 58  
 
 59  
         private boolean renderSequenceField;
 60  
         private String conditionalRenderSequenceField;
 61  
         private boolean generateAutoSequence;
 62  
         private Field sequenceFieldPrototype;
 63  
 
 64  
         private GroupField actionFieldPrototype;
 65  
 
 66  
         private GroupField subCollectionGroupFieldPrototype;
 67  
 
 68  
         // internal counter for the data columns (not including sequence, action)
 69  
         private int numberOfDataColumns;
 70  
 
 71  
         private List<LabelField> headerFields;
 72  
         private List<Field> dataFields;
 73  
 
 74  
         private TableTools tableTools;
 75  0
         private boolean headerAdded = false;
 76  
 
 77  0
         public TableLayoutManager() {
 78  0
                 useShortLabels = true;
 79  0
                 repeatHeader = false;
 80  0
                 renderSequenceField = true;
 81  0
                 generateAutoSequence = false;
 82  
 
 83  0
                 headerFields = new ArrayList<LabelField>();
 84  0
                 dataFields = new ArrayList<Field>();
 85  0
         }
 86  
         
 87  
         /**
 88  
          * The following actions are performed:
 89  
          * 
 90  
          * <ul>
 91  
          * <li>Sets sequence field prototype if auto sequence is true</li>
 92  
          * <li>Initializes the prototypes</li>
 93  
          * </ul>
 94  
          * 
 95  
          * @see org.kuali.rice.krad.uif.layout.BoxLayoutManager#performInitialization(org.kuali.rice.krad.uif.container.View,
 96  
          *      org.kuali.rice.krad.uif.container.Container)
 97  
          */
 98  
         @Override
 99  
         public void performInitialization(View view, Container container) {
 100  0
                 super.performInitialization(view, container);
 101  
                 
 102  0
         if (generateAutoSequence && !(sequenceFieldPrototype instanceof MessageField)) {
 103  0
             sequenceFieldPrototype = ComponentFactory.getMessageField();
 104  
         }
 105  
 
 106  0
                 view.getViewHelperService().performComponentInitialization(view, headerFieldPrototype);
 107  0
                 view.getViewHelperService().performComponentInitialization(view, sequenceFieldPrototype);
 108  0
                 view.getViewHelperService().performComponentInitialization(view, actionFieldPrototype);
 109  0
                 view.getViewHelperService().performComponentInitialization(view, subCollectionGroupFieldPrototype);
 110  0
         }
 111  
 
 112  
         /**
 113  
          * Sets up the final column count for rendering based on whether the
 114  
          * sequence and action fields have been generated
 115  
          * 
 116  
          * @see org.kuali.rice.krad.uif.layout.LayoutManagerBase#performFinalize(org.kuali.rice.krad.uif.container.View,
 117  
          *      java.lang.Object, org.kuali.rice.krad.uif.container.Container)
 118  
          */
 119  
         @Override
 120  
         public void performFinalize(View view, Object model, Container container) {
 121  0
                 super.performFinalize(view, model, container);
 122  
 
 123  0
                 CollectionGroup collectionGroup = (CollectionGroup) container;
 124  
 
 125  0
                 int totalColumns = getNumberOfDataColumns();
 126  0
                 if (renderSequenceField) {
 127  0
                         totalColumns++;
 128  
                 }
 129  
 
 130  0
                 if (collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly()) {
 131  0
                         totalColumns++;
 132  
                 }
 133  
 
 134  0
                 setNumberOfColumns(totalColumns);
 135  
 
 136  0
         }
 137  
 
 138  
         /**
 139  
          * Assembles the field instances for the collection line. The given sequence
 140  
          * field prototype is copied for the line sequence field. Likewise a copy of
 141  
          * the actionFieldPrototype is made and the given actions are set as the
 142  
          * items for the action field. Finally the generated items are assembled
 143  
          * together into the dataFields list with the given lineFields.
 144  
          * 
 145  
          * @see org.kuali.rice.krad.uif.layout.CollectionLayoutManager#buildLine(org.kuali.rice.krad.uif.container.View,
 146  
          *      java.lang.Object, org.kuali.rice.krad.uif.container.CollectionGroup,
 147  
          *      java.util.List, java.util.List, java.lang.String, java.util.List,
 148  
          *      java.lang.String, java.lang.Object, int)
 149  
          */
 150  
         public void buildLine(View view, Object model, CollectionGroup collectionGroup, List<Field> lineFields,
 151  
                         List<GroupField> subCollectionFields, String bindingPath, List<ActionField> actions, String idSuffix,
 152  
                         Object currentLine, int lineIndex) {
 153  0
                 boolean isAddLine = lineIndex == -1;
 154  
                 
 155  
         // if add line or first line set number of data columns
 156  0
         if (isAddLine || ((!collectionGroup.isRenderAddLine() || collectionGroup.isReadOnly()) && (lineIndex == 0))) {
 157  0
             if (isSuppressLineWrapping()) {
 158  0
                 setNumberOfDataColumns(lineFields.size());
 159  
             } else {
 160  0
                 setNumberOfDataColumns(getNumberOfColumns());
 161  
             }
 162  
         }
 163  
 
 164  
                 // if add line build table header first
 165  
                 // TODO: implement repeat header
 166  0
                 if (!headerAdded) {
 167  0
                         headerFields = new ArrayList<LabelField>();
 168  0
                         dataFields = new ArrayList<Field>();
 169  
 
 170  0
                         buildTableHeaderRows(collectionGroup, lineFields);
 171  0
                         ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.LINE, currentLine);
 172  0
                         ComponentUtils.pushObjectToContext(headerFields, UifConstants.ContextVariableNames.INDEX, new Integer(
 173  
                                         lineIndex));
 174  0
                         headerAdded = true;
 175  
                 }
 176  
 
 177  
                 // set label field rendered to true on line fields
 178  0
                 for (Field field : lineFields) {
 179  0
                         field.setLabelFieldRendered(true);
 180  
 
 181  
                         // don't display summary message
 182  
                         // TODO: remove once we have modifier
 183  0
                         ComponentUtils.setComponentPropertyDeep(field, "summaryMessageField.render", new Boolean(false));
 184  
                 }
 185  
 
 186  0
                 int rowCount = calculateNumberOfRows(collectionGroup.getItems());
 187  0
                 int rowSpan = rowCount + subCollectionFields.size();
 188  
 
 189  
                 // sequence field is always first and should span all rows for the line
 190  0
                 if (renderSequenceField) {
 191  0
                         Field sequenceField = null;
 192  0
             if (!isAddLine) {
 193  0
                 sequenceField = ComponentUtils.copy(sequenceFieldPrototype, idSuffix);
 194  
 
 195  0
                 if (generateAutoSequence && (sequenceField instanceof MessageField)) {
 196  0
                     ((MessageField) sequenceField).setMessageText(Integer.toString(lineIndex + 1));
 197  
                 }
 198  
             }
 199  
                         else {
 200  0
                                 sequenceField = ComponentUtils.copy(collectionGroup.getAddLineLabelField(), idSuffix);
 201  
                         }
 202  0
                         sequenceField.setRowSpan(rowSpan);
 203  
 
 204  0
                         if (sequenceField instanceof AttributeField) {
 205  0
                                 ((AttributeField) sequenceField).getBindingInfo().setBindByNamePrefix(bindingPath);
 206  
                         }
 207  
 
 208  0
                         ComponentUtils.updateContextForLine(sequenceField, currentLine, lineIndex);
 209  
 
 210  0
                         dataFields.add(sequenceField);
 211  
                 }
 212  
 
 213  
                 // now add the fields in the correct position
 214  0
                 int cellPosition = 0;
 215  0
                 for (Field lineField : lineFields) {
 216  0
                         dataFields.add(lineField);
 217  
 
 218  0
                         cellPosition += lineField.getColSpan();
 219  
 
 220  
                         // action field should be in last column
 221  0
                         if ((cellPosition == getNumberOfDataColumns()) && collectionGroup.isRenderLineActions()
 222  
                                         && !collectionGroup.isReadOnly()) {
 223  0
                                 GroupField lineActionsField = ComponentUtils.copy(actionFieldPrototype, idSuffix);
 224  
 
 225  0
                                 ComponentUtils.updateContextForLine(lineActionsField, currentLine, lineIndex);
 226  0
                                 lineActionsField.setRowSpan(rowSpan);
 227  0
                                 lineActionsField.setItems(actions);
 228  
 
 229  0
                                 dataFields.add(lineActionsField);
 230  0
                         }
 231  
                 }
 232  
 
 233  
                 // update colspan on sub-collection fields
 234  0
                 for (GroupField subCollectionField : subCollectionFields) {
 235  0
                         subCollectionField.setColSpan(numberOfDataColumns);
 236  
                 }
 237  
 
 238  
                 // add sub-collection fields to end of data fields
 239  0
                 dataFields.addAll(subCollectionFields);
 240  0
         }
 241  
 
 242  
         /**
 243  
          * Create the <code>LabelField</code> instances that will be used to render
 244  
          * the table header
 245  
          * 
 246  
          * <p>
 247  
          * For each column, a copy of headerFieldPrototype is made that determines
 248  
          * the label configuration. The actual label text comes from the field for
 249  
          * which the header applies to. The first column is always the sequence (if
 250  
          * enabled) and the last column contains the actions. Both the sequence and
 251  
          * action header fields will span all rows for the header.
 252  
          * </p>
 253  
          * 
 254  
          * <p>
 255  
          * The headerFields list will contain the final list of header fields built
 256  
          * </p>
 257  
          * 
 258  
          * @param collectionGroup
 259  
          *            - CollectionGroup container the table applies to
 260  
          * @param lineFields - fields for the data columns from which the headers are pulled
 261  
          */
 262  
         protected void buildTableHeaderRows(CollectionGroup collectionGroup, List<Field> lineFields) {
 263  
                 // row count needed to determine the row span for the sequence and
 264  
                 // action fields, since they should span all rows for the line
 265  0
                 int rowCount = calculateNumberOfRows(collectionGroup.getItems());
 266  
 
 267  
                 // first column is sequence label
 268  0
                 if (renderSequenceField) {
 269  0
                         sequenceFieldPrototype.setLabelFieldRendered(true);
 270  0
                         sequenceFieldPrototype.setRowSpan(rowCount);
 271  0
                         addHeaderField(sequenceFieldPrototype, 1);
 272  
                 }
 273  
 
 274  
                 // pull out label fields from the container's items
 275  0
                 int cellPosition = 0;
 276  0
                 for (Field field : lineFields) {
 277  0
                     if (!field.isRender() && StringUtils.isEmpty(field.getProgressiveRender())) {
 278  0
                         continue;
 279  
                     }
 280  
                     
 281  0
                         cellPosition += field.getColSpan();
 282  0
                         addHeaderField(field, cellPosition);
 283  
 
 284  
                         // add action header as last column in row
 285  0
                         if ((cellPosition == getNumberOfDataColumns()) && collectionGroup.isRenderLineActions()
 286  
                                         && !collectionGroup.isReadOnly()) {
 287  0
                                 actionFieldPrototype.setLabelFieldRendered(true);
 288  0
                                 actionFieldPrototype.setRowSpan(rowCount);
 289  0
                                 addHeaderField(actionFieldPrototype, cellPosition);
 290  
                         }
 291  
                 }
 292  0
         }
 293  
 
 294  
         /**
 295  
          * Creates a new instance of the header field prototype and then sets the
 296  
          * label to the short (if useShortLabels is set to true) or long label of
 297  
          * the given component. After created the header field is added to the list
 298  
          * making up the table header
 299  
          * 
 300  
          * @param field
 301  
          *            - field instance the header field is being created for
 302  
          * @param column
 303  
          *            - column number for the header, used for setting the id
 304  
          */
 305  
         protected void addHeaderField(Field field, int column) {
 306  0
                 LabelField headerField = ComponentUtils.copy(headerFieldPrototype, "_c" + column);
 307  0
                 if (useShortLabels) {
 308  0
                         headerField.setLabelText(field.getLabel());
 309  
                 }
 310  
                 else {
 311  0
                         headerField.setLabelText(field.getLabel());
 312  
                 }
 313  
 
 314  0
                 headerField.setRowSpan(field.getRowSpan());
 315  0
                 headerField.setColSpan(field.getColSpan());
 316  
 
 317  0
                 if ((field.getRequired() != null) && field.getRequired().booleanValue()) {
 318  0
                         headerField.getRequiredMessageField().setRender(true);
 319  
                 }
 320  
                 else {
 321  0
                         headerField.getRequiredMessageField().setRender(false);
 322  
                 }
 323  
 
 324  0
                 headerFields.add(headerField);
 325  0
         }
 326  
 
 327  
         /**
 328  
          * Calculates how many rows will be needed per collection line to display
 329  
          * the list of fields. Assumption is made that the total number of cells the
 330  
          * fields take up is evenly divisible by the configured number of columns
 331  
          * 
 332  
          * @param items
 333  
          *            - list of items that make up one collection line
 334  
          * @return int number of rows
 335  
          */
 336  
         protected int calculateNumberOfRows(List<? extends Field> items) {
 337  0
                 int rowCount = 0;
 338  
                 
 339  
                 // check flag that indicates only one row should be created
 340  0
                 if (isSuppressLineWrapping()) {
 341  0
                     return 1;
 342  
                 }
 343  
 
 344  0
                 int cellCount = 0;
 345  0
                 for (Field field : items) {
 346  0
                         cellCount += field.getColSpan() + field.getRowSpan() - 1;
 347  
                 }
 348  
 
 349  0
                 if (cellCount != 0) {
 350  0
                         rowCount = cellCount / getNumberOfDataColumns();
 351  
                 }
 352  
 
 353  0
                 return rowCount;
 354  
         }
 355  
 
 356  
         /**
 357  
          * @see org.kuali.rice.krad.uif.layout.ContainerAware#getSupportedContainer()
 358  
          */
 359  
         @Override
 360  
         public Class<? extends Container> getSupportedContainer() {
 361  0
                 return CollectionGroup.class;
 362  
         }
 363  
 
 364  
         /**
 365  
          * @see org.kuali.rice.krad.uif.layout.LayoutManagerBase#getNestedComponents()
 366  
          */
 367  
         @Override
 368  
         public List<Component> getNestedComponents() {
 369  0
                 List<Component> components = super.getNestedComponents();
 370  
 
 371  0
                 components.add(tableTools);
 372  0
                 components.addAll(headerFields);
 373  0
                 components.addAll(dataFields);
 374  
 
 375  0
                 return components;
 376  
         }
 377  
 
 378  
         /**
 379  
          * Indicates whether the short label for the collection field should be used
 380  
          * as the table header or the regular label
 381  
          * 
 382  
          * @return boolean true if short label should be used, false if long label
 383  
          *         should be used
 384  
          */
 385  
         public boolean isUseShortLabels() {
 386  0
                 return this.useShortLabels;
 387  
         }
 388  
 
 389  
         /**
 390  
          * Setter for the use short label indicator
 391  
          * 
 392  
          * @param useShortLabels
 393  
          */
 394  
         public void setUseShortLabels(boolean useShortLabels) {
 395  0
                 this.useShortLabels = useShortLabels;
 396  0
         }
 397  
 
 398  
         /**
 399  
          * Indicates whether the header should be repeated before each collection
 400  
          * row. If false the header is only rendered at the beginning of the table
 401  
          * 
 402  
          * @return boolean true if header should be repeated, false if it should
 403  
          *         only be rendered once
 404  
          */
 405  
         public boolean isRepeatHeader() {
 406  0
                 return this.repeatHeader;
 407  
         }
 408  
 
 409  
         /**
 410  
          * Setter for the repeat header indicator
 411  
          * 
 412  
          * @param repeatHeader
 413  
          */
 414  
         public void setRepeatHeader(boolean repeatHeader) {
 415  0
                 this.repeatHeader = repeatHeader;
 416  0
         }
 417  
 
 418  
         /**
 419  
          * <code>LabelField</code> instance to use as a prototype for creating the
 420  
          * tables header fields. For each header field the prototype will be copied
 421  
          * and adjusted as necessary
 422  
          * 
 423  
          * @return LabelField instance to serve as prototype
 424  
          */
 425  
         public LabelField getHeaderFieldPrototype() {
 426  0
                 return this.headerFieldPrototype;
 427  
         }
 428  
 
 429  
         /**
 430  
          * Setter for the header field prototype
 431  
          * 
 432  
          * @param headerFieldPrototype
 433  
          */
 434  
         public void setHeaderFieldPrototype(LabelField headerFieldPrototype) {
 435  0
                 this.headerFieldPrototype = headerFieldPrototype;
 436  0
         }
 437  
 
 438  
         /**
 439  
          * List of <code>LabelField</code> instances that should be rendered to make
 440  
          * up the tables header
 441  
          * 
 442  
          * @return List of label field instances
 443  
          */
 444  
         public List<LabelField> getHeaderFields() {
 445  0
                 return this.headerFields;
 446  
         }
 447  
 
 448  
         /**
 449  
          * Indicates whether the sequence field should be rendered for the
 450  
          * collection
 451  
          * 
 452  
          * @return boolean true if sequence field should be rendered, false if not
 453  
          */
 454  
         public boolean isRenderSequenceField() {
 455  0
                 return this.renderSequenceField;
 456  
         }
 457  
 
 458  
         /**
 459  
          * Setter for the render sequence field indicator
 460  
          * 
 461  
          * @param renderSequenceField
 462  
          */
 463  
         public void setRenderSequenceField(boolean renderSequenceField) {
 464  0
                 this.renderSequenceField = renderSequenceField;
 465  0
         }
 466  
 
 467  
         /**
 468  
          * Expression language string for conditionally setting the render sequence
 469  
          * field property
 470  
          * 
 471  
          * @return String el that should evaluate to boolean
 472  
          */
 473  
         public String getConditionalRenderSequenceField() {
 474  0
                 return this.conditionalRenderSequenceField;
 475  
         }
 476  
 
 477  
         /**
 478  
          * Setter for the conditional render sequence field string
 479  
          * 
 480  
          * @param conditionalRenderSequenceField
 481  
          */
 482  
         public void setConditionalRenderSequenceField(String conditionalRenderSequenceField) {
 483  0
                 this.conditionalRenderSequenceField = conditionalRenderSequenceField;
 484  0
         }
 485  
 
 486  
         /**
 487  
          * Attribute name to use as sequence value. For each collection line the
 488  
          * value of this field on the line will be retrieved and used as the
 489  
          * sequence value
 490  
          * 
 491  
          * @return String sequence property name
 492  
          */
 493  
     public String getSequencePropertyName() {
 494  0
         if ((sequenceFieldPrototype != null) && (sequenceFieldPrototype instanceof AttributeField)) {
 495  0
             return ((AttributeField) sequenceFieldPrototype).getPropertyName();
 496  
         }
 497  
 
 498  0
         return null;
 499  
     }
 500  
 
 501  
     /**
 502  
      * Setter for the sequence property name
 503  
      * 
 504  
      * @param sequencePropertyName
 505  
      */
 506  
     public void setSequencePropertyName(String sequencePropertyName) {
 507  0
         if ((sequenceFieldPrototype != null) && (sequenceFieldPrototype instanceof AttributeField)) {
 508  0
             ((AttributeField) sequenceFieldPrototype).setPropertyName(sequencePropertyName);
 509  
         }
 510  0
     }
 511  
         
 512  
     /**
 513  
      * Indicates whether the sequence field should be generated with the current
 514  
      * line number
 515  
      * 
 516  
      * <p>
 517  
      * If set to true the sequence field prototype will be changed to a message
 518  
      * field (if not already a message field) and the text will be set to the
 519  
      * current line number
 520  
      * </p>
 521  
      * 
 522  
      * @return boolean true if the sequence field should be generated from the
 523  
      *         line number, false if not
 524  
      */
 525  
     public boolean isGenerateAutoSequence() {
 526  0
         return this.generateAutoSequence;
 527  
     }
 528  
 
 529  
     /**
 530  
      * Setter for the generate auto sequence field
 531  
      * 
 532  
      * @param generateAutoSequence
 533  
      */
 534  
     public void setGenerateAutoSequence(boolean generateAutoSequence) {
 535  0
         this.generateAutoSequence = generateAutoSequence;
 536  0
     }
 537  
 
 538  
     /**
 539  
          * <code>Field</code> instance to serve as a prototype for the
 540  
          * sequence field. For each collection line this instance is copied and
 541  
          * adjusted as necessary
 542  
          * 
 543  
          * @return Attribute field instance
 544  
          */
 545  
         public Field getSequenceFieldPrototype() {
 546  0
                 return this.sequenceFieldPrototype;
 547  
         }
 548  
 
 549  
         /**
 550  
          * Setter for the sequence field prototype
 551  
          * 
 552  
          * @param sequenceFieldPrototype
 553  
          */
 554  
         public void setSequenceFieldPrototype(Field sequenceFieldPrototype) {
 555  0
                 this.sequenceFieldPrototype = sequenceFieldPrototype;
 556  0
         }
 557  
 
 558  
         /**
 559  
          * <code>GroupField</code> instance to serve as a prototype for the actions
 560  
          * column. For each collection line this instance is copied and adjusted as
 561  
          * necessary. Note the actual actions for the group come from the collection
 562  
          * groups actions List
 563  
          * (org.kuali.rice.krad.uif.container.CollectionGroup.getActionFields()). The
 564  
          * GroupField prototype is useful for setting styling of the actions column
 565  
          * and for the layout of the action fields. Note also the label associated
 566  
          * with the prototype is used for the action column header
 567  
          * 
 568  
          * @return GroupField instance
 569  
          */
 570  
         public GroupField getActionFieldPrototype() {
 571  0
                 return this.actionFieldPrototype;
 572  
         }
 573  
 
 574  
         /**
 575  
          * Setter for the action field prototype
 576  
          * 
 577  
          * @param actionFieldPrototype
 578  
          */
 579  
         public void setActionFieldPrototype(GroupField actionFieldPrototype) {
 580  0
                 this.actionFieldPrototype = actionFieldPrototype;
 581  0
         }
 582  
 
 583  
         /**
 584  
          * @see org.kuali.rice.krad.uif.layout.CollectionLayoutManager#getSubCollectionGroupFieldPrototype()
 585  
          */
 586  
         public GroupField getSubCollectionGroupFieldPrototype() {
 587  0
                 return this.subCollectionGroupFieldPrototype;
 588  
         }
 589  
 
 590  
         /**
 591  
          * Setter for the sub-collection field group prototype
 592  
          * 
 593  
          * @param subCollectionGroupFieldPrototype
 594  
          */
 595  
         public void setSubCollectionGroupFieldPrototype(GroupField subCollectionGroupFieldPrototype) {
 596  0
                 this.subCollectionGroupFieldPrototype = subCollectionGroupFieldPrototype;
 597  0
         }
 598  
 
 599  
         /**
 600  
          * List of <code>Field</code> instances that make up the tables body. Pulled
 601  
          * by the layout manager template to send through the Grid layout
 602  
          * 
 603  
          * @return List<Field> table body fields
 604  
          */
 605  
         public List<Field> getDataFields() {
 606  0
                 return this.dataFields;
 607  
         }
 608  
 
 609  
         /**
 610  
          * Widget associated with the table to add functionality such as sorting,
 611  
          * paging, and export
 612  
          * 
 613  
          * @return TableTools instance
 614  
          */
 615  
         public TableTools getTableTools() {
 616  0
                 return this.tableTools;
 617  
         }
 618  
 
 619  
         /**
 620  
          * Setter for the table tools widget
 621  
          * 
 622  
          * @param tableTools
 623  
          */
 624  
         public void setTableTools(TableTools tableTools) {
 625  0
                 this.tableTools = tableTools;
 626  0
         }
 627  
 
 628  
         /**
 629  
      * @return the numberOfDataColumns
 630  
      */
 631  
     public int getNumberOfDataColumns() {
 632  0
             return this.numberOfDataColumns;
 633  
     }
 634  
 
 635  
         /**
 636  
      * @param numberOfDataColumns the numberOfDataColumns to set
 637  
      */
 638  
     public void setNumberOfDataColumns(int numberOfDataColumns) {
 639  0
             this.numberOfDataColumns = numberOfDataColumns;
 640  0
     }
 641  
 
 642  
 }