1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.container;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
20 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
21 import org.kuali.rice.krad.datadictionary.parse.BeanTags;
22 import org.kuali.rice.krad.datadictionary.validator.ValidationTrace;
23 import org.kuali.rice.krad.datadictionary.validator.Validator;
24 import org.kuali.rice.krad.uif.UifConstants;
25 import org.kuali.rice.krad.uif.UifPropertyPaths;
26 import org.kuali.rice.krad.uif.component.Component;
27 import org.kuali.rice.krad.uif.component.DataBinding;
28 import org.kuali.rice.krad.uif.component.DelayedCopy;
29 import org.kuali.rice.krad.uif.field.Field;
30 import org.kuali.rice.krad.uif.field.FieldGroup;
31 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
32 import org.kuali.rice.krad.uif.lifecycle.initialize.AssignIdsTask;
33 import org.kuali.rice.krad.uif.util.LifecycleAwareList;
34 import org.kuali.rice.krad.uif.util.LifecycleElement;
35 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
36 import org.kuali.rice.krad.uif.view.ExpressionEvaluator;
37 import org.kuali.rice.krad.uif.view.View;
38 import org.kuali.rice.krad.uif.view.ViewModel;
39 import org.kuali.rice.krad.uif.widget.Disclosure;
40 import org.kuali.rice.krad.uif.widget.Scrollpane;
41 import org.kuali.rice.krad.util.KRADUtils;
42
43 import java.util.ArrayList;
44 import java.util.Collections;
45 import java.util.HashSet;
46 import java.util.List;
47 import java.util.Set;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 @BeanTags({@BeanTag(name = "group-bean", parent = "Uif-GroupBase"),
70 @BeanTag(name = "boxGroupBase-bean", parent = "Uif-BoxGroupBase"),
71 @BeanTag(name = "verticalBoxGroup-bean", parent = "Uif-VerticalBoxGroup"),
72 @BeanTag(name = "verticalBoxSection-bean", parent = "Uif-VerticalBoxSection"),
73 @BeanTag(name = "verticalBoxSubSection-bean", parent = "Uif-VerticalBoxSubSection"),
74 @BeanTag(name = "disclosure-verticalBoxSection-bean", parent = "Uif-Disclosure-VerticalBoxSection"),
75 @BeanTag(name = "disclosure-verticalBoxSubSection-bean", parent = "Uif-Disclosure-VerticalBoxSubSection"),
76 @BeanTag(name = "horizontalBoxGroup-bean", parent = "Uif-HorizontalBoxGroup"),
77 @BeanTag(name = "horizontalBoxSection-bean", parent = "Uif-HorizontalBoxSection"),
78 @BeanTag(name = "horizontalBoxSubSection-bean", parent = "Uif-HorizontalBoxSubSection"),
79 @BeanTag(name = "disclosure-horizontalBoxSection-bean", parent = "Uif-Disclosure-HorizontalBoxSection"),
80 @BeanTag(name = "disclosure-horizontalBoxSubSection-bean", parent = "Uif-Disclosure-HorizontalBoxSubSection"),
81 @BeanTag(name = "gridGroup-bean", parent = "Uif-GridGroup"),
82 @BeanTag(name = "gridSection-bean", parent = "Uif-GridSection"),
83 @BeanTag(name = "gridSubSection-bean", parent = "Uif-GridSubSection"),
84 @BeanTag(name = "disclosure-gridSection-bean", parent = "Uif-Disclosure-GridSection"),
85 @BeanTag(name = "cssGridGroup-bean", parent = "Uif-CssGridGroup"),
86 @BeanTag(name = "cssGridSection-bean", parent = "Uif-CssGridSection"),
87 @BeanTag(name = "cssGridSubSection-bean", parent = "Uif-CssGridSubSection"),
88 @BeanTag(name = "cssGridSection-1FieldLabelColumn-bean", parent = "Uif-CssGridSection-1FieldLabelColumn"),
89 @BeanTag(name = "cssGridSection-2FieldLabelColumn-bean", parent = "Uif-CssGridSection-2FieldLabelColumn"),
90 @BeanTag(name = "cssGridSection-3FieldLabelColumn-bean", parent = "Uif-CssGridSection-3FieldLabelColumn"),
91 @BeanTag(name = "cssGridSubSection-1FieldLabelColumn-bean", parent = "Uif-CssGridSubSection-1FieldLabelColumn"),
92 @BeanTag(name = "cssGridSubSection-2FieldLabelColumn-bean", parent = "Uif-CssGridSubSection-2FieldLabelColumn"),
93 @BeanTag(name = "cssGridSubSection-3FieldLabelColumn-bean", parent = "Uif-CssGridSubSection-3FieldLabelColumn"),
94 @BeanTag(name = "listGroup-bean", parent = "Uif-ListGroup"),
95 @BeanTag(name = "listSection-bean", parent = "Uif-ListSection"),
96 @BeanTag(name = "listSubSection-bean", parent = "Uif-ListSubSection"),
97 @BeanTag(name = "disclosure-listSection-bean", parent = "Uif-Disclosure-ListSection"),
98 @BeanTag(name = "disclosure-listSubSection-bean", parent = "Uif-Disclosure-ListSubSection"),
99 @BeanTag(name = "collectionGridItem-bean", parent = "Uif-CollectionGridItem"),
100 @BeanTag(name = "collectionVerticalBoxItem-bean", parent = "Uif-CollectionVerticalBoxItem"),
101 @BeanTag(name = "collectionHorizontalBoxItem-bean", parent = "Uif-CollectionHorizontalBoxItem"),
102 @BeanTag(name = "headerUpperGroup-bean", parent = "Uif-HeaderUpperGroup"),
103 @BeanTag(name = "headerRightGroup-bean", parent = "Uif-HeaderRightGroup"),
104 @BeanTag(name = "headerLowerGroup-bean", parent = "Uif-HeaderLowerGroup"),
105 @BeanTag(name = "footer-bean", parent = "Uif-FooterBase"),
106 @BeanTag(name = "formFooter-bean", parent = "Uif-FormFooter"),
107 @BeanTag(name = "actionsGroup-bean", parent = "Uif-ActionsGroup"),
108 @BeanTag(name = "disclosureActionsGroup-bean", parent = "Uif-DisclosureActionsGroup"),
109 @BeanTag(name = "disclosureActions-reqMessageGroup-bean", parent = "Uif-DisclosureActions-ReqMessageGroup"),
110 @BeanTag(name = "inactiveItemsActionsGroup-bean", parent = "Uif-InactiveItemsActionsGroup"),
111 @BeanTag(name = "documentInfoGroup-bean", parent = "Uif-DocumentInfoGroup"),
112 @BeanTag(name = "documentOverviewSection-bean", parent = "Uif-DocumentOverviewSection"),
113 @BeanTag(name = "documentAdHocRecipientsSection-bean", parent = "Uif-DocumentAdHocRecipientsSection"),
114 @BeanTag(name = "documentRouteLogSection-bean", parent = "Uif-DocumentRouteLogSection"),
115 @BeanTag(name = "documentPageFooter-bean", parent = "Uif-DocumentPageFooter"),
116 @BeanTag(name = "incidentDetailGroup-bean", parent = "Uif-IncidentDetailGroup"),
117 @BeanTag(name = "incidentStackTraceGroup-bean", parent = "Uif-IncidentStackTraceGroup"),
118 @BeanTag(name = "incidentReportFooter-bean", parent = "Uif-IncidentReportFooter"),
119 @BeanTag(name = "initiatedDocumentFooter-bean", parent = "InitiatedDocumentFooter"),
120 @BeanTag(name = "inquiryFooter-bean", parent = "Uif-InquiryFooter"),
121 @BeanTag(name = "lookupCriteriaGroup-bean", parent = "Uif-LookupCriteriaGroup"),
122 @BeanTag(name = "lookupPageHeaderGroup-bean", parent = "Uif-LookupPageHeaderGroup"),
123 @BeanTag(name = "lookupCriteriaFooter-bean", parent = "Uif-LookupCriteriaFooter"),
124 @BeanTag(name = "lookupResultsFooter-bean", parent = "Uif-LookupResultsFooter"),
125 @BeanTag(name = "maintenanceGridGroup-bean", parent = "Uif-MaintenanceGridGroup"),
126 @BeanTag(name = "maintenanceHorizontalBoxGroup-bean", parent = "Uif-MaintenanceHorizontalBoxGroup"),
127 @BeanTag(name = "maintenanceVerticalBoxGroup-bean", parent = "Uif-MaintenanceVerticalBoxGroup"),
128 @BeanTag(name = "maintenanceGridSection-bean", parent = "Uif-MaintenanceGridSection"),
129 @BeanTag(name = "maintenanceGridSubSection-bean", parent = "Uif-MaintenanceGridSubSection"),
130 @BeanTag(name = "maintenanceHorizontalBoxSection-bean", parent = "Uif-MaintenanceHorizontalBoxSection"),
131 @BeanTag(name = "maintenanceVerticalBoxSection-bean", parent = "Uif-MaintenanceVerticalBoxSection"),
132 @BeanTag(name = "maintenanceHorizontalBoxSubSection-bean", parent = "Uif-MaintenanceHorizontalBoxSubSection"),
133 @BeanTag(name = "maintenanceVerticalBoxSubSection-bean", parent = "Uif-MaintenanceVerticalBoxSubSection")})
134 public class GroupBase extends ContainerBase implements Group {
135 private static final long serialVersionUID = 7953641325356535509L;
136
137 private String fieldBindByNamePrefix;
138 private String fieldBindingObjectPath;
139
140 @DelayedCopy
141 private Disclosure disclosure;
142 private Scrollpane scrollpane;
143
144 private List<? extends Component> items;
145
146 private String wrapperTag;
147
148
149
150
151 public GroupBase() {
152 items = Collections.emptyList();
153 }
154
155
156
157
158
159
160
161
162
163
164
165 @Override
166 public void performInitialization(Object model) {
167 if (isClosedAjaxDisclosure()) {
168 this.setItems(new ArrayList<Component>());
169 this.setFooter(null);
170 }
171
172 super.performInitialization(model);
173
174 for (Component component : getItems()) {
175
176
177 if (component instanceof DataBinding) {
178 DataBinding dataBinding = (DataBinding) component;
179
180 if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
181 String bindByNamePrefixToSet = getFieldBindByNamePrefix();
182
183 if (StringUtils.isNotBlank(dataBinding.getBindingInfo().getBindByNamePrefix())) {
184 bindByNamePrefixToSet += "." + dataBinding.getBindingInfo().getBindByNamePrefix();
185 }
186 dataBinding.getBindingInfo().setBindByNamePrefix(bindByNamePrefixToSet);
187 }
188
189 if (StringUtils.isNotBlank(fieldBindingObjectPath) && StringUtils.isBlank(
190 dataBinding.getBindingInfo().getBindingObjectPath())) {
191 dataBinding.getBindingInfo().setBindingObjectPath(fieldBindingObjectPath);
192 }
193 }
194
195 else if (component instanceof FieldGroup) {
196 FieldGroup fieldGroup = (FieldGroup) component;
197
198 if (fieldGroup.getGroup() != null) {
199 if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindByNamePrefix())) {
200 fieldGroup.getGroup().setFieldBindByNamePrefix(fieldBindByNamePrefix);
201 }
202 if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindingObjectPath())) {
203 fieldGroup.getGroup().setFieldBindingObjectPath(fieldBindingObjectPath);
204 }
205 }
206 } else if (component instanceof Group) {
207 Group subGroup = (Group) component;
208 if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
209 if (StringUtils.isNotBlank(subGroup.getFieldBindByNamePrefix())) {
210 subGroup.setFieldBindByNamePrefix(
211 getFieldBindByNamePrefix() + "." + subGroup.getFieldBindByNamePrefix());
212 } else {
213 subGroup.setFieldBindByNamePrefix(getFieldBindByNamePrefix());
214 }
215 }
216 if (StringUtils.isNotBlank(getFieldBindingObjectPath())) {
217 if (StringUtils.isNotBlank(subGroup.getFieldBindingObjectPath())) {
218 subGroup.setFieldBindingObjectPath(
219 getFieldBindingObjectPath() + "." + subGroup.getFieldBindingObjectPath());
220 } else {
221 subGroup.setFieldBindingObjectPath(getFieldBindingObjectPath());
222 }
223 }
224 }
225 }
226 }
227
228
229
230
231
232
233 @Override
234 public void performFinalize(Object model, LifecycleElement parent) {
235 super.performFinalize(model, parent);
236
237 if (StringUtils.isBlank(wrapperTag) && StringUtils.isNotBlank(this.getHeaderText()) && this.getHeader()
238 .isRender()) {
239 wrapperTag = UifConstants.WrapperTags.SECTION;
240 } else if (StringUtils.isBlank(wrapperTag)) {
241 wrapperTag = UifConstants.WrapperTags.DIV;
242 }
243 }
244
245
246
247
248 @Override
249 public Set<Class<? extends Component>> getSupportedComponents() {
250 Set<Class<? extends Component>> supportedComponents = new HashSet<Class<? extends Component>>();
251 supportedComponents.add(Field.class);
252 supportedComponents.add(Group.class);
253
254 return supportedComponents;
255 }
256
257
258
259
260 @Override
261 public String getComponentTypeName() {
262 return "group";
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277 @Override
278 @BeanTagAttribute(name = "fieldBindByNamePrefix")
279 public String getFieldBindByNamePrefix() {
280 return this.fieldBindByNamePrefix;
281 }
282
283
284
285
286
287
288 public void setFieldBindByNamePrefix(String fieldBindByNamePrefix) {
289 this.fieldBindByNamePrefix = fieldBindByNamePrefix;
290 }
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 @BeanTagAttribute(name = "fieldBindingObjectPath")
308 public String getFieldBindingObjectPath() {
309 return this.fieldBindingObjectPath;
310 }
311
312
313
314
315
316
317 public void setFieldBindingObjectPath(String fieldBindingObjectPath) {
318 this.fieldBindingObjectPath = fieldBindingObjectPath;
319 }
320
321
322
323
324
325
326
327 @BeanTagAttribute(name = "Disclosure", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
328 public Disclosure getDisclosure() {
329 return this.disclosure;
330 }
331
332
333
334
335
336
337 public void setDisclosure(Disclosure disclosure) {
338 this.disclosure = disclosure;
339 }
340
341
342
343
344
345
346
347 @BeanTagAttribute(name = "scrollpane", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
348 public Scrollpane getScrollpane() {
349 return this.scrollpane;
350 }
351
352
353
354
355
356
357 public void setScrollpane(Scrollpane scrollpane) {
358 this.scrollpane = scrollpane;
359 }
360
361
362
363
364 @Override
365 @BeanTagAttribute(name = "items", type = BeanTagAttribute.AttributeType.LISTBEAN)
366 public List<? extends Component> getItems() {
367 if (items == Collections.EMPTY_LIST && isMutable(true)) {
368 items = new LifecycleAwareList<Component>(this);
369 }
370
371 return this.items;
372 }
373
374
375
376
377
378
379 @SuppressWarnings("unchecked")
380 @Override
381 public void setItems(List<? extends Component> items) {
382 if (items == null) {
383 this.items = Collections.emptyList();
384 } else if (items.contains(this)) {
385 throw new IllegalArgumentException("Attempted to add group to itself");
386 } else {
387 this.items = new LifecycleAwareList<Component>(this, (List<Component>) items);
388 }
389 }
390
391
392
393
394
395
396
397 @BeanTagAttribute(name = "wrapperTag")
398 public String getWrapperTag() {
399 return wrapperTag;
400 }
401
402
403
404
405 public void setWrapperTag(String wrapperTag) {
406 this.wrapperTag = wrapperTag;
407 }
408
409
410
411
412
413
414 protected boolean isClosedAjaxDisclosure() {
415 ViewModel model = (ViewModel) ViewLifecycle.getModel();
416 View view = ViewLifecycle.getView();
417
418 if (this.getDisclosure() == null) {
419 return false;
420 }
421
422 ViewLifecycle.getExpressionEvaluator().populatePropertyExpressionsFromGraph(this, false);
423
424
425 if (this.getDisclosure() != null && StringUtils.isNotBlank(this.getDisclosure().getPropertyExpression(
426 UifPropertyPaths.DEFAULT_OPEN))) {
427 ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
428
429 String expression = this.getDisclosure().getPropertyExpression(UifPropertyPaths.DEFAULT_OPEN);
430 expression = expressionEvaluator.replaceBindingPrefixes(view, this, expression);
431
432 expression = expressionEvaluator.evaluateExpressionTemplate(this.getDisclosure().getContext(), expression);
433 ObjectPropertyUtils.setPropertyValue(this.getDisclosure(), UifPropertyPaths.DEFAULT_OPEN, expression);
434 }
435
436 if (disclosure.getId() == null) {
437 disclosure.setId(AssignIdsTask.generateId(disclosure, view));
438 }
439
440
441 if (this.getDisclosure() != null) {
442 KRADUtils.syncClientSideStateForComponent(this.getDisclosure(), model.getClientStateForSyncing());
443 }
444
445 boolean closed = !this.getDisclosure().isDefaultOpen();
446
447 boolean open = (closed && ViewLifecycle.isRefreshComponent(ViewLifecycle.getPhase().getViewPhase(),
448 this.getViewPath())) || !closed;
449
450 if (open) {
451 this.getDisclosure().setDefaultOpen(true);
452 }
453
454
455 return !this.isRetrieveViaAjax() && this.getDisclosure().isAjaxRetrievalWhenOpened() && !open;
456 }
457
458
459
460
461 @Override
462 public void completeValidation(ValidationTrace tracer) {
463 tracer.addBean(this);
464
465
466 for (int i = 0; i < getItems().size(); i++) {
467 if (getItems().get(i).getClass() == PageGroup.class || getItems().get(i).getClass()
468 == NavigationGroup.class) {
469 String currentValues[] = {"item(" + i + ").class =" + getItems().get(i).getClass()};
470 tracer.createError("Items in Group cannot be PageGroup or NaviagtionGroup", currentValues);
471 }
472 }
473
474
475 if (getLayoutManager() == null) {
476 if (Validator.checkExpressions(this, "layoutManager")) {
477 String currentValues[] = {"layoutManager = " + getLayoutManager()};
478 tracer.createError("LayoutManager must be set", currentValues);
479 }
480 }
481
482 super.completeValidation(tracer.getCopy());
483 }
484
485
486
487
488
489
490 public boolean isRenderLoading() {
491 return disclosure != null && disclosure.isAjaxRetrievalWhenOpened() && (!disclosure.isRender() || !disclosure
492 .isDefaultOpen());
493 }
494
495 }