Coverage Report - org.kuali.rice.kns.uif.container.ViewIndex
 
Classes in this File Line Coverage Branch Coverage Complexity
ViewIndex
0%
0/42
0%
0/20
2.2
 
 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.container;
 17  
 
 18  
 import java.io.Serializable;
 19  
 import java.util.HashMap;
 20  
 import java.util.Map;
 21  
 
 22  
 import org.apache.commons.lang.StringUtils;
 23  
 import org.kuali.rice.kns.uif.core.BindingInfo;
 24  
 import org.kuali.rice.kns.uif.core.Component;
 25  
 import org.kuali.rice.kns.uif.field.AttributeField;
 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
 118  
          *            - full path of the attribute (from the form)
 119  
          * @return AttributeField instance for the path or Null if not found
 120  
          */
 121  
         public AttributeField getAttributeFieldByPath(String attributePath) {
 122  0
                 return attributeFieldIndex.get(attributePath);
 123  
         }
 124  
 
 125  
         /**
 126  
          * Gets the Map that contains attribute field indexing information. The Map
 127  
          * key points to an attribute binding path, and the Map value is the
 128  
          * <code>AttributeField</code> instance
 129  
          * 
 130  
          * @return Map<String, AttributeField> attribute fields index map
 131  
          */
 132  
         public Map<String, AttributeField> getAttributeFieldIndex() {
 133  0
                 return this.attributeFieldIndex;
 134  
         }
 135  
 
 136  
         /**
 137  
          * Gets the Map that contains collection indexing information. The Map key
 138  
          * gives the binding path to the collection, and the Map value givens the
 139  
          * <code>CollectionGroup</code> instance
 140  
          * 
 141  
          * @return Map<String, CollectionGroup> collection index map
 142  
          */
 143  
         public Map<String, CollectionGroup> getCollectionsIndex() {
 144  0
                 return this.collectionsIndex;
 145  
         }
 146  
 
 147  
         /**
 148  
          * Retrieves a <code>CollectionGroup</code> instance from the index
 149  
          * 
 150  
          * @param collectionPath
 151  
          *            - full path of the collection (from the form)
 152  
          * @return CollectionGroup instance for the collection path or Null if not
 153  
          *         found
 154  
          */
 155  
         public CollectionGroup getCollectionGroupByPath(String collectionPath) {
 156  0
                 return collectionsIndex.get(collectionPath);
 157  
         }
 158  
 
 159  
     /**
 160  
      * Searches for the <code>AttributeField</code> based on the given binding path. 
 161  
      * 
 162  
      * <p>It first searches for the matching <code>AttributeField</code> by path. If not
 163  
      * matching field found, it searches in the <code>CollectionGroup</code>
 164  
      * </p>
 165  
      * 
 166  
      * @param bindingInfo - <code>AttributeField</code> will be searched based on this binding path
 167  
      * @return the attribute field for the binding path
 168  
      */
 169  
         public AttributeField getAttributeField(BindingInfo bindingInfo) {
 170  
                 // Find in the attribute index first.
 171  0
                 AttributeField attributeField = getAttributeFieldByPath(bindingInfo.getBindingPath());
 172  
 
 173  0
                 if (attributeField == null) {
 174  
                         // Lets search the collections (by collection's binding path)
 175  0
                         String path = bindingInfo.getBindingObjectPath() + "." + bindingInfo.getBindByNamePrefix();
 176  
 
 177  0
                         CollectionGroup collectionGroup = getCollectionGroupByPath(stripIndexesFromPropertyPath(path));
 178  0
                         if (collectionGroup != null) {
 179  0
                                 for (Component item : ((CollectionGroup) collectionGroup).getItems()) {
 180  0
                                         if (item instanceof AttributeField) {
 181  0
                                                 if (StringUtils.equals(((AttributeField) item).getPropertyName(),bindingInfo.getBindingName())) {
 182  0
                                                         attributeField = (AttributeField) item;
 183  0
                                                         break;
 184  
                                                 }
 185  
                                         }
 186  
                                 }
 187  
                         }
 188  
                 }
 189  
 
 190  0
                 return attributeField;
 191  
         }
 192  
         
 193  
         /**
 194  
      * Strips indexes from the property path.
 195  
      * 
 196  
      * <p> For example, it returns bo.fiscalOfficer.accounts.name for the input bo.fiscalOfficer.accounts[0].name, 
 197  
      * which can be used to find the components from the CollectionGroup index
 198  
      * </p>
 199  
      * 
 200  
      * @param propertyPath - property path
 201  
      * @return the stripped index path
 202  
      */
 203  
     private String stripIndexesFromPropertyPath(String propertyPath){
 204  
             
 205  0
             String returnValue = propertyPath;
 206  0
             String index = StringUtils.substringBetween(propertyPath, "[", "]");
 207  
             
 208  0
             if (StringUtils.isNotBlank(index)){
 209  0
                     returnValue = StringUtils.remove(propertyPath, "[" + index + "]");
 210  0
                     return stripIndexesFromPropertyPath(returnValue);
 211  
             }else{
 212  0
                     return returnValue;
 213  
             }
 214  
     }
 215  
 }