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.util.ExpressionUtils;
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", parent = "Uif-GroupBase"),
70 @BeanTag(name = "boxGroup", parent = "Uif-BoxGroupBase"),
71 @BeanTag(name = "verticalGroup", parent = "Uif-VerticalBoxGroup"),
72 @BeanTag(name = "verticalSection", parent = "Uif-VerticalBoxSection"),
73 @BeanTag(name = "verticalSubSection", parent = "Uif-VerticalBoxSubSection"),
74 @BeanTag(name = "disclosureVerticalSection", parent = "Uif-Disclosure-VerticalBoxSection"),
75 @BeanTag(name = "disclosureVerticalSubSection", parent = "Uif-Disclosure-VerticalBoxSubSection"),
76 @BeanTag(name = "horizontalGroup", parent = "Uif-HorizontalBoxGroup"),
77 @BeanTag(name = "horizontalSection", parent = "Uif-HorizontalBoxSection"),
78 @BeanTag(name = "horizontalSubSection", parent = "Uif-HorizontalBoxSubSection"),
79 @BeanTag(name = "disclosureHorizontalSection", parent = "Uif-Disclosure-HorizontalBoxSection"),
80 @BeanTag(name = "disclosureHorizontalSubSection", parent = "Uif-Disclosure-HorizontalBoxSubSection"),
81 @BeanTag(name = "grid", parent = "Uif-GridGroup"),
82 @BeanTag(name = "gridSection", parent = "Uif-GridSection"),
83 @BeanTag(name = "gridSubSection", parent = "Uif-GridSubSection"),
84 @BeanTag(name = "disclosureGridSection", parent = "Uif-Disclosure-GridSection"),
85 @BeanTag(name = "cssGrid", parent = "Uif-CssGridGroup"),
86 @BeanTag(name = "section", parent = "Uif-CssGridSection"),
87 @BeanTag(name = "subSection", parent = "Uif-CssGridSubSection"),
88 @BeanTag(name = "section1Col", parent = "Uif-CssGridSection-1FieldLabelColumn"),
89 @BeanTag(name = "section2Col", parent = "Uif-CssGridSection-2FieldLabelColumn"),
90 @BeanTag(name = "section3Col", parent = "Uif-CssGridSection-3FieldLabelColumn"),
91 @BeanTag(name = "subSection1Col", parent = "Uif-CssGridSubSection-1FieldLabelColumn"),
92 @BeanTag(name = "subSection2Col", parent = "Uif-CssGridSubSection-2FieldLabelColumn"),
93 @BeanTag(name = "subSection3Col", parent = "Uif-CssGridSubSection-3FieldLabelColumn"),
94 @BeanTag(name = "list", parent = "Uif-ListGroup"),
95 @BeanTag(name = "listSection", parent = "Uif-ListSection"),
96 @BeanTag(name = "listSubSection", parent = "Uif-ListSubSection"),
97 @BeanTag(name = "disclosureListSection", parent = "Uif-Disclosure-ListSection"),
98 @BeanTag(name = "disclosureListSubSection", parent = "Uif-Disclosure-ListSubSection"),
99 @BeanTag(name = "collectionGridItem", parent = "Uif-CollectionGridItem"),
100 @BeanTag(name = "collectionVerticalBoxItem", parent = "Uif-CollectionVerticalBoxItem"),
101 @BeanTag(name = "collectionHorizontalBoxItem", parent = "Uif-CollectionHorizontalBoxItem"),
102 @BeanTag(name = "headerUpperGroup", parent = "Uif-HeaderUpperGroup"),
103 @BeanTag(name = "headerRightGroup", parent = "Uif-HeaderRightGroup"),
104 @BeanTag(name = "headerLowerGroup", parent = "Uif-HeaderLowerGroup"),
105 @BeanTag(name = "footer", parent = "Uif-FooterBase"),
106 @BeanTag(name = "formFooter", parent = "Uif-FormFooter"),
107 @BeanTag(name = "maintenanceGrid", parent = "Uif-MaintenanceGridGroup"),
108 @BeanTag(name = "maintenanceHorizontalGroup", parent = "Uif-MaintenanceHorizontalBoxGroup"),
109 @BeanTag(name = "maintenanceVerticalGroup", parent = "Uif-MaintenanceVerticalBoxGroup"),
110 @BeanTag(name = "maintenanceGridSection", parent = "Uif-MaintenanceGridSection"),
111 @BeanTag(name = "maintenanceGridSubSection", parent = "Uif-MaintenanceGridSubSection"),
112 @BeanTag(name = "maintenanceHorizontalSection", parent = "Uif-MaintenanceHorizontalBoxSection"),
113 @BeanTag(name = "maintenanceVerticalSection", parent = "Uif-MaintenanceVerticalBoxSection"),
114 @BeanTag(name = "maintenanceHorizontalSubSection", parent = "Uif-MaintenanceHorizontalBoxSubSection"),
115 @BeanTag(name = "maintenanceVerticalSubSection", parent = "Uif-MaintenanceVerticalBoxSubSection")})
116 public class GroupBase extends ContainerBase implements Group {
117 private static final long serialVersionUID = 7953641325356535509L;
118
119 private String fieldBindByNamePrefix;
120 private String fieldBindingObjectPath;
121
122 @DelayedCopy
123 private Disclosure disclosure;
124 private Scrollpane scrollpane;
125
126 private List<? extends Component> items;
127
128 private String wrapperTag;
129
130
131
132
133 public GroupBase() {
134 items = Collections.emptyList();
135 }
136
137
138
139
140 @Override
141 public void performInitialization(Object model) {
142 if (isAjaxDisclosureGroup()) {
143 this.setItems(new ArrayList<Component>());
144 }
145
146 super.performInitialization(model);
147
148 for (Component component : getItems()) {
149
150
151 if (component instanceof DataBinding) {
152 DataBinding dataBinding = (DataBinding) component;
153
154 if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
155 String bindByNamePrefixToSet = getFieldBindByNamePrefix();
156
157 if (StringUtils.isNotBlank(dataBinding.getBindingInfo().getBindByNamePrefix())) {
158 bindByNamePrefixToSet += "." + dataBinding.getBindingInfo().getBindByNamePrefix();
159 }
160 dataBinding.getBindingInfo().setBindByNamePrefix(bindByNamePrefixToSet);
161 }
162
163 if (StringUtils.isNotBlank(fieldBindingObjectPath) && StringUtils.isBlank(
164 dataBinding.getBindingInfo().getBindingObjectPath())) {
165 dataBinding.getBindingInfo().setBindingObjectPath(fieldBindingObjectPath);
166 }
167 }
168
169 else if (component instanceof FieldGroup) {
170 FieldGroup fieldGroup = (FieldGroup) component;
171
172 if (fieldGroup.getGroup() != null) {
173 if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindByNamePrefix())) {
174 fieldGroup.getGroup().setFieldBindByNamePrefix(fieldBindByNamePrefix);
175 }
176 if (StringUtils.isBlank(fieldGroup.getGroup().getFieldBindingObjectPath())) {
177 fieldGroup.getGroup().setFieldBindingObjectPath(fieldBindingObjectPath);
178 }
179 }
180 } else if (component instanceof Group) {
181 Group subGroup = (Group) component;
182 if (StringUtils.isNotBlank(getFieldBindByNamePrefix())) {
183 if (StringUtils.isNotBlank(subGroup.getFieldBindByNamePrefix())) {
184 subGroup.setFieldBindByNamePrefix(
185 getFieldBindByNamePrefix() + "." + subGroup.getFieldBindByNamePrefix());
186 } else {
187 subGroup.setFieldBindByNamePrefix(getFieldBindByNamePrefix());
188 }
189 }
190 if (StringUtils.isNotBlank(getFieldBindingObjectPath())) {
191 if (StringUtils.isNotBlank(subGroup.getFieldBindingObjectPath())) {
192 subGroup.setFieldBindingObjectPath(
193 getFieldBindingObjectPath() + "." + subGroup.getFieldBindingObjectPath());
194 } else {
195 subGroup.setFieldBindingObjectPath(getFieldBindingObjectPath());
196 }
197 }
198 }
199 }
200 }
201
202
203
204
205 @Override
206 public void afterEvaluateExpression() {
207 super.afterEvaluateExpression();
208
209 if (getReadOnly() == null) {
210 Component parent = ViewLifecycle.getPhase().getParent();
211 setReadOnly(parent == null ? null : parent.getReadOnly());
212 }
213 }
214
215
216
217
218
219
220 @Override
221 public void performFinalize(Object model, LifecycleElement parent) {
222 super.performFinalize(model, parent);
223
224 if (StringUtils.isBlank(wrapperTag) && StringUtils.isNotBlank(this.getHeaderText()) && this.getHeader()
225 .isRender()) {
226 wrapperTag = UifConstants.WrapperTags.SECTION;
227 } else if (StringUtils.isBlank(wrapperTag)) {
228 wrapperTag = UifConstants.WrapperTags.DIV;
229 }
230 }
231
232
233
234
235 @Override
236 public Set<Class<? extends Component>> getSupportedComponents() {
237 Set<Class<? extends Component>> supportedComponents = new HashSet<Class<? extends Component>>();
238 supportedComponents.add(Field.class);
239 supportedComponents.add(Group.class);
240
241 return supportedComponents;
242 }
243
244
245
246
247 @Override
248 public String getComponentTypeName() {
249 return "group";
250 }
251
252
253
254
255 @Override
256 @BeanTagAttribute
257 public String getFieldBindByNamePrefix() {
258 return this.fieldBindByNamePrefix;
259 }
260
261
262
263
264 @Override
265 public void setFieldBindByNamePrefix(String fieldBindByNamePrefix) {
266 this.fieldBindByNamePrefix = fieldBindByNamePrefix;
267 }
268
269
270
271
272 @BeanTagAttribute
273 public String getFieldBindingObjectPath() {
274 return this.fieldBindingObjectPath;
275 }
276
277
278
279
280 @Override
281 public void setFieldBindingObjectPath(String fieldBindingObjectPath) {
282 this.fieldBindingObjectPath = fieldBindingObjectPath;
283 }
284
285
286
287
288 @BeanTagAttribute
289 public Disclosure getDisclosure() {
290 return this.disclosure;
291 }
292
293
294
295
296 @Override
297 public void setDisclosure(Disclosure disclosure) {
298 this.disclosure = disclosure;
299 }
300
301
302
303
304 @BeanTagAttribute
305 public Scrollpane getScrollpane() {
306 return this.scrollpane;
307 }
308
309
310
311
312 @Override
313 public void setScrollpane(Scrollpane scrollpane) {
314 this.scrollpane = scrollpane;
315 }
316
317
318
319
320 @Override
321 @BeanTagAttribute
322 public List<? extends Component> getItems() {
323 if (items == Collections.EMPTY_LIST && isMutable(true)) {
324 items = new LifecycleAwareList<Component>(this);
325 }
326
327 return this.items;
328 }
329
330
331
332
333 @SuppressWarnings("unchecked")
334 @Override
335 public void setItems(List<? extends Component> items) {
336 if (items == null) {
337 this.items = Collections.emptyList();
338 } else if (items.contains(this)) {
339 throw new IllegalArgumentException("Attempted to add group to itself");
340 } else {
341 this.items = new LifecycleAwareList<Component>(this, (List<Component>) items);
342 }
343 }
344
345
346
347
348
349
350
351 @BeanTagAttribute
352 public String getWrapperTag() {
353 return wrapperTag;
354 }
355
356
357
358
359 public void setWrapperTag(String wrapperTag) {
360 this.wrapperTag = wrapperTag;
361 }
362
363
364
365
366
367
368 protected boolean isAjaxDisclosureGroup() {
369 ViewModel model = (ViewModel) ViewLifecycle.getModel();
370 View view = ViewLifecycle.getView();
371
372 ExpressionUtils.populatePropertyExpressionsFromGraph(this);
373
374
375 if (this.getDisclosure() != null && StringUtils.isNotBlank(this.getDisclosure().getPropertyExpression(
376 UifPropertyPaths.DEFAULT_OPEN))){
377 ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
378
379 String expression = this.getDisclosure().getPropertyExpression(UifPropertyPaths.DEFAULT_OPEN);
380 expression = expressionEvaluator.replaceBindingPrefixes(view, this, expression);
381
382 expression = expressionEvaluator.evaluateExpressionTemplate(this.getDisclosure().getContext(), expression);
383 ObjectPropertyUtils.setPropertyValue(this.getDisclosure(), UifPropertyPaths.DEFAULT_OPEN, expression);
384 }
385
386
387 if (this.getDisclosure() != null) {
388 KRADUtils.syncClientSideStateForComponent(this.getDisclosure(), model.getClientStateForSyncing());
389 }
390
391
392
393 return !this.isRetrieveViaAjax() && this.getDisclosure() != null && this.getDisclosure()
394 .isAjaxRetrievalWhenOpened() && !this.getDisclosure().isDefaultOpen();
395 }
396
397
398
399
400 @Override
401 public void completeValidation(ValidationTrace tracer) {
402 tracer.addBean(this);
403
404
405 for (int i = 0; i < getItems().size(); i++) {
406 if (getItems().get(i).getClass() == PageGroup.class || getItems().get(i).getClass()
407 == TabNavigationGroup.class) {
408 String currentValues[] = {"item(" + i + ").class =" + getItems().get(i).getClass()};
409 tracer.createError("Items in Group cannot be PageGroup or NaviagtionGroup", currentValues);
410 }
411 }
412
413
414 if (getLayoutManager() == null) {
415 if (Validator.checkExpressions(this, "layoutManager")) {
416 String currentValues[] = {"layoutManager = " + getLayoutManager()};
417 tracer.createError("LayoutManager must be set", currentValues);
418 }
419 }
420
421 super.completeValidation(tracer.getCopy());
422 }
423
424
425
426
427 @Override
428 public boolean isRenderLoading() {
429 return disclosure != null && disclosure.isAjaxRetrievalWhenOpened() && (!disclosure.isRender() || !disclosure
430 .isDefaultOpen());
431 }
432
433 }