1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.datadictionary.uif;
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.core.api.config.property.ConfigContext;
22 import org.kuali.rice.krad.datadictionary.DataDictionaryException;
23 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
24 import org.kuali.rice.krad.uif.UifConstants;
25 import org.kuali.rice.krad.uif.UifConstants.ViewType;
26 import org.kuali.rice.krad.uif.service.ViewTypeService;
27 import org.kuali.rice.krad.uif.util.ViewModelUtils;
28 import org.kuali.rice.krad.uif.view.View;
29 import org.kuali.rice.krad.util.KRADConstants;
30 import org.springframework.beans.PropertyValues;
31 import org.springframework.beans.factory.config.BeanDefinition;
32 import org.springframework.beans.factory.support.KualiDefaultListableBeanFactory;
33
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Map.Entry;
39 import java.util.concurrent.ExecutorService;
40 import java.util.concurrent.Executors;
41
42
43
44
45
46
47
48
49
50
51
52
53 public class UifDictionaryIndex implements Runnable {
54 private static final Log LOG = LogFactory.getLog(UifDictionaryIndex.class);
55
56 private KualiDefaultListableBeanFactory ddBeans;
57
58
59 private Map<String, String> viewBeanEntriesById;
60
61
62 private Map<String, ViewTypeDictionaryIndex> viewEntriesByType;
63
64
65 private Map<String, UifViewPool> viewPools;
66
67
68 private static final int THREADS = 4;
69 private boolean poolSizeSet;
70 private Integer threadPoolSize;
71
72 public UifDictionaryIndex(KualiDefaultListableBeanFactory ddBeans) {
73 this.ddBeans = ddBeans;
74 }
75
76 @Override
77 public void run() {
78 LOG.info("Starting View Index Building");
79 try {
80 Integer size = new Integer(ConfigContext.getCurrentContextConfig().getProperty(
81 KRADConstants.KRAD_DICTIONARY_INDEX_POOL_SIZE));
82 threadPoolSize = size;
83 poolSizeSet = true;
84 } catch (NumberFormatException nfe) {
85
86 }
87 buildViewIndicies();
88 LOG.info("Completed View Index Building");
89 }
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104 public View getViewById(final String viewId) {
105
106 if (viewPools.containsKey(viewId)) {
107
108 final UifViewPool viewPool = viewPools.get(viewId);
109 synchronized (viewPool) {
110 if (!viewPool.isEmpty()) {
111 View view = viewPool.getViewInstance();
112
113
114 Runnable createView = new Runnable() {
115 public void run() {
116 View newViewInstance = getViewInstanceFromFactory(viewId);
117 viewPool.addViewInstance(newViewInstance);
118 }
119 };
120
121 Thread t = new Thread(createView);
122 t.start();
123
124 return view;
125 } else {
126 LOG.info("Pool size for view with id: "
127 + viewId
128 + " is empty. Considering increasing max pool size.");
129 }
130 }
131 }
132
133
134 return getViewInstanceFromFactory(viewId);
135 }
136
137
138
139
140
141
142
143
144 protected View getViewInstanceFromFactory(String viewId) {
145 String beanName = viewBeanEntriesById.get(viewId);
146 if (StringUtils.isBlank(beanName)) {
147 throw new DataDictionaryException("Unable to find View with id: " + viewId);
148 }
149
150 return ddBeans.getBean(beanName, View.class);
151 }
152
153
154
155
156
157
158
159
160
161
162
163
164 public View getViewByTypeIndex(ViewType viewTypeName, Map<String, String> indexKey) {
165 String index = buildTypeIndex(indexKey);
166
167 ViewTypeDictionaryIndex typeIndex = getTypeIndex(viewTypeName);
168
169 String viewId = typeIndex.get(index);
170 if (StringUtils.isNotBlank(viewId)) {
171 return getViewById(viewId);
172 }
173
174 return null;
175 }
176
177
178
179
180
181
182
183
184
185 public boolean viewByTypeExist(ViewType viewTypeName, Map<String, String> indexKey) {
186 boolean viewExist = false;
187
188 String index = buildTypeIndex(indexKey);
189 ViewTypeDictionaryIndex typeIndex = getTypeIndex(viewTypeName);
190
191 String viewId = typeIndex.get(index);
192 if (StringUtils.isNotBlank(viewId)) {
193 viewExist = true;
194 }
195
196 return viewExist;
197 }
198
199
200
201
202
203
204
205
206
207
208
209
210 public PropertyValues getViewPropertiesById(String viewId) {
211 String beanName = viewBeanEntriesById.get(viewId);
212 if (StringUtils.isBlank(beanName)) {
213 BeanDefinition beanDefinition = ddBeans.getMergedBeanDefinition(beanName);
214
215 return beanDefinition.getPropertyValues();
216 }
217
218 return null;
219 }
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 public PropertyValues getViewPropertiesByType(ViewType viewTypeName, Map<String, String> indexKey) {
236 String index = buildTypeIndex(indexKey);
237
238 ViewTypeDictionaryIndex typeIndex = getTypeIndex(viewTypeName);
239
240 String beanName = typeIndex.get(index);
241 if (StringUtils.isNotBlank(beanName)) {
242 BeanDefinition beanDefinition = ddBeans.getMergedBeanDefinition(beanName);
243
244 return beanDefinition.getPropertyValues();
245 }
246
247 return null;
248 }
249
250
251
252
253
254
255
256
257
258 public List<View> getViewsForType(ViewType viewTypeName) {
259 List<View> typeViews = new ArrayList<View>();
260
261
262 if (viewEntriesByType.containsKey(viewTypeName.name())) {
263 ViewTypeDictionaryIndex typeIndex = viewEntriesByType.get(viewTypeName.name());
264 for (Entry<String, String> typeEntry : typeIndex.getViewIndex().entrySet()) {
265 View typeView = ddBeans.getBean(typeEntry.getValue(), View.class);
266 typeViews.add(typeView);
267 }
268 } else {
269 throw new DataDictionaryException("Unable to find view index for type: " + viewTypeName);
270 }
271
272 return typeViews;
273 }
274
275
276
277
278
279
280 protected void buildViewIndicies() {
281 viewBeanEntriesById = new HashMap<String, String>();
282 viewEntriesByType = new HashMap<String, ViewTypeDictionaryIndex>();
283 viewPools = new HashMap<String, UifViewPool>();
284
285 int threads = THREADS;
286
287 if (poolSizeSet) {
288 threads = threadPoolSize;
289 }
290
291 ExecutorService executor = Executors.newFixedThreadPool(threads);
292
293 String[] beanNames = ddBeans.getBeanNamesForType(View.class);
294 for (final String beanName : beanNames) {
295 BeanDefinition beanDefinition = ddBeans.getMergedBeanDefinition(beanName);
296 PropertyValues propertyValues = beanDefinition.getPropertyValues();
297
298 String id = ViewModelUtils.getStringValFromPVs(propertyValues, "id");
299 if (StringUtils.isBlank(id)) {
300 id = beanName;
301 }
302
303 if (viewBeanEntriesById.containsKey(id)) {
304 throw new DataDictionaryException("Two views must not share the same id. Found duplicate id: " + id);
305 }
306 viewBeanEntriesById.put(id, beanName);
307
308 indexViewForType(propertyValues, id);
309
310
311 String poolSizeStr = ViewModelUtils.getStringValFromPVs(propertyValues, "preloadPoolSize");
312 if (StringUtils.isNotBlank(poolSizeStr)) {
313 int poolSize = Integer.parseInt(poolSizeStr);
314 if (poolSize < 1) {
315 continue;
316 }
317
318 final UifViewPool viewPool = new UifViewPool();
319 viewPool.setMaxSize(poolSize);
320 for (int j = 0; j < poolSize; j++) {
321 Runnable createView = new Runnable() {
322 @Override
323 public void run() {
324 View view = (View) ddBeans.getBean(beanName);
325 viewPool.addViewInstance(view);
326 }
327 };
328
329 executor.execute(createView);
330 }
331 viewPools.put(id, viewPool);
332 }
333 }
334 executor.shutdown();
335 }
336
337
338
339
340
341
342
343
344
345
346 protected void indexViewForType(PropertyValues propertyValues, String id) {
347 String viewTypeName = ViewModelUtils.getStringValFromPVs(propertyValues, "viewTypeName");
348 if (StringUtils.isBlank(viewTypeName)) {
349 return;
350 }
351
352 UifConstants.ViewType viewType = ViewType.valueOf(viewTypeName);
353
354 ViewTypeService typeService = KRADServiceLocatorWeb.getViewService().getViewTypeService(viewType);
355 if (typeService == null) {
356
357 return;
358 }
359
360
361 Map<String, String> typeParameters = typeService.getParametersFromViewConfiguration(propertyValues);
362
363
364 String index = buildTypeIndex(typeParameters);
365
366
367 ViewTypeDictionaryIndex typeIndex = getTypeIndex(viewType);
368
369 typeIndex.put(index, id);
370 }
371
372
373
374
375
376
377
378
379
380 protected ViewTypeDictionaryIndex getTypeIndex(UifConstants.ViewType viewType) {
381 ViewTypeDictionaryIndex typeIndex = null;
382
383 if (viewEntriesByType.containsKey(viewType.name())) {
384 typeIndex = viewEntriesByType.get(viewType.name());
385 } else {
386 typeIndex = new ViewTypeDictionaryIndex();
387 viewEntriesByType.put(viewType.name(), typeIndex);
388 }
389
390 return typeIndex;
391 }
392
393
394
395
396
397
398
399 protected String buildTypeIndex(Map<String, String> typeParameters) {
400 String index = "";
401
402 for (String parameterName : typeParameters.keySet()) {
403 if (StringUtils.isNotBlank(index)) {
404 index += "|||";
405 }
406 index += parameterName + "^^" + typeParameters.get(parameterName);
407 }
408
409 return index;
410 }
411
412 }