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