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