Coverage Report - org.kuali.rice.krad.uif.component.BindingInfo
 
Classes in this File Line Coverage Branch Coverage Complexity
BindingInfo
11%
8/67
2%
1/34
2
 
 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.component;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.kuali.rice.krad.uif.UifConstants;
 20  
 import org.kuali.rice.krad.uif.view.View;
 21  
 import org.kuali.rice.krad.util.ObjectUtils;
 22  
 
 23  
 import java.io.Serializable;
 24  
 
 25  
 /**
 26  
  * Provides binding configuration for an DataBinding component (attribute or
 27  
  * collection)
 28  
  * 
 29  
  * <p>
 30  
  * From the binding configuration the binding path is determined (if not
 31  
  * manually set) and used to set the path in the UI or to get the value from the
 32  
  * model
 33  
  * </p>
 34  
  * 
 35  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 36  
  */
 37  
 public class BindingInfo extends ConfigurableBase implements Serializable {
 38  
     private static final long serialVersionUID = -7389398061672136091L;
 39  
 
 40  
     private boolean bindToForm;
 41  
     private boolean bindToMap;
 42  
 
 43  
     private String bindingName;
 44  
     private String bindByNamePrefix;
 45  
     private String bindingObjectPath;
 46  
 
 47  
     private String collectionPath;
 48  
 
 49  
     private String bindingPath;
 50  
 
 51  
     public BindingInfo() {
 52  2
         super();
 53  
 
 54  2
         bindToForm = false;
 55  2
         bindToMap = false;
 56  2
     }
 57  
 
 58  
     /**
 59  
      * Sets up some default binding properties based on the view configuration
 60  
      * and the component's property name
 61  
      * 
 62  
      * <p>
 63  
      * Sets the bindingName (if not set) to the given property name, and if the
 64  
      * binding object path has not been set uses the default binding object path
 65  
      * setup for the view
 66  
      * </p>
 67  
      * 
 68  
      * @param view
 69  
      *            - the view instance the component belongs to
 70  
      * @param propertyName
 71  
      *            - name of the property (relative to the parent object) the
 72  
      *            component binds to
 73  
      */
 74  
     public void setDefaults(View view, String propertyName) {
 75  0
         if (StringUtils.isBlank(bindingName)) {
 76  0
             bindingName = propertyName;
 77  
         }
 78  
 
 79  0
         if (StringUtils.isBlank(bindingObjectPath)) {
 80  0
             bindingObjectPath = view.getDefaultBindingObjectPath();
 81  
         }
 82  0
     }
 83  
 
 84  
     /**
 85  
      * Path to the property on the model the component binds to. Uses standard
 86  
      * dot notation for nested properties. If the binding path was manually set
 87  
      * it will be returned as it is, otherwise the path will be formed by using
 88  
      * the binding object path and the bind prefix
 89  
      * 
 90  
      * <p>
 91  
      * e.g. Property name 'foo' on a model would have binding path "foo", while
 92  
      * property name 'name' of the nested model property 'account' would have
 93  
      * binding path "account.name"
 94  
      * </p>
 95  
      * 
 96  
      * @return String binding path
 97  
      */
 98  
     public String getBindingPath() {
 99  2
         if (StringUtils.isNotBlank(bindingPath)) {
 100  2
             return bindingPath;
 101  
         }
 102  
 
 103  0
         String formedBindingPath = "";
 104  
 
 105  0
         if (!bindToForm && StringUtils.isNotBlank(bindingObjectPath)) {
 106  0
             formedBindingPath = bindingObjectPath;
 107  
         }
 108  
 
 109  0
         if (StringUtils.isNotBlank(bindByNamePrefix)) {
 110  0
             if (!bindByNamePrefix.startsWith("[") && StringUtils.isNotBlank(formedBindingPath)) {
 111  0
                 formedBindingPath += ".";
 112  
             }
 113  0
             formedBindingPath += bindByNamePrefix;
 114  
         }
 115  
 
 116  0
         if (bindToMap) {
 117  0
             formedBindingPath += "['" + bindingName + "']";
 118  
         } else {
 119  0
             if (StringUtils.isNotBlank(formedBindingPath)) {
 120  0
                 formedBindingPath += ".";
 121  
             }
 122  0
             formedBindingPath += bindingName;
 123  
         }
 124  
 
 125  0
         return formedBindingPath;
 126  
     }
 127  
 
 128  
     /**
 129  
      * Returns the binding prefix string that can be used to setup the binding
 130  
      * on <code>DataBinding</code> components that are children of the component
 131  
      * that contains the <code>BindingInfo</code>. The binding prefix is formed
 132  
      * like the binding path but without including the object path
 133  
      *
 134  
      * @return String binding prefix for nested components
 135  
      */
 136  
     public String getBindingPrefixForNested() {
 137  0
         String bindingPrefix = "";
 138  
 
 139  0
         if (StringUtils.isNotBlank(bindByNamePrefix)) {
 140  0
             bindingPrefix = bindByNamePrefix;
 141  
         }
 142  
 
 143  0
         if (bindToMap) {
 144  0
             bindingPrefix += "['" + bindingName + "']";
 145  
         } else {
 146  0
             if (StringUtils.isNotBlank(bindingPrefix)) {
 147  0
                 bindingPrefix += ".";
 148  
             }
 149  0
             bindingPrefix += bindingName;
 150  
         }
 151  
 
 152  0
         return bindingPrefix;
 153  
     }
 154  
 
 155  
     /**
 156  
      * Returns the binding path that is formed by taking the binding configuration
 157  
      * of this <code>BindingInfo</code> instance with the given property path as the
 158  
      * binding name. This can be used to get the binding path when just a property
 159  
      * name is given that is assumed to be on the same parent object of the field with
 160  
      * the configured binding info
 161  
      *
 162  
      * <p>
 163  
      * Special check is done for org.kuali.rice.krad.uif.UifConstants#NO_BIND_ADJUST_PREFIX prefix
 164  
      * on the property name which indicates the property path is the full path and should
 165  
      * not be adjusted. Also, if the property is prefixed with
 166  
      * org.kuali.rice.krad.uif.UifConstants#DATA_OBJECT_BIND_ADJUST_PREFIX, this indicates we should only append the
 167  
      * binding object path
 168  
      * </p>
 169  
      *
 170  
      * @param propertyPath - path for property to return full binding path for
 171  
      * @return String full binding path
 172  
      */
 173  
     public String getPropertyAdjustedBindingPath(String propertyPath) {
 174  0
         if (propertyPath.startsWith(UifConstants.NO_BIND_ADJUST_PREFIX)) {
 175  0
             propertyPath = StringUtils.removeStart(propertyPath, UifConstants.NO_BIND_ADJUST_PREFIX);
 176  0
             return propertyPath;
 177  
         }
 178  
 
 179  0
         BindingInfo bindingInfoCopy = (BindingInfo) ObjectUtils.deepCopy(this);
 180  
 
 181  
         // clear the path if explicitly set
 182  0
         bindingInfoCopy.setBindingPath("");
 183  
 
 184  0
         if (propertyPath.startsWith(UifConstants.DATA_OBJECT_BIND_ADJUST_PREFIX)) {
 185  0
             bindingInfoCopy.setBindByNamePrefix("");
 186  0
             propertyPath = StringUtils.removeStart(propertyPath, UifConstants.DATA_OBJECT_BIND_ADJUST_PREFIX);
 187  
         }
 188  0
         bindingInfoCopy.setBindingName(propertyPath);
 189  
 
 190  0
         return bindingInfoCopy.getBindingPath();
 191  
     }
 192  
 
 193  
     /**
 194  
      * Helper method for adding a path to the binding prefix
 195  
      *
 196  
      * @param bindPrefix - path to add
 197  
      */
 198  
     public void addToBindByNamePrefix(String bindPrefix) {
 199  0
         if (StringUtils.isNotBlank(bindByNamePrefix) && StringUtils.isNotBlank(bindPrefix)) {
 200  0
             bindByNamePrefix += "." + bindPrefix;
 201  
         } else {
 202  0
             bindByNamePrefix = bindPrefix;
 203  
         }
 204  0
     }
 205  
 
 206  
     /**
 207  
      * Setter for the binding path. Can be left blank in which the path will be
 208  
      * determined from the binding configuration
 209  
      * 
 210  
      * @param bindingPath
 211  
      */
 212  
     public void setBindingPath(String bindingPath) {
 213  2
         this.bindingPath = bindingPath;
 214  2
     }
 215  
 
 216  
     /**
 217  
      * Indicates whether the component binds directly to the form (that is its
 218  
      * bindingName gives a property available through the form), or whether is
 219  
      * binds through a nested form object. If bindToForm is false, it is assumed
 220  
      * the component binds to the object given by the form property whose path
 221  
      * is configured by bindingObjectPath.
 222  
      * 
 223  
      * @return boolean true if component binds directly to form, false if it
 224  
      *         binds to a nested object
 225  
      */
 226  
     public boolean isBindToForm() {
 227  0
         return this.bindToForm;
 228  
     }
 229  
 
 230  
     /**
 231  
      * Setter for the bind to form indicator
 232  
      * 
 233  
      * @param bindToForm
 234  
      */
 235  
     public void setBindToForm(boolean bindToForm) {
 236  0
         this.bindToForm = bindToForm;
 237  0
     }
 238  
 
 239  
     /**
 240  
      * Gives the name of the property that the component binds to. The name can
 241  
      * be nested but not the full path, just from the parent object or in the
 242  
      * case of binding directly to the form from the form object
 243  
      * 
 244  
      * <p>
 245  
      * If blank this will be set from the name field of the component
 246  
      * </p>
 247  
      * 
 248  
      * @return String name of the bind property
 249  
      */
 250  
     public String getBindingName() {
 251  0
         return this.bindingName;
 252  
     }
 253  
 
 254  
     /**
 255  
      * Setter for the bind property name
 256  
      * 
 257  
      * @param bindingName
 258  
      */
 259  
     public void setBindingName(String bindingName) {
 260  0
         this.bindingName = bindingName;
 261  0
     }
 262  
 
 263  
     /**
 264  
      * Prefix that will be used to form the binding path from the component
 265  
      * name. Typically used for nested collection properties
 266  
      * 
 267  
      * @return String binding prefix
 268  
      */
 269  
     public String getBindByNamePrefix() {
 270  0
         return this.bindByNamePrefix;
 271  
     }
 272  
 
 273  
     /**
 274  
      * Setter for the prefix to use for forming the binding path by name
 275  
      * 
 276  
      * @param bindByNamePrefix
 277  
      */
 278  
     public void setBindByNamePrefix(String bindByNamePrefix) {
 279  0
         this.bindByNamePrefix = bindByNamePrefix;
 280  0
     }
 281  
 
 282  
     /**
 283  
      * If field is part of a collection field, gives path to collection
 284  
      * 
 285  
      * <p>
 286  
      * This is used for metadata purposes when getting finding the attribute
 287  
      * definition from the dictionary and is not used in building the final
 288  
      * binding path
 289  
      * </p>
 290  
      * 
 291  
      * @return String path to collection
 292  
      */
 293  
     public String getCollectionPath() {
 294  0
         return this.collectionPath;
 295  
     }
 296  
 
 297  
     /**
 298  
      * Setter for the field's collection path (if part of a collection)
 299  
      * 
 300  
      * @param collectionPath
 301  
      */
 302  
     public void setCollectionPath(String collectionPath) {
 303  0
         this.collectionPath = collectionPath;
 304  0
     }
 305  
 
 306  
     /**
 307  
      * For attribute fields that do not belong to the default form object (given
 308  
      * by the view), this field specifies the path to the object (on the form)
 309  
      * the attribute does belong to.
 310  
      * 
 311  
      * <p>
 312  
      * e.g. Say we have an attribute field with property name 'number', that
 313  
      * belongs to the object given by the 'account' property on the form. The
 314  
      * form object path would therefore be set to 'account'. If the property
 315  
      * belonged to the object given by the 'document.header' property of the
 316  
      * form, the binding object path would be set to 'document.header'. Note if
 317  
      * the binding object path is not set for an attribute field (or any
 318  
      * <code>DataBinding</code> component), the binding object path configured
 319  
      * on the <code>View</code> will be used (unless bindToForm is set to true,
 320  
      * where is assumed the property is directly available from the form).
 321  
      * </p>
 322  
      * 
 323  
      * @return String path to object from form
 324  
      */
 325  
     public String getBindingObjectPath() {
 326  0
         return this.bindingObjectPath;
 327  
     }
 328  
 
 329  
     /**
 330  
      * Setter for the object path on the form
 331  
      * 
 332  
      * @param bindingObjectPath
 333  
      */
 334  
     public void setBindingObjectPath(String bindingObjectPath) {
 335  0
         this.bindingObjectPath = bindingObjectPath;
 336  0
     }
 337  
 
 338  
     /**
 339  
      * Indicates whether the parent object for the property that we are binding
 340  
      * to is a Map. If true the binding path will be adjusted to use the map key
 341  
      * syntax
 342  
      * 
 343  
      * @return boolean true if the property binds to a map, false if it does not
 344  
      */
 345  
     public boolean isBindToMap() {
 346  0
         return this.bindToMap;
 347  
     }
 348  
 
 349  
     /**
 350  
      * Setter for the bind to map indicator
 351  
      * 
 352  
      * @param bindToMap
 353  
      */
 354  
     public void setBindToMap(boolean bindToMap) {
 355  0
         this.bindToMap = bindToMap;
 356  0
     }
 357  
 
 358  
 }