1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.modifier;
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.uif.UifConstants;
23 import org.kuali.rice.krad.uif.UifPropertyPaths;
24 import org.kuali.rice.krad.uif.component.Component;
25 import org.kuali.rice.krad.uif.container.Group;
26 import org.kuali.rice.krad.uif.element.Header;
27 import org.kuali.rice.krad.uif.field.DataField;
28 import org.kuali.rice.krad.uif.field.Field;
29 import org.kuali.rice.krad.uif.field.SpaceField;
30 import org.kuali.rice.krad.uif.layout.GridLayoutManager;
31 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
32 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleUtils;
33 import org.kuali.rice.krad.uif.util.ComponentFactory;
34 import org.kuali.rice.krad.uif.util.ComponentUtils;
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
39 import java.util.ArrayList;
40 import java.util.HashMap;
41 import java.util.HashSet;
42 import java.util.List;
43 import java.util.Map;
44 import java.util.Set;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 @BeanTags({@BeanTag(name = "compareFieldCreateModifier", parent = "Uif-CompareFieldCreate-Modifier"),
62 @BeanTag(name = "maintenanceCompareModifier", parent = "Uif-MaintenanceCompare-Modifier")})
63 public class CompareFieldCreateModifier extends ComponentModifierBase {
64 private static final long serialVersionUID = -6285531580512330188L;
65
66 private int defaultOrderSequence;
67 private boolean generateCompareHeaders;
68
69 private Header headerFieldPrototype;
70 private List<ComparableInfo> comparables;
71
72 public CompareFieldCreateModifier() {
73 defaultOrderSequence = 1;
74 generateCompareHeaders = true;
75
76 comparables = new ArrayList<ComparableInfo>();
77 }
78
79
80
81
82 @Override
83 public void performInitialization(Object model, Component component) {
84 super.performInitialization(model, component);
85
86 if ((component != null) && !(component instanceof Group)) {
87 throw new IllegalArgumentException(
88 "Compare field initializer only support Group components, found type: " + component.getClass());
89 }
90
91 if (component == null) {
92 return;
93 }
94
95 Group group = (Group) component;
96
97
98 for (Component item : group.getItems()) {
99 item.pushObjectToContext("renderOnComparableModifier", Boolean.TRUE);
100 }
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119 @Override
120 public void performModification(Object model, Component component) {
121 if ((component != null) && !(component instanceof Group)) {
122 throw new IllegalArgumentException(
123 "Compare field initializer only support Group components, found type: " + component.getClass());
124 }
125
126 if (component == null) {
127 return;
128 }
129
130 Group group = (Group) component;
131
132
133 List<Component> comparisonItems = new ArrayList<Component>();
134
135
136 List<ComparableInfo> groupComparables = ComponentUtils.sort(comparables, defaultOrderSequence);
137
138
139 Map<String, Object> context = new HashMap<String, Object>();
140
141 View view = ViewLifecycle.getView();
142
143 Map<String, Object> viewContext = view.getContext();
144 if (viewContext != null) {
145 context.putAll(view.getContext());
146 }
147
148 context.put(UifConstants.ContextVariableNames.COMPONENT, component);
149
150 ExpressionEvaluator expressionEvaluator = ViewLifecycle.getExpressionEvaluator();
151
152 for (ComparableInfo comparable : groupComparables) {
153 expressionEvaluator.evaluateExpressionsOnConfigurable(view, comparable, context);
154 }
155
156
157 if (isGenerateCompareHeaders()) {
158
159 SpaceField spaceField = ComponentFactory.getSpaceField();
160 comparisonItems.add(spaceField);
161
162 for (ComparableInfo comparable : groupComparables) {
163 Header compareHeaderField = ComponentUtils.copy(headerFieldPrototype, comparable.getComparableId());
164 compareHeaderField.setHeaderText(comparable.getHeaderText());
165 comparisonItems.add(compareHeaderField);
166 }
167
168
169 if (group.getLayoutManager() instanceof GridLayoutManager) {
170
171 ((GridLayoutManager) group.getLayoutManager()).setRenderFirstRowHeader(true);
172
173 ((GridLayoutManager) group.getLayoutManager()).getRowCssClasses().add("");
174 }
175 }
176
177
178 boolean performValueChangeComparison = false;
179 String compareValueObjectBindingPath = null;
180 for (ComparableInfo comparable : groupComparables) {
181 if (comparable.isCompareToForValueChange()) {
182 performValueChangeComparison = true;
183 compareValueObjectBindingPath = comparable.getBindingObjectPath();
184 }
185 }
186
187
188 boolean changeIconShowedOnHeader = false;
189 for (Component item : group.getItems()) {
190
191
192 if (item instanceof Header) {
193 comparisonItems.add(item);
194 item.setColSpan(groupComparables.size() + 1);
195
196
197 if (group.getLayoutManager() instanceof GridLayoutManager) {
198
199 ((GridLayoutManager) group.getLayoutManager()).getRowCssClasses().add("row-separator");
200 }
201
202 continue;
203 }
204
205 int defaultSuffix = 0;
206 boolean suppressLabel = false;
207
208 String rowCssClass = "";
209
210 for (ComparableInfo comparable : groupComparables) {
211 String comparableId = comparable.getComparableId();
212 if (StringUtils.isBlank(comparableId)) {
213 comparableId = UifConstants.IdSuffixes.COMPARE + defaultSuffix;
214 }
215
216 Component compareItem = ComponentUtils.copy(item, comparableId);
217
218 ComponentUtils.setComponentPropertyDeep(compareItem, UifPropertyPaths.BIND_OBJECT_PATH,
219 comparable.getBindingObjectPath());
220 if (comparable.isReadOnly()) {
221 compareItem.setReadOnly(true);
222 if (compareItem.getPropertyExpressions().containsKey("readOnly")) {
223 compareItem.getPropertyExpressions().remove("readOnly");
224 }
225 }
226
227
228 if (suppressLabel && (compareItem instanceof Field)) {
229 ((Field) compareItem).getFieldLabel().setRender(false);
230 }
231
232
233 compareItem.pushObjectToContext("renderOnComparableModifier", comparable.isCompareToForFieldRender());
234
235
236 if (performValueChangeComparison && comparable.isHighlightValueChange() && !comparable
237 .isCompareToForValueChange()) {
238 boolean valueChanged = performValueComparison(group, compareItem, model,
239 compareValueObjectBindingPath);
240
241
242 if (valueChanged && !changeIconShowedOnHeader && isGenerateCompareHeaders()) {
243 Group groupToSetHeader = null;
244 if (group.getDisclosure() != null && group.getDisclosure().isRender()) {
245 groupToSetHeader = group;
246 } else if (group.getContext().get(UifConstants.ContextVariableNames.PARENT) != null) {
247
248 groupToSetHeader = (Group) group.getContext().get(UifConstants.ContextVariableNames.PARENT);
249 }
250
251 if (groupToSetHeader != null) {
252 if (groupToSetHeader.getDisclosure().isRender()) {
253 groupToSetHeader.getDisclosure().setOnDocumentReadyScript(
254 "showChangeIconOnDisclosure('" + groupToSetHeader.getId() + "');");
255 } else if (groupToSetHeader.getHeader() != null) {
256 groupToSetHeader.getHeader().setOnDocumentReadyScript(
257 "showChangeIconOnHeader('" + groupToSetHeader.getHeader().getId() + "');");
258 }
259 }
260
261 changeIconShowedOnHeader = true;
262 }
263
264
265 if (valueChanged) {
266 rowCssClass = "uif-compared";
267 }
268 }
269
270 comparisonItems.add(compareItem);
271
272 defaultSuffix++;
273
274 suppressLabel = true;
275 }
276
277
278 if (group.getLayoutManager() instanceof GridLayoutManager) {
279
280 ((GridLayoutManager) group.getLayoutManager()).getRowCssClasses().add(rowCssClass);
281 }
282 }
283
284
285 group.setItems(comparisonItems);
286 }
287
288
289
290
291
292
293
294
295
296
297
298
299
300 protected boolean performValueComparison(Group group, Component compareItem, Object model,
301 String compareValueObjectBindingPath) {
302
303 List<DataField> itemFields = ViewLifecycleUtils.getElementsOfTypeDeep(compareItem, DataField.class);
304 boolean valueChanged = false;
305 for (DataField field : itemFields) {
306 String fieldBindingPath = field.getBindingInfo().getBindingPath();
307 if (field.getPropertyName() != null && field.getPropertyName().length() > 0 && !fieldBindingPath.endsWith(field.getPropertyName())) {
308 fieldBindingPath += "." + field.getPropertyName();
309 }
310 Object fieldValue = ObjectPropertyUtils.getPropertyValue(model, fieldBindingPath);
311
312 String compareBindingPath = StringUtils.replaceOnce(fieldBindingPath,
313 field.getBindingInfo().getBindingObjectPath(), compareValueObjectBindingPath);
314 Object compareValue = ObjectPropertyUtils.getPropertyValue(model, compareBindingPath);
315
316 if (!((fieldValue == null) && (compareValue == null))) {
317
318 if ((fieldValue == null) || (compareValue == null)) {
319 valueChanged = true;
320 } else {
321
322 valueChanged = !fieldValue.equals(compareValue);
323 }
324 }
325 if (valueChanged) {
326
327 String onReadyScript = "showChangeIcon('" + field.getId() + "');";
328 field.setRenderMarkerIconSpan(true);
329 field.setOnDocumentReadyScript(onReadyScript);
330 }
331
332 }
333 return valueChanged;
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350 protected String getComparableId(ComparableInfo comparable, int index) {
351 String comparableId = comparable.getComparableId();
352 if (StringUtils.isBlank(comparableId)) {
353 comparableId = "_" + index;
354 }
355
356 return comparableId;
357 }
358
359
360
361
362 @Override
363 public Set<Class<? extends Component>> getSupportedComponents() {
364 Set<Class<? extends Component>> components = new HashSet<Class<? extends Component>>();
365 components.add(Group.class);
366
367 return components;
368 }
369
370
371
372
373 public List<Component> getComponentPrototypes() {
374 List<Component> components = new ArrayList<Component>();
375
376 components.add(headerFieldPrototype);
377
378 return components;
379 }
380
381
382
383
384
385
386
387
388 @BeanTagAttribute
389 public int getDefaultOrderSequence() {
390 return this.defaultOrderSequence;
391 }
392
393
394
395
396
397
398 public void setDefaultOrderSequence(int defaultOrderSequence) {
399 this.defaultOrderSequence = defaultOrderSequence;
400 }
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415 @BeanTagAttribute
416 public boolean isGenerateCompareHeaders() {
417 return this.generateCompareHeaders;
418 }
419
420
421
422
423
424
425 public void setGenerateCompareHeaders(boolean generateCompareHeaders) {
426 this.generateCompareHeaders = generateCompareHeaders;
427 }
428
429
430
431
432
433
434
435 @BeanTagAttribute
436 public Header getHeaderFieldPrototype() {
437 return this.headerFieldPrototype;
438 }
439
440
441
442
443
444
445 public void setHeaderFieldPrototype(Header headerFieldPrototype) {
446 this.headerFieldPrototype = headerFieldPrototype;
447 }
448
449
450
451
452
453
454
455
456
457
458
459
460 @BeanTagAttribute
461 public List<ComparableInfo> getComparables() {
462 return this.comparables;
463 }
464
465
466
467
468
469
470 public void setComparables(List<ComparableInfo> comparables) {
471 this.comparables = comparables;
472 }
473
474 }