Coverage Report - org.kuali.rice.krad.uif.util.ComponentUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
ComponentUtils
0%
0/188
0%
0/116
3.31
 
 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.util;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.kuali.rice.core.api.util.type.TypeUtils;
 20  
 import org.kuali.rice.krad.uif.UifConstants;
 21  
 import org.kuali.rice.krad.uif.container.CollectionGroup;
 22  
 import org.kuali.rice.krad.uif.container.Container;
 23  
 import org.kuali.rice.krad.uif.component.Component;
 24  
 import org.kuali.rice.krad.uif.component.DataBinding;
 25  
 import org.kuali.rice.krad.uif.component.Ordered;
 26  
 import org.kuali.rice.krad.uif.field.Field;
 27  
 import org.kuali.rice.krad.uif.field.FieldGroup;
 28  
 import org.kuali.rice.krad.uif.layout.LayoutManager;
 29  
 import org.kuali.rice.krad.util.ObjectUtils;
 30  
 import org.springframework.beans.BeanUtils;
 31  
 import org.springframework.core.OrderComparator;
 32  
 
 33  
 import java.beans.PropertyDescriptor;
 34  
 import java.io.Serializable;
 35  
 import java.util.ArrayList;
 36  
 import java.util.Collections;
 37  
 import java.util.HashSet;
 38  
 import java.util.List;
 39  
 import java.util.Set;
 40  
 
 41  
 /**
 42  
  * Utility class providing methods to help create and modify
 43  
  * <code>Component</code> instances
 44  
  * 
 45  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 46  
  */
 47  0
 public class ComponentUtils {
 48  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ComponentUtils.class);
 49  
 
 50  
 
 51  
     public static <T extends Component> T copy(T component) {
 52  0
         return copy(component, null);
 53  
     }
 54  
 
 55  
     public static <T extends Component> T copy(T component, String idSuffix) {
 56  0
         T copy = copyObject(component);
 57  
 
 58  0
         if (StringUtils.isNotBlank(idSuffix)) {
 59  0
             updateIdsWithSuffixNested(copy, idSuffix);
 60  
         }
 61  
 
 62  0
         return copy;
 63  
     }
 64  
 
 65  
     public static <T extends Object> T copyObject(T object) {
 66  0
         if (object == null) {
 67  0
             return null;
 68  
         }
 69  
 
 70  0
         T copy = null;
 71  
         try {
 72  0
             copy = CloneUtils.deepClone(object);
 73  
         }
 74  0
         catch (Exception e) {
 75  0
             throw new RuntimeException(e);
 76  0
         }
 77  
 
 78  0
         return copy;
 79  
     }
 80  
 
 81  
     protected static Object getCopyPropertyValue(Set<String> propertiesForReferenceCopy, String propertyName,
 82  
             Object propertyValue) {
 83  0
         if (propertyValue == null) {
 84  0
             return null;
 85  
         }
 86  
 
 87  0
         Object copyValue = propertyValue;
 88  
 
 89  0
         Class<?> valuePropertyType = propertyValue.getClass();
 90  0
         if (propertiesForReferenceCopy.contains(propertyName) || TypeUtils.isSimpleType(valuePropertyType)
 91  
                 || TypeUtils.isClassClass(valuePropertyType)) {
 92  0
             return copyValue;
 93  
         }
 94  
 
 95  0
         if (Component.class.isAssignableFrom(valuePropertyType)
 96  
                 || LayoutManager.class.isAssignableFrom(valuePropertyType)) {
 97  0
             copyValue = copyObject(propertyValue);
 98  
         }
 99  
         else {
 100  0
             copyValue = ObjectUtils.deepCopy((Serializable) propertyValue);
 101  
         }
 102  
 
 103  0
         return copyValue;
 104  
     }
 105  
 
 106  
     @SuppressWarnings("unchecked")
 107  
     protected static <T extends Object> T getNewInstance(T object) {
 108  0
         T copy = null;
 109  
         try {
 110  0
             copy = (T) object.getClass().newInstance();
 111  
         }
 112  0
         catch (Exception e) {
 113  0
             throw new RuntimeException("Unable to create new instance of class: " + object.getClass());
 114  0
         }
 115  
 
 116  0
         return copy;
 117  
     }
 118  
 
 119  
     public static <T extends Field> List<T> copyFieldList(List<T> fields, String addBindingPrefix, String idSuffix) {
 120  0
         List<T> copiedFieldList = copyFieldList(fields, idSuffix);
 121  
 
 122  0
         prefixBindingPath(copiedFieldList, addBindingPrefix);
 123  
 
 124  0
         return copiedFieldList;
 125  
     }
 126  
 
 127  
     public static <T extends Field> List<T> copyFieldList(List<T> fields, String idSuffix) {
 128  0
         List<T> copiedFieldList = new ArrayList<T>();
 129  
 
 130  0
         for (T field : fields) {
 131  0
             T copiedField = copy(field, idSuffix);
 132  0
             copiedFieldList.add(copiedField);
 133  0
         }
 134  
 
 135  0
         return copiedFieldList;
 136  
     }
 137  
 
 138  
     public static <T extends Component> T copyComponent(T component, String addBindingPrefix, String idSuffix) {
 139  0
         T copy = copy(component, idSuffix);
 140  
 
 141  0
         prefixBindingPathNested(copy, addBindingPrefix);
 142  
 
 143  0
         return copy;
 144  
     }
 145  
 
 146  
     public static <T extends Component> List<T> copyComponentList(List<T> components, String idSuffix) {
 147  0
         List<T> copiedComponentList = new ArrayList<T>();
 148  
 
 149  0
         for (T field : components) {
 150  0
             T copiedComponent = copy(field, idSuffix);
 151  0
             copiedComponentList.add(copiedComponent);
 152  0
         }
 153  
 
 154  0
         return copiedComponentList;
 155  
     }
 156  
 
 157  
     @SuppressWarnings("unchecked")
 158  
     public static <T extends Component> List<T> getComponentsOfType(List<? extends Component> items,
 159  
             Class<T> componentType) {
 160  0
         List<T> typeComponents = new ArrayList<T>();
 161  
 
 162  0
         for (Component component : items) {
 163  0
             if (componentType.isAssignableFrom(component.getClass())) {
 164  0
                 typeComponents.add((T) component);
 165  
             }
 166  
         }
 167  
 
 168  0
         return typeComponents;
 169  
     }
 170  
     
 171  
     public static <T extends Component> List<T> getComponentsOfTypeDeep(List<? extends Component> items,
 172  
             Class<T> componentType) {
 173  0
         List<T> typeComponents = new ArrayList<T>();
 174  
 
 175  0
         for (Component component : items) {
 176  0
             typeComponents.addAll(getComponentsOfTypeDeep(component, componentType));
 177  
         }
 178  
 
 179  0
         return typeComponents;
 180  
     }
 181  
     
 182  
     @SuppressWarnings("unchecked")
 183  
     public static <T extends Component> List<T> getComponentsOfTypeDeep(Component component, Class<T> componentType) {
 184  0
         List<T> typeComponents = new ArrayList<T>();
 185  
 
 186  0
         if (component == null) {
 187  0
             return typeComponents;
 188  
         }
 189  
 
 190  0
         if (componentType.isAssignableFrom(component.getClass())) {
 191  0
             typeComponents.add((T) component);
 192  
         }
 193  
 
 194  0
         for (Component nested : component.getComponentsForLifecycle()) {
 195  0
             typeComponents.addAll(getComponentsOfTypeDeep(nested, componentType));
 196  
         }
 197  
 
 198  0
         return typeComponents;
 199  
     }
 200  
 
 201  
     public static List<Component> getAllNestedComponents(Component component) {
 202  0
         List<Component> components = new ArrayList<Component>();
 203  
 
 204  0
         if (component == null) {
 205  0
             return components;
 206  
         }
 207  
 
 208  0
         for (Component nested : component.getComponentsForLifecycle()) {
 209  0
             components.add(nested);
 210  0
             components.addAll(getAllNestedComponents(nested));
 211  
         }
 212  
 
 213  0
         return components;
 214  
     }
 215  
 
 216  
     public static void prefixBindingPath(List<? extends Field> fields, String addBindingPrefix) {
 217  0
         for (Field field : fields) {
 218  0
             if (field instanceof DataBinding) {
 219  0
                 prefixBindingPath((DataBinding) field, addBindingPrefix);
 220  
             }
 221  0
             else if ((field instanceof FieldGroup) && (((FieldGroup) field).getItems() != null) ) {
 222  0
                 List<Field> groupFields = getComponentsOfType(((FieldGroup) field).getItems(), Field.class);
 223  0
                 prefixBindingPath(groupFields, addBindingPrefix);
 224  0
             }
 225  
         }
 226  0
     }
 227  
 
 228  
     public static void prefixBindingPathNested(Component component, String addBindingPrefix) {
 229  0
         if (component instanceof DataBinding) {
 230  0
             if (LOG.isDebugEnabled()) {
 231  0
                 LOG.info("setting nested binding prefix '"+ addBindingPrefix  +"' on " + component);
 232  
             }
 233  0
             prefixBindingPath((DataBinding) component, addBindingPrefix);
 234  
         }
 235  
 
 236  0
         for (Component nested : component.getComponentsForLifecycle()) {
 237  0
            if (nested != null) {
 238  0
               prefixBindingPathNested(nested, addBindingPrefix);
 239  
            }
 240  
         }
 241  0
     }
 242  
 
 243  
     public static void prefixBindingPath(DataBinding field, String addBindingPrefix) {
 244  0
         String bindingPrefix = addBindingPrefix;
 245  0
         if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
 246  0
             bindingPrefix += "." + field.getBindingInfo().getBindByNamePrefix();
 247  
         }
 248  0
         field.getBindingInfo().setBindByNamePrefix(bindingPrefix);
 249  0
     }
 250  
 
 251  
     public static void updateIdsWithSuffixNested(List<? extends Component> components, String idSuffix) {
 252  0
         for (Component component : components) {
 253  0
             updateIdsWithSuffixNested(component, idSuffix);
 254  
         }
 255  0
     }
 256  
 
 257  
     public static void updateIdsWithSuffixNested(Component component, String idSuffix) {
 258  0
         updateIdsWithSuffix(component, idSuffix);
 259  
 
 260  0
         if (Container.class.isAssignableFrom(component.getClass())) {
 261  0
             LayoutManager layoutManager = ((Container) component).getLayoutManager();
 262  0
             layoutManager.setId(layoutManager.getId() + idSuffix);
 263  
         }
 264  
 
 265  0
         for (Component nested : component.getComponentsForLifecycle()) {
 266  0
             if (nested != null) {
 267  0
                 updateIdsWithSuffixNested(nested, idSuffix);
 268  
             }
 269  
         }
 270  
         
 271  0
         for (Component nested : component.getPropertyReplacerComponents()) {
 272  0
             if (nested != null) {
 273  0
                 updateIdsWithSuffixNested(nested, idSuffix);
 274  
             }
 275  
         }        
 276  0
     }
 277  
 
 278  
     public static void updateIdsWithSuffix(Component component, String idSuffix) {
 279  0
         component.setId(component.getId() + idSuffix);
 280  0
     }
 281  
 
 282  
     public static void setComponentsPropertyDeep(List<? extends Component> components, String propertyPath,
 283  
             Object propertyValue) {
 284  0
         for (Component component : components) {
 285  0
             setComponentPropertyDeep(component, propertyPath, propertyValue);
 286  
         }
 287  0
     }
 288  
 
 289  
     public static void setComponentPropertyDeep(Component component, String propertyPath, Object propertyValue) {
 290  0
         ObjectPropertyUtils.setPropertyValue(component, propertyPath, propertyValue, true);
 291  
 
 292  0
         for (Component nested : component.getComponentsForLifecycle()) {
 293  0
             if (nested != null) {
 294  0
                 setComponentPropertyDeep(nested, propertyPath, propertyValue);
 295  
             }
 296  
         }
 297  0
     }
 298  
 
 299  
     public static List<String> getComponentPropertyNames(Class<? extends Component> componentClass) {
 300  0
         List<String> componentProperties = new ArrayList<String>();
 301  
 
 302  0
         PropertyDescriptor[] properties = BeanUtils.getPropertyDescriptors(componentClass);
 303  0
         for (int i = 0; i < properties.length; i++) {
 304  0
             PropertyDescriptor descriptor = properties[i];
 305  0
             if (descriptor.getReadMethod() != null) {
 306  0
                 componentProperties.add(descriptor.getName());
 307  
             }
 308  
         }
 309  
 
 310  0
         return componentProperties;
 311  
     }
 312  
 
 313  
     public static void pushObjectToContext(List<? extends Component> components, String contextName, Object contextValue) {
 314  0
         for (Component component : components) {
 315  0
             pushObjectToContext(component, contextName, contextValue);
 316  
         }
 317  0
     }
 318  
 
 319  
     public static void pushObjectToContext(Component component, String contextName, Object contextValue) {
 320  0
         if (component == null) {
 321  0
             return;
 322  
         }
 323  
 
 324  0
         component.pushObjectToContext(contextName, contextValue);
 325  
 
 326  
         // special container check so we pick up the layout manager
 327  0
         if (Container.class.isAssignableFrom(component.getClass())) {
 328  0
             LayoutManager layoutManager = ((Container) component).getLayoutManager();
 329  0
             if (layoutManager != null) {
 330  0
                 layoutManager.pushObjectToContext(contextName, contextValue);
 331  
 
 332  0
                 for (Component nestedComponent : layoutManager.getComponentsForLifecycle()) {
 333  0
                     pushObjectToContext(nestedComponent, contextName, contextValue);
 334  
                 }
 335  
             }
 336  
         }
 337  
 
 338  0
         for (Component nestedComponent : component.getComponentsForLifecycle()) {
 339  0
             pushObjectToContext(nestedComponent, contextName, contextValue);
 340  
         }
 341  0
     }
 342  
 
 343  
     public static void updateContextsForLine(List<? extends Component> components, Object collectionLine,
 344  
             int lineIndex) {
 345  0
         for (Component component : components) {
 346  0
             updateContextForLine(component, collectionLine, lineIndex);
 347  
         }
 348  0
     }
 349  
 
 350  
     public static void updateContextForLine(Component component, Object collectionLine, int lineIndex) {
 351  0
         pushObjectToContext(component, UifConstants.ContextVariableNames.LINE, collectionLine);
 352  0
         pushObjectToContext(component, UifConstants.ContextVariableNames.INDEX, new Integer(lineIndex));
 353  
         
 354  0
         boolean isAddLine = (lineIndex == -1);
 355  0
         pushObjectToContext(component, UifConstants.ContextVariableNames.IS_ADD_LINE, isAddLine);
 356  0
     }
 357  
 
 358  
     /**
 359  
      * Performs sorting logic of the given list of <code>Ordered</code>
 360  
      * instances by its order property
 361  
      *
 362  
      * <p>
 363  
      * Items list is sorted based on its order property. Lower order values are
 364  
      * placed higher in the list. If a item does not have a value assigned for
 365  
      * the order (or is equal to the default order of 0), it will be assigned
 366  
      * the a value based on the given order sequence integer. If two or more
 367  
      * items share the same order value, all but the last item found in the list
 368  
      * will be removed.
 369  
      * </p>
 370  
      * 
 371  
      * @param items
 372  
      * @param defaultOrderSequence
 373  
      * @return List<Ordered> sorted items
 374  
      * @see org.kuali.rice.krad.uif.component.Component#getOrder()
 375  
      * @see @see org.springframework.core.Ordered
 376  
      */
 377  
     public static List<? extends Ordered> sort(List<? extends Ordered> items, int defaultOrderSequence) {
 378  0
         List<Ordered> orderedItems = new ArrayList<Ordered>();
 379  
 
 380  
         // do replacement for items with the same order property value
 381  0
         Set<Integer> foundOrders = new HashSet<Integer>();
 382  
 
 383  
         // reverse the list, so items later in the list win
 384  0
         Collections.reverse(items);
 385  0
         for (Ordered component : items) {
 386  0
             int order = component.getOrder();
 387  
 
 388  
             // if order not set just add to list
 389  0
             if (order == 0) {
 390  0
                 orderedItems.add(component);
 391  
             }
 392  
             // check if the order value has been used already
 393  0
             else if (!foundOrders.contains(new Integer(order))) {
 394  0
                 orderedItems.add(component);
 395  0
                 foundOrders.add(new Integer(order));
 396  
             }
 397  0
         }
 398  
 
 399  
         // now reverse the list back so we can assign defaults for items without
 400  
         // an order value
 401  0
         Collections.reverse(items);
 402  0
         for (Ordered component : items) {
 403  0
             int order = component.getOrder();
 404  
 
 405  
             // if order property not set assign default
 406  0
             if (order == 0) {
 407  0
                 defaultOrderSequence++;
 408  0
                 while (foundOrders.contains(new Integer(defaultOrderSequence))) {
 409  0
                     defaultOrderSequence++;
 410  
                 }
 411  0
                 component.setOrder(defaultOrderSequence);
 412  
             }
 413  0
         }
 414  
 
 415  
         // now sort the list by its order property
 416  0
         Collections.sort(orderedItems, new OrderComparator());
 417  
 
 418  0
         return orderedItems;
 419  
     }
 420  
 
 421  
     public static String getLinePathValue(Component component) {
 422  0
         CollectionGroup collectionGroup =
 423  
                 (CollectionGroup) (component.getContext().get(UifConstants.ContextVariableNames.COLLECTION_GROUP));
 424  0
         String linePath = "";
 425  0
         if (collectionGroup != null) {
 426  0
             Object indexObj = component.getContext().get(UifConstants.ContextVariableNames.INDEX);
 427  0
             if (indexObj != null) {
 428  0
                 int index = (Integer) indexObj;
 429  0
                 boolean addLine = false;
 430  0
                 Object addLineObj = component.getContext().get(UifConstants.ContextVariableNames.IS_ADD_LINE);
 431  
 
 432  0
                 if (addLineObj != null) {
 433  0
                     addLine = (Boolean) addLineObj;
 434  
                 }
 435  0
                 if (addLine) {
 436  0
                     linePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
 437  
                 } else {
 438  0
                     linePath = collectionGroup.getBindingInfo().getBindingPath() + "[" + index + "]";
 439  
                 }
 440  
             }
 441  
         }
 442  0
         return linePath;
 443  
     }
 444  
     
 445  
     public static String replaceLineAttr(String statement, String replacement){
 446  0
         if (statement.contains("#line") && StringUtils.isNotEmpty(replacement)) {
 447  0
             statement = statement.replace("#line?", replacement);
 448  0
             statement = statement.replace("#line", replacement);
 449  
         }
 450  0
         return statement;
 451  
     }
 452  
 }