1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.view;
17
18 import java.beans.PropertyEditor;
19 import java.io.Serializable;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Map;
23 import java.util.Map.Entry;
24 import java.util.Set;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.kuali.rice.krad.uif.component.Component;
28 import org.kuali.rice.krad.uif.container.CollectionGroup;
29 import org.kuali.rice.krad.uif.field.DataField;
30 import org.kuali.rice.krad.uif.field.InputField;
31 import org.kuali.rice.krad.uif.util.ComponentUtils;
32 import org.kuali.rice.krad.uif.util.ViewCleaner;
33
34
35
36
37
38
39
40 public class ViewIndex implements Serializable {
41 private static final long serialVersionUID = 4700818801272201371L;
42
43 protected Map<String, Component> index;
44 protected Map<String, DataField> dataFieldIndex;
45
46 protected Map<String, CollectionGroup> collectionsIndex;
47
48 protected Map<String, Component> initialComponentStates;
49
50 protected Map<String, PropertyEditor> fieldPropertyEditors;
51 protected Map<String, PropertyEditor> secureFieldPropertyEditors;
52 protected Map<String, Map<String, String>> componentExpressionGraphs;
53
54 protected Map<String, Map<String, Object>> postContext;
55
56 private Set<String> idsToHoldInIndex;
57 private Set<String> idsToHoldInitialState;
58
59 private Set<String> assignedIds;
60
61
62
63
64 public ViewIndex() {
65 index = new HashMap<String, Component>();
66 dataFieldIndex = new HashMap<String, DataField>();
67 collectionsIndex = new HashMap<String, CollectionGroup>();
68 initialComponentStates = new HashMap<String, Component>();
69 fieldPropertyEditors = new HashMap<String, PropertyEditor>();
70 secureFieldPropertyEditors = new HashMap<String, PropertyEditor>();
71 componentExpressionGraphs = new HashMap<String, Map<String, String>>();
72 postContext = new HashMap<String, Map<String, Object>>();
73 idsToHoldInIndex = new HashSet<String>();
74 idsToHoldInitialState = new HashSet<String>();
75 assignedIds = new HashSet<String>();
76 }
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 protected void index(View view) {
93 index = new HashMap<String, Component>();
94 dataFieldIndex = new HashMap<String, DataField>();
95 collectionsIndex = new HashMap<String, CollectionGroup>();
96 fieldPropertyEditors = new HashMap<String, PropertyEditor>();
97 secureFieldPropertyEditors = new HashMap<String, PropertyEditor>();
98
99 indexComponent(view);
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 public void indexComponent(Component component) {
120 if (component == null) {
121 return;
122 }
123
124 synchronized (index) {
125 index.put(component.getId(), component);
126 }
127
128 if (component instanceof DataField) {
129 DataField field = (DataField) component;
130 synchronized (dataFieldIndex) {
131 dataFieldIndex.put(field.getBindingInfo().getBindingPath(), field);
132 }
133
134
135 if (component.isRender()) {
136 if (field.hasSecureValue()) {
137 synchronized (secureFieldPropertyEditors) {
138 secureFieldPropertyEditors.put(field.getBindingInfo().getBindingPath(),
139 field.getPropertyEditor());
140 }
141 } else {
142 synchronized (fieldPropertyEditors) {
143 fieldPropertyEditors.put(field.getBindingInfo().getBindingPath(), field.getPropertyEditor());
144 }
145 }
146 }
147 } else if (component instanceof CollectionGroup) {
148 CollectionGroup collectionGroup = (CollectionGroup) component;
149 synchronized (collectionsIndex) {
150 collectionsIndex.put(collectionGroup.getBindingInfo().getBindingPath(), collectionGroup);
151 }
152 }
153
154 for (Component nestedComponent : component.getComponentsForLifecycle()) {
155 indexComponent(nestedComponent);
156 }
157 }
158
159
160
161
162
163 public void clearIndexesAfterRender() {
164
165
166 for (Component component : index.values()) {
167 if (component == null) {
168 continue;
169 }
170
171 if (component.isDisableSessionPersistence()) {
172 continue;
173 }
174
175 if (component.isForceSessionPersistence() || canBeRefreshed(component) ||
176
177
178 (component instanceof CollectionGroup)) {
179 synchronized (idsToHoldInitialState) {
180 idsToHoldInitialState.add(component.getBaseId());
181 }
182 synchronized (idsToHoldInIndex) {
183 idsToHoldInIndex.add(component.getId());
184 }
185 }
186 else if ((component instanceof InputField)) {
187 InputField inputField = (InputField) component;
188
189 if ((inputField.getAttributeQuery() != null) || ((inputField.getSuggest() != null) && inputField
190 .getSuggest().isRender())) {
191 synchronized (idsToHoldInIndex) {
192 idsToHoldInIndex.add(component.getId());
193 }
194 }
195 }
196 }
197
198
199 Map<String, Component> holdInitialComponentStates = new HashMap<String, Component>();
200 synchronized (initialComponentStates) {
201 for (Entry<String, Component> factoryEntry : initialComponentStates.entrySet()) {
202 if (idsToHoldInitialState.contains(factoryEntry.getKey())) {
203 holdInitialComponentStates.put(factoryEntry.getKey(), factoryEntry.getValue());
204 }
205 }
206 }
207 initialComponentStates = holdInitialComponentStates;
208
209 Map<String, Component> holdComponentStates = new HashMap<String, Component>();
210 synchronized (index) {
211 for (Entry<String, Component> indexEntry : index.entrySet()) {
212 if (idsToHoldInIndex.contains(indexEntry.getKey())) {
213 Component component = indexEntry.getValue();
214
215
216 if ((component.getRefreshExpressionGraph() != null) && !component.getRefreshExpressionGraph()
217 .isEmpty()) {
218 synchronized (componentExpressionGraphs) {
219 componentExpressionGraphs.put(component.getBaseId(), component.getRefreshExpressionGraph());
220 }
221 }
222
223 ViewCleaner.cleanComponent(component, this);
224
225 holdComponentStates.put(indexEntry.getKey(), component);
226 }
227 }
228 }
229 index = holdComponentStates;
230
231 for (CollectionGroup collectionGroup : collectionsIndex.values()) {
232 ViewCleaner.cleanComponent(collectionGroup, this);
233 }
234
235 dataFieldIndex.clear();
236 assignedIds.clear();
237 }
238
239
240
241
242
243
244
245 protected boolean canBeRefreshed(Component component) {
246 boolean canBeRefreshed = false;
247
248 boolean hasRefreshCondition = StringUtils.isNotBlank(component.getProgressiveRender()) ||
249 StringUtils.isNotBlank(component.getConditionalRefresh()) || (component.getRefreshTimer() > 0) ||
250 (component.getRefreshWhenChangedPropertyNames() != null && !component
251 .getRefreshWhenChangedPropertyNames().isEmpty());
252
253 canBeRefreshed = hasRefreshCondition || component.isRefreshedByAction() || component.isDisclosedByAction();
254
255 return canBeRefreshed;
256 }
257
258
259
260
261
262
263
264
265 public boolean isIdForRefreshComponent(String componentId) {
266 return idsToHoldInIndex != null && idsToHoldInIndex.contains(componentId);
267 }
268
269
270
271
272
273
274
275 public Component getComponentById(String id) {
276 return index.get(id);
277 }
278
279
280
281
282
283
284
285 public DataField getDataFieldByPath(String propertyPath) {
286 return dataFieldIndex.get(propertyPath);
287 }
288
289
290
291
292
293
294
295
296 public DataField getDataFieldByPropertyName(String propertyName) {
297 DataField dataField = null;
298
299 for (DataField field : dataFieldIndex.values()) {
300 if (StringUtils.equals(propertyName, field.getPropertyName())) {
301 dataField = field;
302 break;
303 }
304 }
305
306 return dataField;
307 }
308
309
310
311
312
313
314
315 public Map<String, DataField> getDataFieldIndex() {
316 return this.dataFieldIndex;
317 }
318
319
320
321
322
323
324
325 public Map<String, CollectionGroup> getCollectionsIndex() {
326 return this.collectionsIndex;
327 }
328
329
330
331
332
333
334
335 public CollectionGroup getCollectionGroupByPath(String collectionPath) {
336 return collectionsIndex.get(collectionPath);
337 }
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357 public Map<String, Component> getInitialComponentStates() {
358 return initialComponentStates;
359 }
360
361
362
363
364
365
366
367
368
369
370
371
372 public void addInitialComponentStateIfNeeded(Component component) {
373 if (StringUtils.isBlank(component.getBaseId())) {
374 component.setBaseId(component.getId());
375 synchronized (initialComponentStates) {
376 initialComponentStates.put(component.getBaseId(), ComponentUtils.copy(component));
377 }
378 }
379 }
380
381
382
383
384
385
386 public void setInitialComponentStates(Map<String, Component> initialComponentStates) {
387 this.initialComponentStates = initialComponentStates;
388 }
389
390
391
392
393
394
395
396
397
398
399
400
401
402 public Map<String, PropertyEditor> getFieldPropertyEditors() {
403 return fieldPropertyEditors;
404 }
405
406
407
408
409
410
411
412
413
414
415
416
417
418 public Map<String, PropertyEditor> getSecureFieldPropertyEditors() {
419 return secureFieldPropertyEditors;
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438 public Map<String, Map<String, String>> getComponentExpressionGraphs() {
439 return componentExpressionGraphs;
440 }
441
442
443
444
445
446
447
448
449
450
451
452
453
454 public Map<String, Map<String, Object>> getPostContext() {
455 return postContext;
456 }
457
458
459
460
461
462
463
464
465 public void addPostContextEntry(String componentId, String entryKey, Object entryValue) {
466 Map<String, Object> componentContext = null;
467
468 if (postContext.containsKey(componentId)) {
469 componentContext = postContext.get(componentId);
470 } else {
471 componentContext = new HashMap<String, Object>();
472 synchronized (postContext) {
473 postContext.put(componentId, componentContext);
474 }
475 }
476
477 synchronized (postContext) {
478 componentContext.put(entryKey, entryValue);
479 }
480 }
481
482
483
484
485
486
487
488
489 public boolean observeAssignedId(String id) {
490 if (assignedIds.contains(id)) {
491 return false;
492 }
493
494 synchronized (assignedIds) {
495 return assignedIds.add(id);
496 }
497 }
498
499
500
501
502
503
504
505
506 public Object getPostContextEntry(String componentId, String entryKey) {
507 Object entryValue = null;
508
509 Map<String, Object> componentContext = null;
510
511 if (postContext.containsKey(componentId)) {
512 componentContext = postContext.get(componentId);
513
514 entryValue = componentContext.get(entryKey);
515 }
516
517 return entryValue;
518 }
519
520
521
522
523
524
525 public ViewIndex copy() {
526 ViewIndex viewIndexCopy = new ViewIndex();
527
528 if (this.index != null) {
529 Map<String, Component> indexCopy = new HashMap<String, Component>();
530 for (Map.Entry<String, Component> indexEntry : this.index.entrySet()) {
531 indexCopy.put(indexEntry.getKey(), (Component) indexEntry.getValue().copy());
532 }
533
534 viewIndexCopy.index = indexCopy;
535 }
536
537 if (this.dataFieldIndex != null) {
538 Map<String, DataField> dataFieldIndexCopy = new HashMap<String, DataField>();
539 for (Map.Entry<String, DataField> indexEntry : this.dataFieldIndex.entrySet()) {
540 dataFieldIndexCopy.put(indexEntry.getKey(), (DataField) indexEntry.getValue().copy());
541 }
542
543 viewIndexCopy.dataFieldIndex = dataFieldIndexCopy;
544 }
545
546 if (this.collectionsIndex != null) {
547 Map<String, CollectionGroup> collectionsIndexCopy = new HashMap<String, CollectionGroup>();
548 for (Map.Entry<String, CollectionGroup> indexEntry : this.collectionsIndex.entrySet()) {
549 collectionsIndexCopy.put(indexEntry.getKey(), (CollectionGroup) indexEntry.getValue().copy());
550 }
551
552 viewIndexCopy.collectionsIndex = collectionsIndexCopy;
553 }
554
555 if (this.initialComponentStates != null) {
556 Map<String, Component> initialComponentStatesCopy = new HashMap<String, Component>();
557 for (Map.Entry<String, Component> indexEntry : this.initialComponentStates.entrySet()) {
558 initialComponentStatesCopy.put(indexEntry.getKey(), (Component) indexEntry.getValue().copy());
559 }
560
561 viewIndexCopy.initialComponentStates = initialComponentStatesCopy;
562 }
563
564 if (this.fieldPropertyEditors != null) {
565 viewIndexCopy.fieldPropertyEditors = new HashMap<String, PropertyEditor>(this.fieldPropertyEditors);
566 }
567
568 if (this.secureFieldPropertyEditors != null) {
569 viewIndexCopy.secureFieldPropertyEditors = new HashMap<String, PropertyEditor>(
570 this.secureFieldPropertyEditors);
571 }
572
573 if (this.componentExpressionGraphs != null) {
574 viewIndexCopy.componentExpressionGraphs = new HashMap<String, Map<String, String>>(
575 this.componentExpressionGraphs);
576 }
577
578 if (this.postContext != null) {
579 viewIndexCopy.postContext = new HashMap<String, Map<String, Object>>(this.postContext);
580 }
581
582 return viewIndexCopy;
583 }
584
585 }