Coverage Report - org.kuali.rice.krad.datadictionary.UifDictionaryIndex
 
Classes in this File Line Coverage Branch Coverage Complexity
UifDictionaryIndex
0%
0/64
0%
0/22
2.778
 
 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.datadictionary;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.apache.commons.logging.Log;
 20  
 import org.apache.commons.logging.LogFactory;
 21  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 22  
 import org.kuali.rice.krad.uif.container.View;
 23  
 import org.kuali.rice.krad.uif.core.Component;
 24  
 import org.kuali.rice.krad.uif.service.ViewTypeService;
 25  
 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
 26  
 
 27  
 import java.util.ArrayList;
 28  
 import java.util.HashMap;
 29  
 import java.util.List;
 30  
 import java.util.Map;
 31  
 import java.util.Map.Entry;
 32  
 
 33  
 /**
 34  
  * Indexes <code>View</code> bean entries for retrieval
 35  
  * 
 36  
  * <p>
 37  
  * This is used to retrieve a <code>View</code> instance by its unique id.
 38  
  * Furthermore, view of certain types (that have a <code>ViewTypeService</code>
 39  
  * are indexed by their type to support retrieval of views based on parameters.
 40  
  * </p>
 41  
  * 
 42  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 43  
  */
 44  
 public class UifDictionaryIndex implements Runnable {
 45  0
         private static final Log LOG = LogFactory.getLog(UifDictionaryIndex.class);
 46  
 
 47  
         private DefaultListableBeanFactory ddBeans;
 48  
 
 49  
         // view entries keyed by view id with value the spring bean name
 50  
         private Map<String, String> viewBeanEntriesById;
 51  
         
 52  
         // view entries keyed by bean name with value the view prototype
 53  
         private Map<String, View> viewEntriesByBean;
 54  
 
 55  
         // view entries indexed by type
 56  
         private Map<String, ViewTypeDictionaryIndex> viewEntriesByType;
 57  
 
 58  0
         public UifDictionaryIndex(DefaultListableBeanFactory ddBeans) {
 59  0
                 this.ddBeans = ddBeans;
 60  0
         }
 61  
 
 62  
         public void run() {
 63  0
                 LOG.info("Starting View Index Building");
 64  0
                 buildViewIndicies();
 65  0
                 LOG.info("Completed View Index Building");
 66  0
         }
 67  
 
 68  
         /**
 69  
          * Retrieves the View instance with the given id from the bean factory.
 70  
          * Since View instances are stateful, we need to get a new instance from
 71  
          * Spring each time.
 72  
          * 
 73  
          * @param viewId
 74  
          *            - the unique id for the view
 75  
          * @return <code>View</code> instance
 76  
          */
 77  
         public View getViewById(String viewId) {
 78  0
                 String beanName = viewBeanEntriesById.get(viewId);
 79  0
                 if (StringUtils.isBlank(beanName)) {
 80  0
                         throw new DataDictionaryException("Unable to find View with id: " + viewId);
 81  
                 }
 82  
 
 83  0
                 return ddBeans.getBean(beanName, View.class);
 84  
         }
 85  
 
 86  
         /**
 87  
          * Retrieves a <code>View</code> instance that is of the given type based on
 88  
          * the index key
 89  
          * 
 90  
          * @param viewTypeName
 91  
          *            - type name for the view
 92  
          * @param indexKey
 93  
          *            - Map of index key parameters, these are the parameters the
 94  
          *            indexer used to index the view initially and needs to identify
 95  
          *            an unique view instance
 96  
          * @return View instance that matches the given index or Null if one is not
 97  
          *         found
 98  
          */
 99  
         public View getViewByTypeIndex(String viewTypeName, Map<String, String> indexKey) {
 100  0
                 String index = buildTypeIndex(indexKey);
 101  
 
 102  0
                 ViewTypeDictionaryIndex typeIndex = getTypeIndex(viewTypeName);
 103  
 
 104  0
                 String beanName = typeIndex.get(index);
 105  0
                 if (StringUtils.isBlank(beanName)) {
 106  0
                         throw new DataDictionaryException("Unable to find View with index: " + index);
 107  
                 }
 108  
 
 109  0
                 return ddBeans.getBean(beanName, View.class);
 110  
         }
 111  
 
 112  
         /**
 113  
          * Gets all <code>View</code> prototypes configured for the given view type
 114  
          * name
 115  
          * 
 116  
          * @param viewTypeName
 117  
          *            - view type name to retrieve
 118  
          * @return List<View> view prototypes with the given type name, or empty
 119  
          *         list
 120  
          */
 121  
         public List<View> getViewsForType(String viewTypeName) {
 122  0
                 List<View> typeViews = new ArrayList<View>();
 123  
 
 124  
                 // get view ids for the type
 125  0
                 if (viewEntriesByType.containsKey(viewTypeName)) {
 126  0
                         ViewTypeDictionaryIndex typeIndex = viewEntriesByType.get(viewTypeName);
 127  0
                         for (Entry<String, String> typeEntry : typeIndex.getViewIndex().entrySet()) {
 128  
                                 // get the view prototype by bean name
 129  0
                                 if (viewEntriesByBean.containsKey(typeEntry.getValue())) {
 130  0
                                         View typeView = viewEntriesByBean.get(typeEntry.getValue());
 131  0
                                         typeViews.add(typeView);
 132  0
                                 }
 133  
                         }
 134  0
                 }
 135  
                 else {
 136  0
                         throw new DataDictionaryException("Unable to find view index for type: " + viewTypeName);
 137  
                 }
 138  
 
 139  0
                 return typeViews;
 140  
         }
 141  
 
 142  
         /**
 143  
          * Initializes the view index <code>Map</code> then iterates through all the
 144  
          * beans in the factory that implement <code>View</code>, adding them to the
 145  
          * index
 146  
          */
 147  
         protected void buildViewIndicies() {
 148  0
                 viewBeanEntriesById = new HashMap<String, String>();
 149  0
                 viewEntriesByBean = new HashMap<String, View>();
 150  0
                 viewEntriesByType = new HashMap<String, ViewTypeDictionaryIndex>();
 151  
 
 152  0
                 Map<String, View> viewBeans = ddBeans.getBeansOfType(View.class);
 153  0
                 for (String beanName : viewBeans.keySet()) {
 154  0
                         View view = viewBeans.get(beanName);
 155  0
                         if (viewBeanEntriesById.containsKey(view.getId())) {
 156  0
                                 throw new DataDictionaryException("Two views must not share the same id. Found duplicate id: "
 157  
                                                 + view.getId());
 158  
                         }
 159  
                         
 160  0
                         viewBeanEntriesById.put(view.getId(), beanName);
 161  0
                         viewEntriesByBean.put(beanName, view);
 162  
 
 163  0
                         indexViewForType(view, beanName);
 164  0
                 }
 165  
 
 166  
         // trigger a load of all component so they will get indexed in the component factory
 167  0
         Map<String, Component> componentBeans = ddBeans.getBeansOfType(Component.class);
 168  0
         }
 169  
 
 170  
         /**
 171  
          * Performs additional indexing based on the view type associated with the
 172  
          * view instance. The <code>ViewTypeService</code> associated with the view
 173  
          * type name on the instance is invoked to retrieve the parameter key/value
 174  
          * pairs from the view instance, which are then used to build up an index
 175  
          * which will key the entry
 176  
          * 
 177  
          * @param view
 178  
          *            - view instance to index
 179  
          * @param beanName
 180  
          *            - name of the view's bean in Spring
 181  
          */
 182  
         protected void indexViewForType(View view, String beanName) {
 183  0
                 String viewType = view.getViewTypeName();
 184  
 
 185  0
                 ViewTypeService typeService = KRADServiceLocatorWeb.getViewService().getViewTypeService(viewType);
 186  0
                 if (typeService == null) {
 187  
                         // don't do any further indexing
 188  0
                         return;
 189  
                 }
 190  
 
 191  
                 // invoke type service to retrieve it parameter name/value pairs from
 192  
                 // the view
 193  0
                 Map<String, String> typeParameters = typeService.getParametersFromView(view);
 194  
 
 195  
                 // build the index string from the parameters
 196  0
                 String index = buildTypeIndex(typeParameters);
 197  
 
 198  
                 // get the index for the type and add the view entry
 199  0
                 ViewTypeDictionaryIndex typeIndex = getTypeIndex(viewType);
 200  
 
 201  0
                 typeIndex.put(index, beanName);
 202  0
         }
 203  
 
 204  
         /**
 205  
          * Retrieves the <code>ViewTypeDictionaryIndex</code> instance for the given
 206  
          * view type name. If one does not exist yet for the given name, a new
 207  
          * instance is created
 208  
          * 
 209  
          * @param viewType
 210  
          *            - name of the view type to retrieve index for
 211  
          * @return ViewTypeDictionaryIndex instance
 212  
          */
 213  
         protected ViewTypeDictionaryIndex getTypeIndex(String viewType) {
 214  0
                 ViewTypeDictionaryIndex typeIndex = null;
 215  
 
 216  0
                 if (viewEntriesByType.containsKey(viewType)) {
 217  0
                         typeIndex = viewEntriesByType.get(viewType);
 218  
                 }
 219  
                 else {
 220  0
                         typeIndex = new ViewTypeDictionaryIndex();
 221  0
                         viewEntriesByType.put(viewType, typeIndex);
 222  
                 }
 223  
 
 224  0
                 return typeIndex;
 225  
         }
 226  
 
 227  
         /**
 228  
          * Builds up an index string from the given Map of parameters
 229  
          * 
 230  
          * @param typeParameters
 231  
          *            - Map of parameters to use for index
 232  
          * @return String index
 233  
          */
 234  
         protected String buildTypeIndex(Map<String, String> typeParameters) {
 235  0
                 String index = "";
 236  
 
 237  0
                 for (String parameterName : typeParameters.keySet()) {
 238  0
                         if (StringUtils.isNotBlank(index)) {
 239  0
                                 index += "|||";
 240  
                         }
 241  0
                         index += parameterName + "^^" + typeParameters.get(parameterName);
 242  
                 }
 243  
 
 244  0
                 return index;
 245  
         }
 246  
 
 247  
 }