Coverage Report - org.kuali.rice.krad.uif.container.ViewIndex
 
Classes in this File Line Coverage Branch Coverage Complexity
ViewIndex
0%
0/48
0%
0/24
2.273
 
 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.container;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.kuali.rice.krad.uif.core.BindingInfo;
 20  
 import org.kuali.rice.krad.uif.core.Component;
 21  
 import org.kuali.rice.krad.uif.field.AttributeField;
 22  
 
 23  
 import java.io.Serializable;
 24  
 import java.util.HashMap;
 25  
 import java.util.Map;
 26  
 
 27  
 /**
 28  
  * Holds field indexes of a <code>View</code> instance for retrieval
 29  
  *
 30  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 31  
  */
 32  
 public class ViewIndex implements Serializable {
 33  
     private static final long serialVersionUID = 4700818801272201371L;
 34  
 
 35  
     private Map<String, Component> index;
 36  
     private Map<String, AttributeField> attributeFieldIndex;
 37  
     private Map<String, CollectionGroup> collectionsIndex;
 38  
 
 39  
     /**
 40  
      * Constructs new instance and performs indexing on View instance
 41  
      *
 42  
      * @param view - view instance to index
 43  
      */
 44  0
     public ViewIndex(View view) {
 45  0
         index(view);
 46  0
     }
 47  
 
 48  
     /**
 49  
      * Walks through the View tree and indexes all components found. All components
 50  
      * are indexed by their IDs with the special indexing done for certain components
 51  
      *
 52  
      * <p>
 53  
      * <code>AttributeField</code> instances are indexed by the attribute path.
 54  
      * This is useful for retrieving the AttributeField based on the incoming
 55  
      * request parameter
 56  
      * </p>
 57  
      *
 58  
      * <p>
 59  
      * <code>CollectionGroup</code> instances are indexed by the collection
 60  
      * path. This is useful for retrieving the CollectionGroup based on the
 61  
      * incoming request parameter
 62  
      * </p>
 63  
      */
 64  
     protected void index(View view) {
 65  0
         index = new HashMap<String, Component>();
 66  0
         attributeFieldIndex = new HashMap<String, AttributeField>();
 67  0
         collectionsIndex = new HashMap<String, CollectionGroup>();
 68  
 
 69  0
         indexComponent(view);
 70  0
     }
 71  
 
 72  
     /**
 73  
      * Adds an entry to the main index for the given component. If the component
 74  
      * is of type <code>AttributeField</code> or <code>CollectionGroup</code> an
 75  
      * entry is created in the corresponding indexes for those types as well. Then
 76  
      * the #indexComponent method is called for each of the component's children
 77  
      *
 78  
      * <p>
 79  
      * If the component is already contained in the indexes, it will be replaced
 80  
      * </p>
 81  
      *
 82  
      * @param component - component instance to index
 83  
      */
 84  
     public void indexComponent(Component component) {
 85  0
         if (component == null) {
 86  0
             return;
 87  
         }
 88  
 
 89  0
         index.put(component.getId(), component);
 90  
 
 91  0
         if (component instanceof AttributeField) {
 92  0
             AttributeField field = (AttributeField) component;
 93  0
             attributeFieldIndex.put(field.getBindingInfo().getBindingPath(), field);
 94  0
         } else if (component instanceof CollectionGroup) {
 95  0
             CollectionGroup collectionGroup = (CollectionGroup) component;
 96  0
             collectionsIndex.put(collectionGroup.getBindingInfo().getBindingPath(), collectionGroup);
 97  
         }
 98  
 
 99  0
         for (Component nestedComponent : component.getNestedComponents()) {
 100  0
             indexComponent(nestedComponent);
 101  
         }
 102  0
     }
 103  
 
 104  
     /**
 105  
      * Retrieves a <code>Component</code> from the view index by Id
 106  
      *
 107  
      * @param id - id for the component to retrieve
 108  
      * @return Component instance found in index, or null if no such component exists
 109  
      */
 110  
     public Component getComponentById(String id) {
 111  0
         return index.get(id);
 112  
     }
 113  
 
 114  
     /**
 115  
      * Retrieves a <code>AttributeField</code> instance from the index
 116  
      *
 117  
      * @param attributePath - full path of the attribute (from the form)
 118  
      * @return AttributeField instance for the path or Null if not found
 119  
      */
 120  
     public AttributeField getAttributeFieldByPath(String attributePath) {
 121  0
         return attributeFieldIndex.get(attributePath);
 122  
     }
 123  
 
 124  
     /**
 125  
      * Retrieves a <code>AttributeField</code> instance that has the given property name
 126  
      * specified (note this is not the full binding path and first match is returned)
 127  
      *
 128  
      * @param propertyName - property name for field to retrieve
 129  
      * @return AttributeField instance found or null if not found
 130  
      */
 131  
     public AttributeField getAttributeFieldByPropertyName(String propertyName) {
 132  0
         AttributeField attributeField = null;
 133  
 
 134  0
         for (AttributeField field : attributeFieldIndex.values()) {
 135  0
             if (StringUtils.equals(propertyName, field.getPropertyName())) {
 136  0
                 attributeField = field;
 137  0
                 break;
 138  
             }
 139  
         }
 140  
 
 141  0
         return attributeField;
 142  
     }
 143  
 
 144  
     /**
 145  
      * Gets the Map that contains attribute field indexing information. The Map
 146  
      * key points to an attribute binding path, and the Map value is the
 147  
      * <code>AttributeField</code> instance
 148  
      *
 149  
      * @return Map<String, AttributeField> attribute fields index map
 150  
      */
 151  
     public Map<String, AttributeField> getAttributeFieldIndex() {
 152  0
         return this.attributeFieldIndex;
 153  
     }
 154  
 
 155  
     /**
 156  
      * Gets the Map that contains collection indexing information. The Map key
 157  
      * gives the binding path to the collection, and the Map value givens the
 158  
      * <code>CollectionGroup</code> instance
 159  
      *
 160  
      * @return Map<String, CollectionGroup> collection index map
 161  
      */
 162  
     public Map<String, CollectionGroup> getCollectionsIndex() {
 163  0
         return this.collectionsIndex;
 164  
     }
 165  
 
 166  
     /**
 167  
      * Retrieves a <code>CollectionGroup</code> instance from the index
 168  
      *
 169  
      * @param collectionPath - full path of the collection (from the form)
 170  
      * @return CollectionGroup instance for the collection path or Null if not
 171  
      *         found
 172  
      */
 173  
     public CollectionGroup getCollectionGroupByPath(String collectionPath) {
 174  0
         return collectionsIndex.get(collectionPath);
 175  
     }
 176  
 
 177  
     /**
 178  
      * Searches for the <code>AttributeField</code> based on the given binding path.
 179  
      *
 180  
      * <p>It first searches for the matching <code>AttributeField</code> by path. If not
 181  
      * matching field found, it searches in the <code>CollectionGroup</code>
 182  
      * </p>
 183  
      *
 184  
      * @param bindingInfo - <code>AttributeField</code> will be searched based on this binding path
 185  
      * @return the attribute field for the binding path
 186  
      */
 187  
     public AttributeField getAttributeField(BindingInfo bindingInfo) {
 188  
         // Find in the attribute index first.
 189  0
         AttributeField attributeField = getAttributeFieldByPath(bindingInfo.getBindingPath());
 190  
 
 191  0
         if (attributeField == null) {
 192  
             // Lets search the collections (by collection's binding path)
 193  0
             String path = bindingInfo.getBindingObjectPath() + "." + bindingInfo.getBindByNamePrefix();
 194  
 
 195  0
             CollectionGroup collectionGroup = getCollectionGroupByPath(stripIndexesFromPropertyPath(path));
 196  0
             if (collectionGroup != null) {
 197  0
                 for (Component item : ((CollectionGroup) collectionGroup).getItems()) {
 198  0
                     if (item instanceof AttributeField) {
 199  0
                         if (StringUtils
 200  
                                 .equals(((AttributeField) item).getPropertyName(), bindingInfo.getBindingName())) {
 201  0
                             attributeField = (AttributeField) item;
 202  0
                             break;
 203  
                         }
 204  
                     }
 205  
                 }
 206  
             }
 207  
         }
 208  
 
 209  0
         return attributeField;
 210  
     }
 211  
 
 212  
     /**
 213  
      * Strips indexes from the property path.
 214  
      *
 215  
      * <p> For example, it returns bo.fiscalOfficer.accounts.name for the input bo.fiscalOfficer.accounts[0].name,
 216  
      * which can be used to find the components from the CollectionGroup index
 217  
      * </p>
 218  
      *
 219  
      * @param propertyPath - property path
 220  
      * @return the stripped index path
 221  
      */
 222  
     private String stripIndexesFromPropertyPath(String propertyPath) {
 223  
 
 224  0
         String returnValue = propertyPath;
 225  0
         String index = StringUtils.substringBetween(propertyPath, "[", "]");
 226  
 
 227  0
         if (StringUtils.isNotBlank(index)) {
 228  0
             returnValue = StringUtils.remove(propertyPath, "[" + index + "]");
 229  0
             return stripIndexesFromPropertyPath(returnValue);
 230  
         } else {
 231  0
             return returnValue;
 232  
         }
 233  
     }
 234  
 }