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