Coverage Report - org.kuali.rice.kns.uif.container.CollectionGroup
 
Classes in this File Line Coverage Branch Coverage Complexity
CollectionGroup
0%
0/86
0%
0/28
1.469
 
 1  
 /*
 2  
  * Copyright 2007 The Kuali Foundation Licensed under the Educational Community
 3  
  * License, Version 1.0 (the "License"); you may not use this file except in
 4  
  * compliance with the License. You may obtain a copy of the License at
 5  
  * http://www.opensource.org/licenses/ecl1.php Unless required by applicable law
 6  
  * or agreed to in writing, software distributed under the License is
 7  
  * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 8  
  * KIND, either express or implied. See the License for the specific language
 9  
  * governing permissions and limitations under the License.
 10  
  */
 11  
 package org.kuali.rice.kns.uif.container;
 12  
 
 13  
 import java.util.ArrayList;
 14  
 import java.util.List;
 15  
 
 16  
 import org.apache.commons.lang.StringUtils;
 17  
 import org.kuali.rice.kns.uif.core.BindingInfo;
 18  
 import org.kuali.rice.kns.uif.core.Component;
 19  
 import org.kuali.rice.kns.uif.core.DataBinding;
 20  
 import org.kuali.rice.kns.uif.field.ActionField;
 21  
 import org.kuali.rice.kns.uif.field.AttributeField;
 22  
 import org.kuali.rice.kns.uif.field.Field;
 23  
 import org.kuali.rice.kns.uif.field.LabelField;
 24  
 
 25  
 /**
 26  
  * Group that holds a collection of objects and configuration for presenting the
 27  
  * collection in the UI. Supports functionality such as add line, line actions,
 28  
  * and nested collections.
 29  
  * <p>
 30  
  * Note the standard header/footer can be used to give a header to the
 31  
  * collection as a whole, or to provide actions that apply to the entire
 32  
  * collection
 33  
  * </p>
 34  
  * <p>
 35  
  * For binding purposes the binding path of each row field is indexed. The name
 36  
  * property inherited from <code>ComponentBase</code> is used as the collection
 37  
  * name. The collectionObjectClass property is used to lookup attributes from
 38  
  * the data dictionary.
 39  
  * </p>
 40  
  * 
 41  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 42  
  */
 43  
 public class CollectionGroup extends Group implements DataBinding {
 44  
     private static final long serialVersionUID = -6496712566071542452L;
 45  
 
 46  
     private Class<?> collectionObjectClass;
 47  
 
 48  
     private String propertyName;
 49  
     private BindingInfo bindingInfo;
 50  
 
 51  
     private boolean renderAddLine;
 52  
     private String addLinePropertyName;
 53  
     private BindingInfo addLineBindingInfo;
 54  
     private LabelField addLineLabelField;
 55  
     private List<ActionField> addLineActionFields;
 56  
 
 57  
     private boolean renderLineActions;
 58  
     private List<ActionField> actionFields;
 59  
 
 60  
     private List<CollectionGroup> subCollections;
 61  
 
 62  
     private CollectionGroupBuilder collectionGroupBuilder;
 63  
 
 64  0
     public CollectionGroup() {
 65  0
         renderAddLine = true;
 66  0
         renderLineActions = true;
 67  
 
 68  0
         actionFields = new ArrayList<ActionField>();
 69  0
         addLineActionFields = new ArrayList<ActionField>();
 70  0
         subCollections = new ArrayList<CollectionGroup>();
 71  0
     }
 72  
 
 73  
     /**
 74  
      * The following actions are performed:
 75  
      * <ul>
 76  
      * <li>Set fieldBindModelPath to the collection model path (since the fields
 77  
      * have to belong to the same model as the collection)</li>
 78  
      * <li>Set defaults for binding</li>
 79  
      * <li>Sets the dictionary entry (if blank) on each of the items to the
 80  
      * collection class</li>
 81  
      * </ul>
 82  
      * 
 83  
      * @see org.kuali.rice.kns.uif.core.ComponentBase#performInitialization(org.kuali.rice.kns.uif.container.View)
 84  
      */
 85  
     @Override
 86  
     public void performInitialization(View view) {
 87  0
         setFieldBindingObjectPath(getBindingInfo().getBindingObjectPath());
 88  
 
 89  0
         super.performInitialization(view);
 90  
 
 91  0
         if (bindingInfo != null) {
 92  0
             bindingInfo.setDefaults(view, getPropertyName());
 93  
         }
 94  
 
 95  0
         if (addLineBindingInfo != null) {
 96  
             // add line binds to model property
 97  0
             if (StringUtils.isNotBlank(addLinePropertyName)) {
 98  0
                 addLineBindingInfo.setDefaults(view, getPropertyName());
 99  0
                 addLineBindingInfo.setBindingName(addLinePropertyName);
 100  0
                 if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
 101  0
                     addLineBindingInfo.setBindByNamePrefix(getFieldBindByNamePrefix());
 102  
                 }
 103  
             }
 104  
         }
 105  
 
 106  0
         for (Component item : getItems()) {
 107  0
             if (item instanceof AttributeField) {
 108  0
                 AttributeField field = (AttributeField) item;
 109  
 
 110  0
                 if (StringUtils.isBlank(field.getDictionaryObjectEntry())) {
 111  0
                     field.setDictionaryObjectEntry(collectionObjectClass.getName());
 112  
                 }
 113  0
             }
 114  
         }
 115  
 
 116  
         // initialize container items and sub-collections (since they are not in child list)
 117  0
         for (Component item : getItems()) {
 118  0
             view.getViewHelperService().performComponentInitialization(view, item);
 119  
         }
 120  
         
 121  0
         for (CollectionGroup collectionGroup : getSubCollections()) {
 122  0
             view.getViewHelperService().performComponentInitialization(view, collectionGroup);
 123  
         }
 124  0
     }
 125  
 
 126  
     /**
 127  
      * Calls the configured <code>CollectionGroupBuilder</code> to build the
 128  
      * necessary components based on the collection data
 129  
      * 
 130  
      * @see org.kuali.rice.kns.uif.container.ContainerBase#performApplyModel(org.kuali.rice.kns.uif.container.View,
 131  
      *      java.lang.Object)
 132  
      */
 133  
     @Override
 134  
     public void performApplyModel(View view, Object model) {
 135  0
         super.performApplyModel(view, model);
 136  
 
 137  0
         getCollectionGroupBuilder().build(view, model, this);
 138  0
     }
 139  
 
 140  
     /**
 141  
      * New collection lines are handled in the framework by maintaining a map on
 142  
      * the form. The map contains as a key the collection name, and as value an
 143  
      * instance of the collection type. An entry is created here for the
 144  
      * collection represented by the <code>CollectionGroup</code> if an instance
 145  
      * is not available (clearExistingLine will force a new instance). The given
 146  
      * model must be a subclass of <code>UifFormBase</code> in order to find the
 147  
      * Map.
 148  
      * 
 149  
      * @param model
 150  
      *            - Model instance that contains the new collection lines Map
 151  
      * @param clearExistingLine
 152  
      *            - boolean that indicates whether the line should be set to a
 153  
      *            new instance if it already exists
 154  
      */
 155  
     public void initializeNewCollectionLine(View view, Object model, CollectionGroup collectionGroup,
 156  
             boolean clearExistingLine) {
 157  0
         getCollectionGroupBuilder().initializeNewCollectionLine(view, model, collectionGroup, clearExistingLine);
 158  0
     }
 159  
 
 160  
     /**
 161  
      * @see org.kuali.rice.kns.uif.container.ContainerBase#getNestedComponents()
 162  
      */
 163  
     @Override
 164  
     public List<Component> getNestedComponents() {
 165  0
         List<Component> components = super.getNestedComponents();
 166  
 
 167  0
         components.add(addLineLabelField);
 168  0
         components.addAll(actionFields);
 169  0
         components.addAll(addLineActionFields);
 170  
 
 171  
         // remove the containers items because we don't want them as children
 172  
         // (they will become children of the layout manager as the rows are
 173  
         // created)
 174  0
         for (Component item : getItems()) {
 175  0
             if (components.contains(item)) {
 176  0
                 components.remove(item);
 177  
             }
 178  
         }
 179  
 
 180  0
         return components;
 181  
     }
 182  
 
 183  
     /**
 184  
      * Object class the collection maintains. Used to get dictionary information
 185  
      * in addition to creating new instances for the collection when necessary
 186  
      * 
 187  
      * @return Class<?> collection object class
 188  
      */
 189  
     public Class<?> getCollectionObjectClass() {
 190  0
         return this.collectionObjectClass;
 191  
     }
 192  
 
 193  
     /**
 194  
      * Setter for the collection object class
 195  
      * 
 196  
      * @param collectionObjectClass
 197  
      */
 198  
     public void setCollectionObjectClass(Class<?> collectionObjectClass) {
 199  0
         this.collectionObjectClass = collectionObjectClass;
 200  0
     }
 201  
 
 202  
     /**
 203  
      * @see org.kuali.rice.kns.uif.core.DataBinding#getPropertyName()
 204  
      */
 205  
     public String getPropertyName() {
 206  0
         return this.propertyName;
 207  
     }
 208  
 
 209  
     /**
 210  
      * Setter for the collections property name
 211  
      * 
 212  
      * @param propertyName
 213  
      */
 214  
     public void setPropertyName(String propertyName) {
 215  0
         this.propertyName = propertyName;
 216  0
     }
 217  
 
 218  
     /**
 219  
      * Determines the binding path for the collection. Used to get the
 220  
      * collection value from the model in addition to setting the binding path
 221  
      * for the collection attributes
 222  
      * 
 223  
      * @see org.kuali.rice.kns.uif.core.DataBinding#getBindingInfo()
 224  
      */
 225  
     public BindingInfo getBindingInfo() {
 226  0
         return this.bindingInfo;
 227  
     }
 228  
 
 229  
     /**
 230  
      * Setter for the binding info instance
 231  
      * 
 232  
      * @param bindingInfo
 233  
      */
 234  
     public void setBindingInfo(BindingInfo bindingInfo) {
 235  0
         this.bindingInfo = bindingInfo;
 236  0
     }
 237  
 
 238  
     /**
 239  
      * Action fields that should be rendered for each collection line. Example
 240  
      * line action is the delete action
 241  
      * 
 242  
      * @return List<ActionField> line action fields
 243  
      */
 244  
     public List<ActionField> getActionFields() {
 245  0
         return this.actionFields;
 246  
     }
 247  
 
 248  
     /**
 249  
      * Setter for the line action fields list
 250  
      * 
 251  
      * @param actionFields
 252  
      */
 253  
     public void setActionFields(List<ActionField> actionFields) {
 254  0
         this.actionFields = actionFields;
 255  0
     }
 256  
 
 257  
     /**
 258  
      * Indicates whether the action column for the collection should be rendered
 259  
      * 
 260  
      * @return boolean true if the actions should be rendered, false if not
 261  
      * @see #getActionFields()
 262  
      */
 263  
     public boolean isRenderLineActions() {
 264  0
         return this.renderLineActions;
 265  
     }
 266  
 
 267  
     /**
 268  
      * Setter for the render line actions indicator
 269  
      * 
 270  
      * @param renderLineActions
 271  
      */
 272  
     public void setRenderLineActions(boolean renderLineActions) {
 273  0
         this.renderLineActions = renderLineActions;
 274  0
     }
 275  
 
 276  
     /**
 277  
      * Indicates whether an add line should be rendered for the collection
 278  
      * 
 279  
      * @return boolean true if add line should be rendered, false if it should
 280  
      *         not be
 281  
      */
 282  
     public boolean isRenderAddLine() {
 283  0
         return this.renderAddLine;
 284  
     }
 285  
 
 286  
     /**
 287  
      * Setter for the render add line indicator
 288  
      * 
 289  
      * @param renderAddLine
 290  
      */
 291  
     public void setRenderAddLine(boolean renderAddLine) {
 292  0
         this.renderAddLine = renderAddLine;
 293  0
     }
 294  
 
 295  
     /**
 296  
      * Convenience getter for the add line label field text. The text is used to
 297  
      * label the add line when rendered and its placement depends on the
 298  
      * <code>LayoutManager</code>.
 299  
      * <p>
 300  
      * For the <code>TableLayoutManager</code> the label appears in the sequence
 301  
      * column to the left of the add line fields. For the
 302  
      * <code>StackedLayoutManager</code> the label is placed into the group
 303  
      * header for the line.
 304  
      * </p>
 305  
      * 
 306  
      * @return String add line label
 307  
      */
 308  
     public String getAddLineLabel() {
 309  0
         if (getAddLineLabelField() != null) {
 310  0
             return getAddLineLabelField().getLabelText();
 311  
         }
 312  
 
 313  0
         return null;
 314  
     }
 315  
 
 316  
     /**
 317  
      * Setter for the add line label text
 318  
      * 
 319  
      * @param addLineLabel
 320  
      */
 321  
     public void setAddLineLabel(String addLineLabel) {
 322  0
         if (getAddLineLabelField() != null) {
 323  0
             getAddLineLabelField().setLabelText(addLineLabel);
 324  
         }
 325  0
     }
 326  
 
 327  
     /**
 328  
      * <code>LabelField</code> instance for the add line label
 329  
      * 
 330  
      * @return LabelField add line label field
 331  
      * @see #getAddLineLabel()
 332  
      */
 333  
     public LabelField getAddLineLabelField() {
 334  0
         return this.addLineLabelField;
 335  
     }
 336  
 
 337  
     /**
 338  
      * Setter for the <code>LabelField</code> instance for the add line label
 339  
      * 
 340  
      * @param addLineLabelField
 341  
      * @see #getAddLineLabel()
 342  
      */
 343  
     public void setAddLineLabelField(LabelField addLineLabelField) {
 344  0
         this.addLineLabelField = addLineLabelField;
 345  0
     }
 346  
 
 347  
     /**
 348  
      * Name of the property that contains an instance for the add line. If set
 349  
      * this is used with the binding info to create the path to the add line.
 350  
      * Can be left blank in which case the framework will manage the add line
 351  
      * instance in a generic map.
 352  
      * 
 353  
      * @return String add line property name
 354  
      */
 355  
     public String getAddLinePropertyName() {
 356  0
         return this.addLinePropertyName;
 357  
     }
 358  
 
 359  
     /**
 360  
      * Setter for the add line property name
 361  
      * 
 362  
      * @param addLinePropertyName
 363  
      */
 364  
     public void setAddLinePropertyName(String addLinePropertyName) {
 365  0
         this.addLinePropertyName = addLinePropertyName;
 366  0
     }
 367  
 
 368  
     /**
 369  
      * <code>BindingInfo</code> instance for the add line property used to
 370  
      * determine the full binding path. If add line name given
 371  
      * {@link #getAddLineLabel()} then it is set as the binding name on the
 372  
      * binding info. Add line label and binding info are not required, in which
 373  
      * case the framework will manage the new add line instances through a
 374  
      * generic map (model must extend UifFormBase)
 375  
      * 
 376  
      * @return BindingInfo add line binding info
 377  
      */
 378  
     public BindingInfo getAddLineBindingInfo() {
 379  0
         return this.addLineBindingInfo;
 380  
     }
 381  
 
 382  
     /**
 383  
      * Setter for the add line binding info
 384  
      * 
 385  
      * @param addLineBindingInfo
 386  
      */
 387  
     public void setAddLineBindingInfo(BindingInfo addLineBindingInfo) {
 388  0
         this.addLineBindingInfo = addLineBindingInfo;
 389  0
     }
 390  
 
 391  
     /**
 392  
      * Action fields that should be rendered for the add line. This is generally
 393  
      * the add action (button) but can be configured to contain additional
 394  
      * actions
 395  
      * 
 396  
      * @return List<ActionField> add line action fields
 397  
      */
 398  
     public List<ActionField> getAddLineActionFields() {
 399  0
         return this.addLineActionFields;
 400  
     }
 401  
 
 402  
     /**
 403  
      * Setter for the add line action fields
 404  
      * 
 405  
      * @param addLineActionFields
 406  
      */
 407  
     public void setAddLineActionFields(List<ActionField> addLineActionFields) {
 408  0
         this.addLineActionFields = addLineActionFields;
 409  0
     }
 410  
 
 411  
     /**
 412  
      * List of <code>CollectionGroup</code> instances that are sub-collections
 413  
      * of the collection represented by this collection group
 414  
      * 
 415  
      * @return List<CollectionGroup> sub collections
 416  
      */
 417  
     public List<CollectionGroup> getSubCollections() {
 418  0
         return this.subCollections;
 419  
     }
 420  
 
 421  
     /**
 422  
      * Setter for the sub collection list
 423  
      * 
 424  
      * @param subCollections
 425  
      */
 426  
     public void setSubCollections(List<CollectionGroup> subCollections) {
 427  0
         this.subCollections = subCollections;
 428  0
     }
 429  
 
 430  
     /**
 431  
      * <code>CollectionGroupBuilder</code> instance that will build the
 432  
      * components dynamically for the collection instance
 433  
      * 
 434  
      * @return CollectionGroupBuilder instance
 435  
      */
 436  
     public CollectionGroupBuilder getCollectionGroupBuilder() {
 437  0
         if (this.collectionGroupBuilder == null) {
 438  0
             this.collectionGroupBuilder = new CollectionGroupBuilder();
 439  
         }
 440  0
         return this.collectionGroupBuilder;
 441  
     }
 442  
 
 443  
     /**
 444  
      * Setter for the collection group building instance
 445  
      * 
 446  
      * @param collectionGroupBuilder
 447  
      */
 448  
     public void setCollectionGroupBuilder(CollectionGroupBuilder collectionGroupBuilder) {
 449  0
         this.collectionGroupBuilder = collectionGroupBuilder;
 450  0
     }
 451  
 
 452  
     /**
 453  
      * @see org.kuali.rice.kns.uif.container.ContainerBase#getItems()
 454  
      */
 455  
     @SuppressWarnings("unchecked")
 456  
     @Override
 457  
     public List<? extends Field> getItems() {
 458  0
         return (List<? extends Field>) super.getItems();
 459  
     }
 460  
 
 461  
 }