| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| ViewDictionaryIndex |
|
| 2.7777777777777777;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.view; | |
| 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.service.ViewTypeService; | |
| 31 | import org.springframework.beans.factory.support.DefaultListableBeanFactory; | |
| 32 | ||
| 33 | /** | |
| 34 | * Indexes <code>View</code> bean entries for retrieval | |
| 35 | * | |
| 36 | * <p> | |
| 37 | * Builds up a Map index where the key is the view id, and the value is the bean | |
| 38 | * name. 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 ViewDictionaryIndex implements Runnable { | |
| 46 | 0 | private static final Log LOG = LogFactory.getLog(ViewDictionaryIndex.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 ViewDictionaryIndex(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 | 0 | } |
| 167 | ||
| 168 | /** | |
| 169 | * Performs additional indexing based on the view type associated with the | |
| 170 | * view instance. The <code>ViewTypeService</code> associated with the view | |
| 171 | * type name on the instance is invoked to retrieve the parameter key/value | |
| 172 | * pairs from the view instance, which are then used to build up an index | |
| 173 | * which will key the entry | |
| 174 | * | |
| 175 | * @param view | |
| 176 | * - view instance to index | |
| 177 | * @param beanName | |
| 178 | * - name of the view's bean in Spring | |
| 179 | */ | |
| 180 | protected void indexViewForType(View view, String beanName) { | |
| 181 | 0 | String viewType = view.getViewTypeName(); |
| 182 | ||
| 183 | 0 | ViewTypeService typeService = KNSServiceLocatorWeb.getViewService().getViewTypeService(viewType); |
| 184 | 0 | if (typeService == null) { |
| 185 | // don't do any further indexing | |
| 186 | 0 | return; |
| 187 | } | |
| 188 | ||
| 189 | // invoke type service to retrieve it parameter name/value pairs from | |
| 190 | // the view | |
| 191 | 0 | Map<String, String> typeParameters = typeService.getParametersFromView(view); |
| 192 | ||
| 193 | // build the index string from the parameters | |
| 194 | 0 | String index = buildTypeIndex(typeParameters); |
| 195 | ||
| 196 | // get the index for the type and add the view entry | |
| 197 | 0 | ViewTypeDictionaryIndex typeIndex = getTypeIndex(viewType); |
| 198 | ||
| 199 | 0 | typeIndex.put(index, beanName); |
| 200 | 0 | } |
| 201 | ||
| 202 | /** | |
| 203 | * Retrieves the <code>ViewTypeDictionaryIndex</code> instance for the given | |
| 204 | * view type name. If one does not exist yet for the given name, a new | |
| 205 | * instance is created | |
| 206 | * | |
| 207 | * @param viewType | |
| 208 | * - name of the view type to retrieve index for | |
| 209 | * @return ViewTypeDictionaryIndex instance | |
| 210 | */ | |
| 211 | protected ViewTypeDictionaryIndex getTypeIndex(String viewType) { | |
| 212 | 0 | ViewTypeDictionaryIndex typeIndex = null; |
| 213 | ||
| 214 | 0 | if (viewEntriesByType.containsKey(viewType)) { |
| 215 | 0 | typeIndex = viewEntriesByType.get(viewType); |
| 216 | } | |
| 217 | else { | |
| 218 | 0 | typeIndex = new ViewTypeDictionaryIndex(); |
| 219 | 0 | viewEntriesByType.put(viewType, typeIndex); |
| 220 | } | |
| 221 | ||
| 222 | 0 | return typeIndex; |
| 223 | } | |
| 224 | ||
| 225 | /** | |
| 226 | * Builds up an index string from the given Map of parameters | |
| 227 | * | |
| 228 | * @param typeParameters | |
| 229 | * - Map of parameters to use for index | |
| 230 | * @return String index | |
| 231 | */ | |
| 232 | protected String buildTypeIndex(Map<String, String> typeParameters) { | |
| 233 | 0 | String index = ""; |
| 234 | ||
| 235 | 0 | for (String parameterName : typeParameters.keySet()) { |
| 236 | 0 | if (StringUtils.isNotBlank(index)) { |
| 237 | 0 | index += "|||"; |
| 238 | } | |
| 239 | 0 | index += parameterName + "^^" + typeParameters.get(parameterName); |
| 240 | } | |
| 241 | ||
| 242 | 0 | return index; |
| 243 | } | |
| 244 | ||
| 245 | } |