1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.uif.service.impl;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.kuali.rice.core.api.CoreApiServiceLocator;
20 import org.kuali.rice.core.api.config.property.ConfigurationService;
21 import org.kuali.rice.core.api.exception.RiceRuntimeException;
22 import org.kuali.rice.kim.api.identity.Person;
23 import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
24 import org.kuali.rice.krad.bo.PersistableBusinessObject;
25 import org.kuali.rice.krad.datadictionary.AttributeDefinition;
26 import org.kuali.rice.krad.inquiry.Inquirable;
27 import org.kuali.rice.krad.messages.MessageService;
28 import org.kuali.rice.krad.service.BusinessObjectService;
29 import org.kuali.rice.krad.service.DataDictionaryService;
30 import org.kuali.rice.krad.service.KRADServiceLocator;
31 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
32 import org.kuali.rice.krad.service.ModuleService;
33 import org.kuali.rice.krad.service.PersistenceService;
34 import org.kuali.rice.krad.service.PersistenceStructureService;
35 import org.kuali.rice.krad.uif.UifConstants;
36 import org.kuali.rice.krad.uif.UifPropertyPaths;
37 import org.kuali.rice.krad.uif.component.ComponentSecurity;
38 import org.kuali.rice.krad.uif.container.Group;
39 import org.kuali.rice.krad.uif.element.Action;
40 import org.kuali.rice.krad.uif.element.Label;
41 import org.kuali.rice.krad.uif.field.ActionField;
42 import org.kuali.rice.krad.uif.field.FieldGroup;
43 import org.kuali.rice.krad.uif.layout.TableLayoutManager;
44 import org.kuali.rice.krad.uif.util.ViewCleaner;
45 import org.kuali.rice.krad.uif.view.DefaultExpressionEvaluator;
46 import org.kuali.rice.krad.uif.view.ExpressionEvaluator;
47 import org.kuali.rice.krad.uif.view.ViewAuthorizer;
48 import org.kuali.rice.krad.uif.view.ViewPresentationController;
49 import org.kuali.rice.krad.uif.component.BindingInfo;
50 import org.kuali.rice.krad.uif.component.ClientSideState;
51 import org.kuali.rice.krad.uif.component.Component;
52 import org.kuali.rice.krad.uif.component.DataBinding;
53 import org.kuali.rice.krad.uif.component.PropertyReplacer;
54 import org.kuali.rice.krad.uif.component.RequestParameter;
55 import org.kuali.rice.krad.uif.container.CollectionGroup;
56 import org.kuali.rice.krad.uif.container.Container;
57 import org.kuali.rice.krad.uif.control.Control;
58 import org.kuali.rice.krad.uif.field.DataField;
59 import org.kuali.rice.krad.uif.field.InputField;
60 import org.kuali.rice.krad.uif.field.Field;
61 import org.kuali.rice.krad.uif.field.RemoteFieldsHolder;
62 import org.kuali.rice.krad.uif.layout.LayoutManager;
63 import org.kuali.rice.krad.uif.modifier.ComponentModifier;
64 import org.kuali.rice.krad.uif.service.ViewDictionaryService;
65 import org.kuali.rice.krad.uif.service.ViewHelperService;
66 import org.kuali.rice.krad.uif.util.BooleanMap;
67 import org.kuali.rice.krad.uif.util.CloneUtils;
68 import org.kuali.rice.krad.uif.util.ComponentFactory;
69 import org.kuali.rice.krad.uif.util.ComponentUtils;
70 import org.kuali.rice.krad.uif.util.ExpressionUtils;
71 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
72 import org.kuali.rice.krad.uif.util.ScriptUtils;
73 import org.kuali.rice.krad.uif.util.ViewModelUtils;
74 import org.kuali.rice.krad.uif.view.View;
75 import org.kuali.rice.krad.uif.view.ViewModel;
76 import org.kuali.rice.krad.uif.widget.Inquiry;
77 import org.kuali.rice.krad.uif.widget.Widget;
78 import org.kuali.rice.krad.util.ErrorMessage;
79 import org.kuali.rice.krad.util.GlobalVariables;
80 import org.kuali.rice.krad.util.GrowlMessage;
81 import org.kuali.rice.krad.util.KRADConstants;
82 import org.kuali.rice.krad.util.KRADUtils;
83 import org.kuali.rice.krad.util.MessageMap;
84 import org.kuali.rice.krad.util.ObjectUtils;
85 import org.kuali.rice.krad.valuefinder.ValueFinder;
86 import org.kuali.rice.krad.web.form.UifFormBase;
87 import org.springframework.util.ClassUtils;
88 import org.springframework.util.MethodInvoker;
89
90 import java.io.Serializable;
91 import java.lang.annotation.Annotation;
92 import java.text.MessageFormat;
93 import java.util.ArrayList;
94 import java.util.Collection;
95 import java.util.Collections;
96 import java.util.HashMap;
97 import java.util.HashSet;
98 import java.util.List;
99 import java.util.Map;
100 import java.util.Map.Entry;
101 import java.util.Set;
102
103
104
105
106
107
108 public class ViewHelperServiceImpl implements ViewHelperService, Serializable {
109 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ViewHelperServiceImpl.class);
110
111 private transient BusinessObjectService businessObjectService;
112 private transient PersistenceService persistenceService;
113 private transient PersistenceStructureService persistenceStructureService;
114 private transient DataDictionaryService dataDictionaryService;
115 private transient ExpressionEvaluator expressionEvaluator;
116 private transient ViewDictionaryService viewDictionaryService;
117 private transient ConfigurationService configurationService;
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 @Override
134 public void populateViewFromRequestParameters(View view, Map<String, String> parameters) {
135
136
137 Map<String, Set<PropertyReplacer>> viewPropertyReplacers = new HashMap<String, Set<PropertyReplacer>>();
138 for (PropertyReplacer replacer : view.getPropertyReplacers()) {
139 Set<PropertyReplacer> propertyReplacers = new HashSet<PropertyReplacer>();
140 if (viewPropertyReplacers.containsKey(replacer.getPropertyName())) {
141 propertyReplacers = viewPropertyReplacers.get(replacer.getPropertyName());
142 }
143 propertyReplacers.add(replacer);
144
145 viewPropertyReplacers.put(replacer.getPropertyName(), propertyReplacers);
146 }
147
148 Map<String, Annotation> annotatedFields = CloneUtils.getFieldsWithAnnotation(view.getClass(),
149 RequestParameter.class);
150
151
152
153 Map<String, String> viewRequestParameters = new HashMap<String, String>();
154 for (String fieldToPopulate : annotatedFields.keySet()) {
155 RequestParameter requestParameter = (RequestParameter) annotatedFields.get(fieldToPopulate);
156
157
158 String requestParameterName = requestParameter.parameterName();
159 if (StringUtils.isBlank(requestParameterName)) {
160 requestParameterName = fieldToPopulate;
161 }
162
163 if (!parameters.containsKey(requestParameterName)) {
164 continue;
165 }
166
167 String fieldValue = parameters.get(requestParameterName);
168 if (StringUtils.isNotBlank(fieldValue)) {
169 viewRequestParameters.put(requestParameterName, fieldValue);
170 ObjectPropertyUtils.setPropertyValue(view, fieldToPopulate, fieldValue);
171
172
173
174 if (view.getPropertyExpressions().containsKey(fieldToPopulate)) {
175 view.getPropertyExpressions().remove(fieldToPopulate);
176 }
177
178 if (viewPropertyReplacers.containsKey(fieldToPopulate)) {
179 Set<PropertyReplacer> propertyReplacers = viewPropertyReplacers.get(fieldToPopulate);
180 for (PropertyReplacer replacer : propertyReplacers) {
181 view.getPropertyReplacers().remove(replacer);
182 }
183 }
184 }
185 }
186
187 view.setViewRequestParameters(viewRequestParameters);
188 }
189
190
191
192
193
194 @Override
195 public void performInitialization(View view, Object model) {
196 view.assignComponentIds(view);
197
198
199
200 view.setIdSequence(100000);
201 performComponentInitialization(view, model, view);
202
203
204 getExpressionEvaluator().initializeEvaluationContext(model);
205
206
207
208
209 for (Component dialog : view.getDialogs()) {
210 dialog.setRefreshedByAction(true);
211 }
212 }
213
214
215
216
217
218
219
220
221
222
223
224
225
226 public void performComponentLifecycle(View view, Object model, Component component, String origId) {
227 Component origComponent = view.getViewIndex().getComponentById(origId);
228
229
230
231 Integer currentSequenceVal = view.getIdSequence();
232 Integer startingSequenceVal = view.getViewIndex().getIdSequenceSnapshot().get(component.getId());
233
234 if (startingSequenceVal != null) {
235 view.setIdSequence(startingSequenceVal);
236 }
237
238 view.assignComponentIds(component);
239
240
241
242 view.setIdSequence(currentSequenceVal);
243
244 Component parent = (Component) origComponent.getContext().get(UifConstants.ContextVariableNames.PARENT);
245
246
247 component.pushAllToContext(origComponent.getContext());
248 List<Component> nestedComponents = ComponentUtils.getAllNestedComponents(component);
249 for (Component nestedComponent : nestedComponents) {
250 nestedComponent.pushAllToContext(origComponent.getContext());
251 }
252
253
254 component.setDataAttributes(origComponent.getDataAttributes());
255
256
257 view.getViewHelperService().getExpressionEvaluator().initializeEvaluationContext(model);
258
259
260
261
262 Map<String, String> expressionGraph = view.getViewIndex().getComponentExpressionGraphs().get(
263 component.getBaseId());
264 component.setExpressionGraph(expressionGraph);
265 ExpressionUtils.populatePropertyExpressionsFromGraph(component, false);
266
267
268 if (component instanceof DataBinding) {
269 ((DataBinding) component).setBindingInfo(((DataBinding) origComponent).getBindingInfo());
270 ((DataBinding) component).getBindingInfo().setBindingPath(
271 ((DataBinding) origComponent).getBindingInfo().getBindingPath());
272 }
273
274
275 if (component instanceof Field) {
276 ((Field) component).setLabelRendered(((Field) origComponent).isLabelRendered());
277 }
278
279 if (origComponent.isRefreshedByAction()) {
280 component.setRefreshedByAction(true);
281 }
282
283
284 if (component.isResetDataOnRefresh()) {
285
286 if (component instanceof DataField) {
287
288
289
290 ObjectPropertyUtils.initializeProperty(model,
291 ((DataField) component).getBindingInfo().getBindingPath());
292 }
293 }
294
295 performComponentInitialization(view, model, component);
296
297
298 String suffix = StringUtils.replaceOnce(origComponent.getId(), origComponent.getBaseId(), "");
299 if (StringUtils.isNotBlank(suffix)) {
300 ComponentUtils.updateIdWithSuffix(component, suffix);
301 ComponentUtils.updateChildIdsWithSuffixNested(component, suffix);
302 }
303
304
305
306
307 if (component instanceof Group || component instanceof FieldGroup) {
308 List<CollectionGroup> origCollectionGroups = ComponentUtils.getComponentsOfTypeShallow(origComponent,
309 CollectionGroup.class);
310 List<CollectionGroup> collectionGroups = ComponentUtils.getComponentsOfTypeShallow(component,
311 CollectionGroup.class);
312
313 for (int i = 0; i < collectionGroups.size(); i++) {
314 CollectionGroup origCollectionGroup = origCollectionGroups.get(i);
315 CollectionGroup collectionGroup = collectionGroups.get(i);
316
317 String prefix = origCollectionGroup.getBindingInfo().getBindByNamePrefix();
318 if (StringUtils.isNotBlank(prefix) && StringUtils.isBlank(
319 collectionGroup.getBindingInfo().getBindByNamePrefix())) {
320 ComponentUtils.prefixBindingPath(collectionGroup, prefix);
321 }
322
323 String lineSuffix = origCollectionGroup.getSubCollectionSuffix();
324 collectionGroup.setSubCollectionSuffix(lineSuffix);
325 }
326 }
327
328
329 if (component.isDisclosedByAction()) {
330 ComponentUtils.setComponentPropertyFinal(component, UifPropertyPaths.RENDER, true);
331 ComponentUtils.setComponentPropertyFinal(component, UifPropertyPaths.HIDDEN, false);
332 }
333
334 performComponentApplyModel(view, component, model, new HashMap<String, Integer>());
335 view.getViewIndex().indexComponent(component);
336
337
338 if (component instanceof Container) {
339 ComponentUtils.adjustNestedLevelsForTableCollections((Container) component, 0);
340 } else if (component instanceof FieldGroup) {
341 ComponentUtils.adjustNestedLevelsForTableCollections(((FieldGroup) component).getGroup(), 0);
342 }
343
344 performComponentFinalize(view, component, model, parent);
345
346
347 if (component instanceof Group || component instanceof FieldGroup) {
348 List<Component> nestedGroupComponents = ComponentUtils.getAllNestedComponents(component);
349 List<Component> originalNestedGroupComponents = ComponentUtils.getAllNestedComponents(origComponent);
350
351 for (Component nestedComponent : nestedGroupComponents) {
352 Component origNestedComponent = ComponentUtils.findComponentInList(originalNestedGroupComponents,
353 nestedComponent.getId());
354
355 if (origNestedComponent != null) {
356
357 if (nestedComponent instanceof DataBinding) {
358 ((DataBinding) nestedComponent).setBindingInfo(
359 ((DataBinding) origNestedComponent).getBindingInfo());
360 ((DataBinding) nestedComponent).getBindingInfo().setBindingPath(
361 ((DataBinding) origNestedComponent).getBindingInfo().getBindingPath());
362 }
363
364
365 if (nestedComponent instanceof Field) {
366 ((Field) nestedComponent).setLabelRendered(((Field) origNestedComponent).isLabelRendered());
367 }
368
369 if (origNestedComponent.isRefreshedByAction()) {
370 nestedComponent.setRefreshedByAction(true);
371 }
372 }
373 }
374 }
375
376
377 String growlScript = buildGrowlScript(view);
378 ((ViewModel) model).setGrowlScript(growlScript);
379
380 view.getViewIndex().indexComponent(component);
381 }
382
383
384
385
386
387
388 @Override
389 public void spawnSubLifecyle(View view, Object model, Component component, Component parent, String startPhase,
390 String endPhase) {
391 if (component == null) {
392 return;
393 }
394
395 if (LOG.isDebugEnabled()) {
396 LOG.debug("Spawning sub-lifecycle for component: " + component.getId());
397 }
398
399 if (StringUtils.isBlank(component.getId())) {
400 view.assignComponentIds(component);
401 }
402
403 if (StringUtils.isBlank(startPhase)) {
404 startPhase = UifConstants.ViewPhases.INITIALIZE;
405 } else if (!UifConstants.ViewPhases.INITIALIZE.equals(startPhase) && !UifConstants.ViewPhases.APPLY_MODEL
406 .equals(startPhase) && !UifConstants.ViewPhases.FINALIZE.equals(startPhase)) {
407 throw new RuntimeException("Invalid start phase given: " + startPhase);
408 }
409
410 if (StringUtils.isBlank(endPhase)) {
411 endPhase = UifConstants.ViewPhases.FINALIZE;
412 } else if (!UifConstants.ViewPhases.INITIALIZE.equals(endPhase) && !UifConstants.ViewPhases.APPLY_MODEL.equals(
413 endPhase) && !UifConstants.ViewPhases.FINALIZE.equals(endPhase)) {
414 throw new RuntimeException("Invalid end phase given: " + endPhase);
415 }
416
417 if (UifConstants.ViewPhases.INITIALIZE.equals(startPhase)) {
418 performComponentInitialization(view, model, component);
419 view.getViewIndex().indexComponent(component);
420
421 startPhase = UifConstants.ViewPhases.APPLY_MODEL;
422 }
423
424 if (UifConstants.ViewPhases.INITIALIZE.equals(endPhase)) {
425 return;
426 }
427
428 component.pushObjectToContext(UifConstants.ContextVariableNames.PARENT, parent);
429
430 if (UifConstants.ViewPhases.APPLY_MODEL.equals(startPhase)) {
431 performComponentApplyModel(view, component, model, new HashMap<String, Integer>());
432 view.getViewIndex().indexComponent(component);
433 }
434
435 if (UifConstants.ViewPhases.APPLY_MODEL.equals(endPhase)) {
436 return;
437 }
438
439 performComponentFinalize(view, component, model, parent);
440 view.getViewIndex().indexComponent(component);
441 }
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468 public void performComponentInitialization(View view, Object model, Component component) {
469 if (component == null) {
470 return;
471 }
472
473 if (StringUtils.isBlank(component.getId())) {
474 throw new RiceRuntimeException("Id is not set, this should not happen unless a component is misconfigured");
475 }
476
477
478
479 LOG.debug("Initializing component: " + component.getId() + " with type: " + component.getClass());
480
481
482 if (!(component instanceof View)) {
483 view.getViewIndex().addInitialComponentStateIfNeeded(component);
484 }
485
486
487
488 ExpressionUtils.populatePropertyExpressionsFromGraph(component, true);
489
490
491 component.performInitialization(view, model);
492
493
494 for (PropertyReplacer replacer : component.getPropertyReplacers()) {
495 ExpressionUtils.populatePropertyExpressionsFromGraph(replacer, true);
496 }
497
498 for (ComponentModifier modifier : component.getComponentModifiers()) {
499 ExpressionUtils.populatePropertyExpressionsFromGraph(modifier, true);
500 }
501
502
503 if (component instanceof DataField) {
504 initializeDataFieldFromDataDictionary(view, (DataField) component);
505 }
506
507 if (component instanceof Container) {
508 LayoutManager layoutManager = ((Container) component).getLayoutManager();
509
510
511 addCustomContainerComponents(view, model, (Container) component);
512
513
514
515 if (!(component instanceof CollectionGroup)) {
516 processAnyRemoteFieldsHolder(view, model, (Container) component);
517 }
518 }
519
520
521 if (component instanceof CollectionGroup) {
522
523 }
524
525
526 performCustomInitialization(view, component);
527
528
529 runComponentModifiers(view, component, null, UifConstants.ViewPhases.INITIALIZE);
530
531
532 for (Component nestedComponent : component.getComponentsForLifecycle()) {
533 performComponentInitialization(view, model, nestedComponent);
534 }
535
536
537 for (Component nestedComponent : component.getComponentPrototypes()) {
538 performComponentInitialization(view, model, nestedComponent);
539 }
540 }
541
542
543
544
545
546
547
548
549
550
551 protected void processAnyRemoteFieldsHolder(View view, Object model, Container container) {
552 List<Component> processedItems = new ArrayList<Component>();
553
554
555
556 for (Component item : container.getItems()) {
557 if (item instanceof RemoteFieldsHolder) {
558 List<InputField> translatedFields = ((RemoteFieldsHolder) item).fetchAndTranslateRemoteFields(view,
559 model, container);
560 processedItems.addAll(translatedFields);
561 } else {
562 processedItems.add(item);
563 }
564 }
565
566
567 container.setItems(processedItems);
568 }
569
570
571
572
573
574
575
576
577 protected void initializeDataFieldFromDataDictionary(View view, DataField field) {
578 AttributeDefinition attributeDefinition = null;
579
580 String dictionaryAttributeName = field.getDictionaryAttributeName();
581 String dictionaryObjectEntry = field.getDictionaryObjectEntry();
582
583
584
585 if (StringUtils.isNotBlank(dictionaryObjectEntry) && StringUtils.isBlank(dictionaryAttributeName)) {
586 dictionaryAttributeName = field.getPropertyName();
587 }
588
589
590 if (StringUtils.isNotBlank(dictionaryAttributeName) && StringUtils.isNotBlank(dictionaryObjectEntry)) {
591 attributeDefinition = getDataDictionaryService().getAttributeDefinition(dictionaryObjectEntry,
592 dictionaryAttributeName);
593 }
594
595
596 if (attributeDefinition == null) {
597 String propertyPath = field.getBindingInfo().getBindingPath();
598 if (StringUtils.isNotBlank(field.getBindingInfo().getCollectionPath())) {
599 propertyPath = field.getBindingInfo().getCollectionPath();
600 if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
601 propertyPath += "." + field.getBindingInfo().getBindByNamePrefix();
602 }
603 propertyPath += "." + field.getBindingInfo().getBindingName();
604 }
605
606 attributeDefinition = findNestedDictionaryAttribute(view, field, null, propertyPath);
607 }
608
609
610 if (attributeDefinition != null) {
611 field.copyFromAttributeDefinition(view, attributeDefinition);
612 }
613
614
615 if (field instanceof InputField) {
616 InputField inputField = (InputField) field;
617 if (inputField.getControl() == null) {
618 Control control = ComponentFactory.getTextControl();
619 view.assignComponentIds(control);
620
621 inputField.setControl(control);
622 }
623 }
624 }
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651 protected AttributeDefinition findNestedDictionaryAttribute(View view, DataField field, String parentPath,
652 String propertyPath) {
653 AttributeDefinition attributeDefinition = null;
654
655
656 String dictionaryAttributeName = propertyPath;
657 String dictionaryObjectEntry = null;
658
659 if (field.getBindingInfo().isBindToMap()) {
660 parentPath = "";
661 if (!field.getBindingInfo().isBindToForm() && StringUtils.isNotBlank(
662 field.getBindingInfo().getBindingObjectPath())) {
663 parentPath = field.getBindingInfo().getBindingObjectPath();
664 }
665 if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
666 if (StringUtils.isNotBlank(parentPath)) {
667 parentPath += "." + field.getBindingInfo().getBindByNamePrefix();
668 } else {
669 parentPath = field.getBindingInfo().getBindByNamePrefix();
670 }
671 }
672
673 dictionaryAttributeName = field.getBindingInfo().getBindingName();
674 }
675
676 if (StringUtils.isNotBlank(parentPath)) {
677 Class<?> dictionaryModelClass = ViewModelUtils.getPropertyTypeByClassAndView(view, parentPath);
678 if (dictionaryModelClass != null) {
679 dictionaryObjectEntry = dictionaryModelClass.getName();
680
681 attributeDefinition = getDataDictionaryService().getAttributeDefinition(dictionaryObjectEntry,
682 dictionaryAttributeName);
683 }
684 }
685
686
687
688 if ((attributeDefinition == null) && StringUtils.contains(propertyPath, ".")) {
689 String nextParentPath = StringUtils.substringBefore(propertyPath, ".");
690 if (StringUtils.isNotBlank(parentPath)) {
691 nextParentPath = parentPath + "." + nextParentPath;
692 }
693 String nextPropertyPath = StringUtils.substringAfter(propertyPath, ".");
694
695 return findNestedDictionaryAttribute(view, field, nextParentPath, nextPropertyPath);
696 }
697
698
699 if (attributeDefinition != null) {
700 field.setDictionaryAttributeName(dictionaryAttributeName);
701 field.setDictionaryObjectEntry(dictionaryObjectEntry);
702 }
703
704 return attributeDefinition;
705 }
706
707
708
709
710
711 @Override
712 public void performApplyModel(View view, Object model) {
713
714 retrieveEditModesAndActionFlags(view, (UifFormBase) model);
715
716
717 setViewContext(view, model);
718
719 Map<String, Integer> visitedIds = new HashMap<String, Integer>();
720 performComponentApplyModel(view, view, model, visitedIds);
721 }
722
723
724
725
726
727
728
729
730
731 protected void retrieveEditModesAndActionFlags(View view, UifFormBase model) {
732 ViewPresentationController presentationController = view.getPresentationController();
733 ViewAuthorizer authorizer = view.getAuthorizer();
734
735 Set<String> actionFlags = presentationController.getActionFlags(view, model);
736 Set<String> editModes = presentationController.getEditModes(view, model);
737
738
739 if (GlobalVariables.getUserSession() != null) {
740 Person user = GlobalVariables.getUserSession().getPerson();
741
742 actionFlags = authorizer.getActionFlags(view, model, user, actionFlags);
743 editModes = authorizer.getEditModes(view, model, user, editModes);
744 }
745
746 view.setActionFlags(new BooleanMap(actionFlags));
747 view.setEditModes(new BooleanMap(editModes));
748 }
749
750
751
752
753
754
755
756
757 protected void setViewContext(View view, Object model) {
758 view.pushAllToContext(getPreModelContext(view));
759
760
761 for (Entry<String, String> variableExpression : view.getExpressionVariables().entrySet()) {
762 String variableName = variableExpression.getKey();
763 Object value = getExpressionEvaluator().evaluateExpression(view.getContext(),
764 variableExpression.getValue());
765 view.pushObjectToContext(variableName, value);
766 }
767 }
768
769
770
771
772
773
774
775
776 protected Map<String, Object> getPreModelContext(View view) {
777 Map<String, Object> context = new HashMap<String, Object>();
778
779 context.put(UifConstants.ContextVariableNames.VIEW, view);
780 context.put(UifConstants.ContextVariableNames.VIEW_HELPER, this);
781
782 Map<String, String> properties = CoreApiServiceLocator.getKualiConfigurationService().getAllProperties();
783 context.put(UifConstants.ContextVariableNames.CONFIG_PROPERTIES, properties);
784 context.put(UifConstants.ContextVariableNames.CONSTANTS, KRADConstants.class);
785 context.put(UifConstants.ContextVariableNames.UIF_CONSTANTS, UifConstants.class);
786
787 return context;
788 }
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806 protected void performComponentApplyModel(View view, Component component, Object model,
807 Map<String, Integer> visitedIds) {
808 if (component == null) {
809 return;
810 }
811
812
813 component.pushAllToContext(getCommonContext(view, component));
814
815 for (PropertyReplacer replacer : component.getPropertyReplacers()) {
816 getExpressionEvaluator().evaluateExpressionsOnConfigurable(view, replacer, component.getContext());
817 }
818
819 for (ComponentModifier modifier : component.getComponentModifiers()) {
820 getExpressionEvaluator().evaluateExpressionsOnConfigurable(view, modifier, component.getContext());
821 }
822
823 getExpressionEvaluator().evaluateExpressionsOnConfigurable(view, component, component.getContext());
824
825
826 ComponentSecurity componentSecurity = component.getComponentSecurity();
827 getExpressionEvaluator().evaluateExpressionsOnConfigurable(view, componentSecurity, component.getContext());
828
829
830 if (component instanceof DataBinding) {
831 BindingInfo bindingInfo = ((DataBinding) component).getBindingInfo();
832 getExpressionEvaluator().evaluateExpressionsOnConfigurable(view, bindingInfo, component.getContext());
833 }
834
835
836 if (component instanceof Container) {
837 LayoutManager layoutManager = ((Container) component).getLayoutManager();
838
839 if (layoutManager != null) {
840 layoutManager.getContext().putAll(getCommonContext(view, component));
841 layoutManager.pushObjectToContext(UifConstants.ContextVariableNames.PARENT, component);
842 layoutManager.pushObjectToContext(UifConstants.ContextVariableNames.MANAGER, layoutManager);
843
844 getExpressionEvaluator().evaluateExpressionsOnConfigurable(view, layoutManager,
845 layoutManager.getContext());
846
847 layoutManager.setId(adjustIdIfNecessary(layoutManager.getId(), visitedIds));
848 }
849 }
850
851
852 syncClientSideStateForComponent(component, ((ViewModel) model).getClientStateForSyncing());
853
854
855 applyAuthorizationAndPresentationLogic(view, component, (ViewModel) model);
856
857
858
859
860
861 Component parent = (Component) component.getContext().get(UifConstants.ContextVariableNames.PARENT);
862 component.performApplyModel(view, model, parent);
863
864
865 performCustomApplyModel(view, component, model);
866
867
868 runComponentModifiers(view, component, model, UifConstants.ViewPhases.APPLY_MODEL);
869
870
871 for (Component nestedComponent : component.getComponentsForLifecycle()) {
872 if (nestedComponent != null) {
873 nestedComponent.pushObjectToContext(UifConstants.ContextVariableNames.PARENT, component);
874 performComponentApplyModel(view, nestedComponent, model, visitedIds);
875 }
876 }
877 }
878
879
880
881
882
883
884
885
886
887 protected String adjustIdIfNecessary(String id, Map<String, Integer> visitedIds) {
888 String adjustedId = id;
889
890 if (visitedIds.containsKey(id)) {
891 Integer nextAdjustSeq = visitedIds.get(id);
892 adjustedId = id + nextAdjustSeq;
893
894
895 while (visitedIds.containsKey(adjustedId)) {
896 nextAdjustSeq = nextAdjustSeq + 1;
897 adjustedId = id + nextAdjustSeq;
898 }
899
900 visitedIds.put(adjustedId, Integer.valueOf(1));
901
902 nextAdjustSeq = nextAdjustSeq + 1;
903 visitedIds.put(id, nextAdjustSeq);
904 } else {
905 visitedIds.put(id, Integer.valueOf(1));
906 }
907
908 return adjustedId;
909 }
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932 protected void applyAuthorizationAndPresentationLogic(View view, Component component, ViewModel model) {
933 ViewPresentationController presentationController = view.getPresentationController();
934 ViewAuthorizer authorizer = view.getAuthorizer();
935
936
937 if (GlobalVariables.getUserSession() == null) {
938 return;
939 }
940
941 Person user = GlobalVariables.getUserSession().getPerson();
942
943
944 if (!component.isRender()) {
945 return;
946 }
947
948
949 if (component instanceof View) {
950 if (!view.isReadOnly()) {
951 boolean canEditView = authorizer.canEditView(view, model, user);
952 if (canEditView) {
953 canEditView = presentationController.canEditView(view, model);
954 }
955 view.setReadOnly(!canEditView);
956 }
957 }
958
959
960 else if (component instanceof Group) {
961 Group group = (Group) component;
962
963
964 if (!group.isHidden()) {
965 boolean canViewGroup = authorizer.canViewGroup(view, model, group, group.getId(), user);
966 if (canViewGroup) {
967 canViewGroup = presentationController.canViewGroup(view, model, group, group.getId());
968 }
969 group.setHidden(!canViewGroup);
970 group.setRender(canViewGroup);
971 }
972
973
974 if (!group.isReadOnly()) {
975 boolean canEditGroup = authorizer.canEditGroup(view, model, group, group.getId(), user);
976 if (canEditGroup) {
977 canEditGroup = presentationController.canEditGroup(view, model, group, group.getId());
978 }
979 group.setReadOnly(!canEditGroup);
980 }
981 }
982
983
984 else if (component instanceof Field && !(component instanceof ActionField)) {
985 Field field = (Field) component;
986
987 String propertyName = null;
988 if (field instanceof DataBinding) {
989 propertyName = ((DataBinding) field).getPropertyName();
990 }
991
992
993 if (!field.isHidden()) {
994 boolean canViewField = authorizer.canViewField(view, model, field, propertyName, user);
995 if (canViewField) {
996 canViewField = presentationController.canViewField(view, model, field, propertyName);
997 }
998 field.setHidden(!canViewField);
999 field.setRender(canViewField);
1000 }
1001
1002
1003 if (!field.isReadOnly()) {
1004
1005 boolean canEditField = authorizer.canEditField(view, model, field, propertyName, user);
1006 if (canEditField) {
1007 canEditField = presentationController.canEditField(view, model, field, propertyName);
1008 }
1009 field.setReadOnly(!canEditField);
1010 }
1011
1012
1013 if ((field.getRequired() == null) || !field.getRequired().booleanValue()) {
1014 boolean fieldIsRequired = presentationController.fieldIsRequired(view, model, field, propertyName);
1015 }
1016
1017 if (field instanceof DataField) {
1018 DataField dataField = (DataField) field;
1019
1020
1021 boolean canUnmaskValue = authorizer.canUnmaskField(view, model, dataField, dataField.getPropertyName(),
1022 user);
1023 if (!canUnmaskValue) {
1024 dataField.setApplyMask(true);
1025 dataField.setMaskFormatter(dataField.getDataFieldSecurity().getAttributeSecurity().
1026 getMaskFormatter());
1027 } else {
1028
1029 boolean canPartiallyUnmaskValue = authorizer.canPartialUnmaskField(view, model, dataField,
1030 dataField.getPropertyName(), user);
1031 if (!canPartiallyUnmaskValue) {
1032 dataField.setApplyMask(true);
1033 dataField.setMaskFormatter(
1034 dataField.getDataFieldSecurity().getAttributeSecurity().getPartialMaskFormatter());
1035 }
1036 }
1037 }
1038 }
1039
1040
1041 else if (component instanceof ActionField || component instanceof Action) {
1042 Action action = null;
1043 if (component instanceof ActionField) {
1044 action = ((ActionField) component).getAction();
1045 } else {
1046 action = (Action) component;
1047 }
1048
1049 boolean canTakeAction = authorizer.canPerformAction(view, model, action, action.getActionEvent(),
1050 action.getId(), user);
1051 if (canTakeAction) {
1052 canTakeAction = presentationController.canPerformAction(view, model, action, action.getActionEvent(),
1053 action.getId());
1054 }
1055 action.setRender(canTakeAction);
1056 }
1057
1058
1059 else if (component instanceof Widget) {
1060 Widget widget = (Widget) component;
1061
1062
1063 if (!widget.isHidden()) {
1064 boolean canViewWidget = authorizer.canViewWidget(view, model, widget, widget.getId(), user);
1065 if (canViewWidget) {
1066 canViewWidget = presentationController.canViewWidget(view, model, widget, widget.getId());
1067 }
1068 widget.setHidden(!canViewWidget);
1069 widget.setRender(canViewWidget);
1070 }
1071
1072
1073 if (!widget.isReadOnly()) {
1074 boolean canEditWidget = authorizer.canEditWidget(view, model, widget, widget.getId(), user);
1075 if (canEditWidget) {
1076 canEditWidget = presentationController.canEditWidget(view, model, widget, widget.getId());
1077 }
1078 widget.setReadOnly(!canEditWidget);
1079 }
1080 }
1081 }
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098 protected void runComponentModifiers(View view, Component component, Object model, String runPhase) {
1099 for (ComponentModifier modifier : component.getComponentModifiers()) {
1100
1101 if (StringUtils.equals(runPhase, UifConstants.ViewPhases.INITIALIZE)) {
1102 modifier.performInitialization(view, model, component);
1103 }
1104
1105
1106 if (StringUtils.equals(modifier.getRunPhase(), runPhase)) {
1107
1108 boolean runModifier = true;
1109 if (StringUtils.isNotBlank(modifier.getRunCondition())) {
1110 Map<String, Object> context = new HashMap<String, Object>();
1111 context.put(UifConstants.ContextVariableNames.COMPONENT, component);
1112 context.put(UifConstants.ContextVariableNames.VIEW, view);
1113
1114 String conditionEvaluation = getExpressionEvaluator().evaluateExpressionTemplate(context,
1115 modifier.getRunCondition());
1116 runModifier = Boolean.parseBoolean(conditionEvaluation);
1117 }
1118
1119 if (runModifier) {
1120 modifier.performModification(view, model, component);
1121 }
1122 }
1123 }
1124 }
1125
1126
1127
1128
1129
1130
1131
1132
1133 public Map<String, Object> getCommonContext(View view, Component component) {
1134 Map<String, Object> context = new HashMap<String, Object>();
1135
1136 context.putAll(view.getContext());
1137 context.put(UifConstants.ContextVariableNames.THEME_IMAGES, view.getTheme().getImageDirectory());
1138 context.put(UifConstants.ContextVariableNames.COMPONENT, component);
1139
1140 return context;
1141 }
1142
1143
1144
1145
1146
1147 @Override
1148 public void performFinalize(View view, Object model) {
1149
1150 String growlScript = buildGrowlScript(view);
1151 ((ViewModel) model).setGrowlScript(growlScript);
1152
1153 performComponentFinalize(view, view, model, null);
1154
1155 String clientStateScript = buildClientSideStateScript(view, model);
1156 view.setPreLoadScript(ScriptUtils.appendScript(view.getPreLoadScript(), clientStateScript));
1157
1158
1159 if (!((ViewModel) model).isDefaultsApplied()) {
1160 applyDefaultValues(view, view, model);
1161 ((ViewModel) model).setDefaultsApplied(true);
1162 }
1163 }
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175 protected String buildClientSideStateScript(View view, Object model) {
1176 Map<String, Object> clientSideState = ((ViewModel) model).getClientStateForSyncing();
1177
1178
1179 String clientStateScript = "";
1180 if (!clientSideState.isEmpty()) {
1181 clientStateScript = ScriptUtils.buildFunctionCall(UifConstants.JsFunctions.INITIALIZE_VIEW_STATE,
1182 clientSideState);
1183 }
1184
1185
1186 String kradImageLocation = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
1187 UifConstants.ConfigProperties.KRAD_IMAGES_URL);
1188 clientStateScript += ScriptUtils.buildFunctionCall(UifConstants.JsFunctions.SET_CONFIG_PARM,
1189 UifConstants.ClientSideVariables.KRAD_IMAGE_LOCATION, kradImageLocation);
1190
1191 String kradURL = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
1192 UifConstants.ConfigProperties.KRAD_URL);
1193 clientStateScript += ScriptUtils.buildFunctionCall(UifConstants.JsFunctions.SET_CONFIG_PARM,
1194 UifConstants.ClientSideVariables.KRAD_URL, kradURL);
1195
1196 String applicationURL = CoreApiServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
1197 KRADConstants.ConfigParameters.APPLICATION_URL);
1198 clientStateScript += ScriptUtils.buildFunctionCall(UifConstants.JsFunctions.SET_CONFIG_PARM,
1199 UifConstants.ClientSideVariables.APPLICATION_URL, applicationURL);
1200
1201 return clientStateScript;
1202 }
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213 public String buildExportTableData(View view, Object model, String tableId, String formatType) {
1214
1215 Map<String, String> exportTableFormatOptions = getExportTableFormatOptions(formatType);
1216 String startTable = exportTableFormatOptions.get("startTable");
1217 String endTable = exportTableFormatOptions.get("endTable");
1218
1219 Component component = view.getViewIndex().getComponentById(tableId);
1220 StringBuilder tableRows = new StringBuilder("");
1221
1222
1223 if (component instanceof CollectionGroup && ((CollectionGroup) component)
1224 .getLayoutManager() instanceof TableLayoutManager) {
1225
1226 CollectionGroup collectionGroup = (CollectionGroup) component;
1227 TableLayoutManager layoutManager = (TableLayoutManager) collectionGroup.getLayoutManager();
1228 List<Label> headerLabels = layoutManager.getHeaderLabels();
1229 List<Field> rowFields = layoutManager.getAllRowFields();
1230 int numberOfColumns = layoutManager.getNumberOfColumns();
1231 List<Integer> ignoredColumns = findIgnoredColumns(layoutManager, collectionGroup);
1232
1233
1234 if (headerLabels.size() > 0) {
1235 List<String> labels = new ArrayList<String>();
1236 for (Label label : headerLabels) {
1237 labels.add(label.getLabelText());
1238 }
1239
1240 tableRows.append(buildExportTableRow(labels, exportTableFormatOptions, ignoredColumns));
1241 }
1242
1243
1244 if (rowFields.size() > 0) {
1245 List<String> columnData = new ArrayList<String>();
1246 for (Field field : rowFields) {
1247 columnData.add(KRADUtils.getSimpleFieldValue(model, field));
1248 if (columnData.size() >= numberOfColumns) {
1249 tableRows.append(buildExportTableRow(columnData, exportTableFormatOptions, ignoredColumns));
1250 columnData.clear();
1251 }
1252 }
1253 }
1254 }
1255
1256 return startTable + tableRows.toString() + endTable;
1257 }
1258
1259
1260
1261
1262
1263
1264 protected String buildExportTableRow(List<String> columnData, Map<String, String> tableFormatOptions,
1265 List<Integer> ignoredColumns) {
1266 String startRow = tableFormatOptions.get("startRow");
1267 String endRow = tableFormatOptions.get("endRow");
1268 String startColumn = tableFormatOptions.get("startColumn");
1269 String endColumn = tableFormatOptions.get("endColumn");
1270 boolean appendLastColumn = Boolean.valueOf(tableFormatOptions.get("appendLastColumn"));
1271 int columnIndex = 0;
1272
1273 StringBuilder builder = new StringBuilder();
1274 for (String columnItem : columnData) {
1275 boolean displayColumn = !ignoredColumns.contains(columnIndex);
1276 if (displayColumn) {
1277 builder.append(startColumn + columnItem + endColumn);
1278 }
1279 if (columnIndex >= columnData.size() - 1 && !appendLastColumn) {
1280 builder.delete(builder.length() - endColumn.length(), builder.length());
1281 }
1282 columnIndex++;
1283 }
1284
1285 return startRow + builder.toString() + endRow;
1286 }
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296 private List<Integer> findIgnoredColumns(TableLayoutManager layoutManager, CollectionGroup collectionGroup) {
1297 List<Integer> ignoreColumns = new ArrayList<Integer>();
1298 int actionColumnIndex = layoutManager.getActionColumnIndex();
1299 int numberOfColumns = layoutManager.getNumberOfColumns();
1300 boolean renderActions = collectionGroup.isRenderLineActions() && !collectionGroup.isReadOnly();
1301 boolean renderSelectField = collectionGroup.isIncludeLineSelectionField();
1302 boolean renderSequenceField = layoutManager.isRenderSequenceField();
1303
1304 if (renderActions || renderSelectField || renderSequenceField) {
1305 int shiftColumn = 0;
1306
1307 if (renderSelectField) {
1308 ignoreColumns.add(shiftColumn);
1309 shiftColumn++;
1310 }
1311 if (renderSequenceField) {
1312 ignoreColumns.add(shiftColumn);
1313 shiftColumn++;
1314 }
1315 if (renderActions) {
1316 if (actionColumnIndex == 1) {
1317 ignoreColumns.add(shiftColumn);
1318 } else if (actionColumnIndex == -1) {
1319 ignoreColumns.add(numberOfColumns - 1);
1320 } else if (actionColumnIndex > 1) {
1321 ignoreColumns.add(actionColumnIndex);
1322 }
1323 }
1324 }
1325 return ignoreColumns;
1326 }
1327
1328
1329
1330
1331
1332
1333
1334 protected Map<String, String> getExportTableFormatOptions(String formatType) {
1335 HashMap<String, String> map = new HashMap<String, String>();
1336
1337 map.put("contentType", "text/plain");
1338 map.put("formatType", "txt");
1339 map.put("startTable", "");
1340 map.put("endTable", "");
1341 map.put("startRow", "");
1342 map.put("endRow", "\n");
1343 map.put("startColumn", "");
1344 map.put("endColumn", ", ");
1345 map.put("appendLastColumn", "false");
1346
1347 if ("csv".equals(formatType)) {
1348 map.put("contentType", "text/csv");
1349 map.put("formatType", "csv");
1350 map.put("startTable", "");
1351 map.put("endTable", "");
1352 map.put("startRow", "");
1353 map.put("endRow", "\n");
1354 map.put("startColumn", "");
1355 map.put("endColumn", ", ");
1356 map.put("appendLastColumn", "false");
1357
1358 } else if ("xls".equals(formatType)) {
1359 map.put("contentType", "application/vnd.ms-excel");
1360 map.put("formatType", "xls");
1361 map.put("startTable", "");
1362 map.put("endTable", "");
1363 map.put("startRow", "");
1364 map.put("endRow", "\n");
1365 map.put("startColumn", "\"");
1366 map.put("endColumn", "\"\t");
1367 map.put("appendLastColumn", "true");
1368
1369 } else if ("xml".equals(formatType)) {
1370 map.put("contentType", "application/xml");
1371 map.put("formatType", "xml");
1372 map.put("startTable", "<table>\n");
1373 map.put("endTable", "</table>\n");
1374 map.put("startRow", " <row>\n");
1375 map.put("endRow", " </row>\n");
1376 map.put("startColumn", " <column>");
1377 map.put("endColumn", "</column>\n");
1378 map.put("appendLastColumn", "true");
1379
1380 }
1381
1382 return map;
1383 }
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401 protected String buildGrowlScript(View view) {
1402 String growlScript = "";
1403
1404 MessageService messageService = KRADServiceLocatorWeb.getMessageService();
1405
1406 MessageMap messageMap = GlobalVariables.getMessageMap();
1407 for (GrowlMessage growl : messageMap.getGrowlMessages()) {
1408 if (view.isGrowlMessagingEnabled()) {
1409 String message = messageService.getMessageText(growl.getNamespaceCode(), growl.getComponentCode(),
1410 growl.getMessageKey());
1411
1412 if (StringUtils.isNotBlank(message)) {
1413 if (growl.getMessageParameters() != null) {
1414 message = message.replace("'", "''");
1415 message = MessageFormat.format(message, (Object[]) growl.getMessageParameters());
1416 }
1417
1418
1419 message = message.replace("'", "\\'");
1420
1421 String title = growl.getTitle();
1422 if (StringUtils.isNotBlank(growl.getTitleKey())) {
1423 title = messageService.getMessageText(growl.getNamespaceCode(), growl.getComponentCode(),
1424 growl.getTitleKey());
1425 }
1426 title = title.replace("'", "\\'");
1427
1428 growlScript =
1429 growlScript + "showGrowl('" + message + "', '" + title + "', '" + growl.getTheme() + "');";
1430 }
1431 } else {
1432 ErrorMessage infoMessage = new ErrorMessage(growl.getMessageKey(), growl.getMessageParameters());
1433 infoMessage.setNamespaceCode(growl.getNamespaceCode());
1434 infoMessage.setComponentCode(growl.getComponentCode());
1435
1436 messageMap.putInfoForSectionId(KRADConstants.GLOBAL_INFO, infoMessage);
1437 }
1438 }
1439
1440 return growlScript;
1441 }
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452 protected void performComponentFinalize(View view, Component component, Object model, Component parent) {
1453 if (component == null) {
1454 return;
1455 }
1456
1457
1458 ViewModel viewModel = (ViewModel) model;
1459 if ((component instanceof DataBinding) && view.isSupportsRequestOverrideOfReadOnlyFields() && !viewModel
1460 .getReadOnlyFieldsList().isEmpty()) {
1461 String propertyName = ((DataBinding) component).getPropertyName();
1462 if (viewModel.getReadOnlyFieldsList().contains(propertyName)) {
1463 component.setReadOnly(true);
1464 }
1465 }
1466
1467
1468 invokeMethodFinalizer(view, component, model);
1469
1470
1471 component.performFinalize(view, model, parent);
1472
1473
1474 performCustomFinalize(view, component, model, parent);
1475
1476
1477 runComponentModifiers(view, component, model, UifConstants.ViewPhases.FINALIZE);
1478
1479
1480 if (!component.isSelfRendered() && StringUtils.isNotBlank(component.getTemplate()) &&
1481 !view.getViewTemplates().contains(component.getTemplate())) {
1482 view.getViewTemplates().add(component.getTemplate());
1483 }
1484
1485 if (component instanceof Container) {
1486 LayoutManager layoutManager = ((Container) component).getLayoutManager();
1487
1488 if ((layoutManager != null) && !view.getViewTemplates().contains(layoutManager.getTemplate())) {
1489 view.getViewTemplates().add(layoutManager.getTemplate());
1490 }
1491 }
1492
1493
1494 for (Component nestedComponent : component.getComponentsForLifecycle()) {
1495 performComponentFinalize(view, nestedComponent, model, component);
1496 }
1497 }
1498
1499
1500
1501
1502
1503
1504
1505
1506 protected void syncClientSideStateForComponent(Component component, Map<String, Object> clientSideState) {
1507
1508 Map<String, Object> componentState = null;
1509 if (component instanceof View) {
1510 componentState = clientSideState;
1511 } else {
1512 if (clientSideState.containsKey(component.getId())) {
1513 componentState = (Map<String, Object>) clientSideState.get(component.getId());
1514 }
1515 }
1516
1517
1518 if ((componentState != null) && (!componentState.isEmpty())) {
1519 Map<String, Annotation> annotatedFields = CloneUtils.getFieldsWithAnnotation(component.getClass(),
1520 ClientSideState.class);
1521
1522 for (Entry<String, Annotation> annotatedField : annotatedFields.entrySet()) {
1523 ClientSideState clientSideStateAnnot = (ClientSideState) annotatedField.getValue();
1524
1525 String variableName = clientSideStateAnnot.variableName();
1526 if (StringUtils.isBlank(variableName)) {
1527 variableName = annotatedField.getKey();
1528 }
1529
1530 if (componentState.containsKey(variableName)) {
1531 Object value = componentState.get(variableName);
1532 ObjectPropertyUtils.setPropertyValue(component, annotatedField.getKey(), value);
1533 }
1534 }
1535 }
1536 }
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547 protected void invokeMethodFinalizer(View view, Component component, Object model) {
1548 String finalizeMethodToCall = component.getFinalizeMethodToCall();
1549 MethodInvoker finalizeMethodInvoker = component.getFinalizeMethodInvoker();
1550
1551 if (StringUtils.isBlank(finalizeMethodToCall) && (finalizeMethodInvoker == null)) {
1552 return;
1553 }
1554
1555 if (finalizeMethodInvoker == null) {
1556 finalizeMethodInvoker = new MethodInvoker();
1557 }
1558
1559
1560
1561 if (StringUtils.isBlank(finalizeMethodInvoker.getTargetMethod())) {
1562 finalizeMethodInvoker.setTargetMethod(finalizeMethodToCall);
1563 }
1564
1565
1566 if ((finalizeMethodInvoker.getTargetClass() == null) && (finalizeMethodInvoker.getTargetObject() == null)) {
1567 finalizeMethodInvoker.setTargetObject(view.getViewHelperService());
1568 }
1569
1570
1571 List<Object> additionalArguments = component.getFinalizeMethodAdditionalArguments();
1572 if (additionalArguments == null) {
1573 additionalArguments = new ArrayList<Object>();
1574 }
1575
1576 Object[] arguments = new Object[2 + additionalArguments.size()];
1577 arguments[0] = component;
1578 arguments[1] = model;
1579
1580 int argumentIndex = 1;
1581 for (Object argument : additionalArguments) {
1582 argumentIndex++;
1583 arguments[argumentIndex] = argument;
1584 }
1585 finalizeMethodInvoker.setArguments(arguments);
1586
1587
1588 try {
1589 LOG.debug("Invoking finalize method: "
1590 + finalizeMethodInvoker.getTargetMethod()
1591 + " for component: "
1592 + component.getId());
1593 finalizeMethodInvoker.prepare();
1594
1595 Class<?> methodReturnType = finalizeMethodInvoker.getPreparedMethod().getReturnType();
1596 if (StringUtils.equals("void", methodReturnType.getName())) {
1597 finalizeMethodInvoker.invoke();
1598 } else {
1599 String renderOutput = (String) finalizeMethodInvoker.invoke();
1600
1601 component.setSelfRendered(true);
1602 component.setRenderedHtmlOutput(renderOutput);
1603 }
1604 } catch (Exception e) {
1605 LOG.error("Error invoking finalize method for component: " + component.getId(), e);
1606 throw new RuntimeException("Error invoking finalize method for component: " + component.getId(), e);
1607 }
1608 }
1609
1610
1611
1612
1613 @Override
1614 public void cleanViewAfterRender(View view) {
1615 ViewCleaner.cleanView(view);
1616 }
1617
1618
1619
1620
1621 public void refreshReferences(Object model, String referencesToRefresh) {
1622 for (String reference : StringUtils.split(referencesToRefresh, KRADConstants.REFERENCES_TO_REFRESH_SEPARATOR)) {
1623 if (StringUtils.isBlank(reference)) {
1624 continue;
1625 }
1626
1627
1628
1629 if (ObjectUtils.isNestedAttribute(reference)) {
1630 String parentPath = ObjectUtils.getNestedAttributePrefix(reference);
1631 Object parentObject = ObjectPropertyUtils.getPropertyValue(model, parentPath);
1632 String referenceObjectName = ObjectUtils.getNestedAttributePrimitive(reference);
1633
1634 if (parentObject == null) {
1635 LOG.warn("Unable to refresh references for " + referencesToRefresh +
1636 ". Object not found in model. Nothing refreshed.");
1637 continue;
1638 }
1639
1640 refreshReference(parentObject, referenceObjectName);
1641 } else {
1642 refreshReference(model, reference);
1643 }
1644 }
1645 }
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657 private void refreshReference(Object parentObject, String referenceObjectName) {
1658 if (!(parentObject instanceof PersistableBusinessObject)) {
1659 LOG.warn("Could not refresh reference " + referenceObjectName + " off class " + parentObject.getClass()
1660 .getName() + ". Class not of type PersistableBusinessObject");
1661 return;
1662 }
1663
1664 if (getPersistenceStructureService().hasReference(parentObject.getClass(), referenceObjectName)
1665 || getPersistenceStructureService().hasCollection(parentObject.getClass(), referenceObjectName)) {
1666
1667 getPersistenceService().retrieveReferenceObject(parentObject, referenceObjectName);
1668 } else if (getDataDictionaryService().hasRelationship(parentObject.getClass().getName(), referenceObjectName)) {
1669
1670 Object referenceObject = ObjectUtils.getPropertyValue(parentObject, referenceObjectName);
1671 if (!(referenceObject instanceof PersistableBusinessObject)) {
1672 LOG.warn("Could not refresh reference " + referenceObjectName + " off class " + parentObject.getClass()
1673 .getName() + ". Class not of type PersistableBusinessObject");
1674 return;
1675 }
1676
1677 referenceObject = getBusinessObjectService().retrieve((PersistableBusinessObject) referenceObject);
1678 if (referenceObject == null) {
1679 LOG.warn("Could not refresh reference " + referenceObjectName + " off class " + parentObject.getClass()
1680 .getName() + ".");
1681 return;
1682 }
1683
1684 try {
1685 ObjectUtils.setObjectProperty(parentObject, referenceObjectName, referenceObject);
1686 } catch (Exception e) {
1687 LOG.error("Unable to refresh persistable business object: " + referenceObjectName + "\n" + e
1688 .getMessage());
1689 throw new RuntimeException(
1690 "Unable to refresh persistable business object: " + referenceObjectName + "\n" + e
1691 .getMessage());
1692 }
1693 } else {
1694 LOG.warn("Could not refresh reference " + referenceObjectName + " off class " + parentObject.getClass()
1695 .getName() + ".");
1696 }
1697 }
1698
1699
1700
1701
1702
1703 @Override
1704 public void processCollectionAddLine(View view, Object model, String collectionPath) {
1705
1706 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1707 if (collectionGroup == null) {
1708 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
1709 }
1710
1711
1712 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
1713 if (collection == null) {
1714 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
1715 }
1716
1717
1718 String addLinePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
1719 Object addLine = ObjectPropertyUtils.getPropertyValue(model, addLinePath);
1720 if (addLine == null) {
1721 logAndThrowRuntime("Add line instance not found for path: " + addLinePath);
1722 }
1723
1724 processBeforeAddLine(view, collectionGroup, model, addLine);
1725
1726
1727 boolean isValidLine = performAddLineValidation(view, collectionGroup, model, addLine);
1728 if (isValidLine) {
1729
1730
1731
1732 addLine(collection, addLine, collectionGroup.getAddLinePlacement().equals("TOP"));
1733
1734
1735 collectionGroup.initializeNewCollectionLine(view, model, collectionGroup, true);
1736 }
1737
1738 ((UifFormBase) model).getAddedCollectionItems().add(addLine);
1739
1740 processAfterAddLine(view, collectionGroup, model, addLine, isValidLine);
1741 }
1742
1743
1744
1745
1746
1747 @Override
1748 public void processCollectionSaveLine(View view, Object model, String collectionPath, int selectedLineIndex) {
1749
1750 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1751 if (collectionGroup == null) {
1752 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
1753 }
1754
1755
1756 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
1757 if (collection == null) {
1758 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
1759 }
1760
1761
1762
1763 if (collection instanceof List) {
1764 Object saveLine = ((List<Object>) collection).get(selectedLineIndex);
1765
1766 processBeforeSaveLine(view, collectionGroup, model, saveLine);
1767
1768 ((UifFormBase) model).getAddedCollectionItems().remove(saveLine);
1769
1770 processAfterSaveLine(view, collectionGroup, model, saveLine);
1771
1772 } else {
1773 logAndThrowRuntime("Only List collection implementations are supported for the delete by index method");
1774 }
1775
1776 }
1777
1778
1779
1780
1781
1782 @Override
1783 public void processCollectionAddBlankLine(View view, Object model, String collectionPath) {
1784
1785 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1786 if (collectionGroup == null) {
1787 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
1788 }
1789
1790
1791 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
1792 if (collection == null) {
1793 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
1794 }
1795
1796 Object newLine = ObjectUtils.newInstance(collectionGroup.getCollectionObjectClass());
1797 applyDefaultValuesForCollectionLine(view, model, collectionGroup, newLine);
1798 addLine(collection, newLine, collectionGroup.getAddLinePlacement().equals("TOP"));
1799
1800 ((UifFormBase) model).getAddedCollectionItems().add(newLine);
1801 }
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811 protected void addLine(Collection<Object> collection, Object addLine, boolean insertFirst) {
1812 if (insertFirst && (collection instanceof List)) {
1813 ((List) collection).add(0, addLine);
1814 } else {
1815 collection.add(addLine);
1816 }
1817 }
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831 protected boolean performAddLineValidation(View view, CollectionGroup collectionGroup, Object model,
1832 Object addLine) {
1833 boolean isValid = true;
1834
1835
1836
1837
1838 return isValid;
1839 }
1840
1841
1842
1843
1844
1845 public void processCollectionDeleteLine(View view, Object model, String collectionPath, int lineIndex) {
1846
1847 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1848 if (collectionGroup == null) {
1849 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
1850 }
1851
1852
1853 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
1854 if (collection == null) {
1855 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
1856 }
1857
1858
1859
1860 if (collection instanceof List) {
1861 Object deleteLine = ((List<Object>) collection).get(lineIndex);
1862
1863
1864 boolean isValid = performDeleteLineValidation(view, collectionGroup, deleteLine);
1865 if (isValid) {
1866 ((List<Object>) collection).remove(lineIndex);
1867 processAfterDeleteLine(view, collectionGroup, model, lineIndex);
1868 }
1869 } else {
1870 logAndThrowRuntime("Only List collection implementations are supported for the delete by index method");
1871 }
1872 }
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884 protected boolean performDeleteLineValidation(View view, CollectionGroup collectionGroup, Object deleteLine) {
1885 boolean isValid = true;
1886
1887
1888
1889
1890 return isValid;
1891 }
1892
1893
1894
1895
1896 public void processMultipleValueLookupResults(View view, Object model, String collectionPath,
1897 String lookupResultValues) {
1898
1899 if (StringUtils.isBlank(lookupResultValues)) {
1900 return;
1901 }
1902
1903
1904 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1905 if (collectionGroup == null) {
1906 throw new RuntimeException("Unable to find collection group for path: " + collectionPath);
1907 }
1908
1909 Class<?> collectionObjectClass = collectionGroup.getCollectionObjectClass();
1910 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model,
1911 collectionGroup.getBindingInfo().getBindingPath());
1912 if (collection == null) {
1913 Class<?> collectionClass = ObjectPropertyUtils.getPropertyType(model,
1914 collectionGroup.getBindingInfo().getBindingPath());
1915 collection = (Collection<Object>) ObjectUtils.newInstance(collectionClass);
1916 ObjectPropertyUtils.setPropertyValue(model, collectionGroup.getBindingInfo().getBindingPath(), collection);
1917 }
1918
1919 Map<String, String> fieldConversions = collectionGroup.getCollectionLookup().getFieldConversions();
1920 List<String> toFieldNamesColl = new ArrayList(fieldConversions.values());
1921 Collections.sort(toFieldNamesColl);
1922 String[] toFieldNames = new String[toFieldNamesColl.size()];
1923 toFieldNamesColl.toArray(toFieldNames);
1924
1925
1926 String[] lineValues = StringUtils.split(lookupResultValues, ",");
1927
1928
1929 for (String lineValue : lineValues) {
1930 Object lineDataObject = null;
1931
1932
1933 ModuleService moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
1934 collectionObjectClass);
1935 if (moduleService != null && moduleService.isExternalizable(collectionObjectClass)) {
1936 lineDataObject = moduleService.createNewObjectFromExternalizableClass(collectionObjectClass.asSubclass(
1937 ExternalizableBusinessObject.class));
1938 } else {
1939 lineDataObject = ObjectUtils.newInstance(collectionObjectClass);
1940 }
1941
1942
1943 applyDefaultValuesForCollectionLine(view, model, collectionGroup, lineDataObject);
1944
1945 String[] fieldValues = StringUtils.splitByWholeSeparatorPreserveAllTokens(lineValue, ":");
1946 if (fieldValues.length != toFieldNames.length) {
1947 throw new RuntimeException(
1948 "Value count passed back from multi-value lookup does not match field conversion count");
1949 }
1950
1951
1952 for (int i = 0; i < fieldValues.length; i++) {
1953 String fieldName = toFieldNames[i];
1954 ObjectPropertyUtils.setPropertyValue(lineDataObject, fieldName, fieldValues[i]);
1955 }
1956
1957
1958
1959 collection.add(lineDataObject);
1960 }
1961 }
1962
1963
1964
1965
1966
1967
1968
1969
1970 public void buildInquiryLink(Object dataObject, String propertyName, Inquiry inquiry) {
1971 Inquirable inquirable = getViewDictionaryService().getInquirable(dataObject.getClass(), inquiry.getViewName());
1972 if (inquirable != null) {
1973 inquirable.buildInquirableLink(dataObject, propertyName, inquiry);
1974 } else {
1975
1976
1977
1978 inquiry.setRender(false);
1979 }
1980 }
1981
1982
1983
1984
1985
1986
1987 public void applyDefaultValuesForCollectionLine(View view, Object model, CollectionGroup collectionGroup,
1988 Object line) {
1989
1990 List<DataField> dataFields = ComponentUtils.getComponentsOfTypeDeep(collectionGroup.getAddLineItems(),
1991 DataField.class);
1992 for (DataField dataField : dataFields) {
1993 String bindingPath = "";
1994 if (StringUtils.isNotBlank(dataField.getBindingInfo().getBindByNamePrefix())) {
1995 bindingPath = dataField.getBindingInfo().getBindByNamePrefix() + ".";
1996 }
1997 bindingPath += dataField.getBindingInfo().getBindingName();
1998
1999 populateDefaultValueForField(view, line, dataField, bindingPath);
2000 }
2001 }
2002
2003
2004
2005
2006
2007
2008
2009
2010 protected void applyDefaultValues(View view, Component component, Object model) {
2011 if (component == null) {
2012 return;
2013 }
2014
2015
2016 if (component instanceof DataField) {
2017 DataField dataField = ((DataField) component);
2018
2019
2020 dataField.getBindingInfo().setDefaults(view, dataField.getPropertyName());
2021
2022 populateDefaultValueForField(view, model, dataField, dataField.getBindingInfo().getBindingPath());
2023 }
2024
2025 List<Component> nestedComponents = component.getComponentsForLifecycle();
2026
2027
2028 if (component instanceof View) {
2029 nestedComponents.addAll(((View) component).getItems());
2030 }
2031
2032 for (Component nested : nestedComponents) {
2033 applyDefaultValues(view, nested, model);
2034 }
2035 }
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053 protected void populateDefaultValueForField(View view, Object object, DataField dataField, String bindingPath) {
2054
2055 String defaultValue = dataField.getDefaultValue();
2056 Object[] defaultValues = dataField.getDefaultValues();
2057
2058 if (StringUtils.isBlank(defaultValue) && defaultValues != null && defaultValues.length > 0) {
2059 ObjectPropertyUtils.setPropertyValue(object, bindingPath, defaultValues);
2060 } else {
2061 if (StringUtils.isBlank(defaultValue) && (dataField.getDefaultValueFinderClass() != null)) {
2062 ValueFinder defaultValueFinder = ObjectUtils.newInstance(dataField.getDefaultValueFinderClass());
2063 defaultValue = defaultValueFinder.getValue();
2064 }
2065
2066
2067 if (StringUtils.isNotBlank(defaultValue) && ObjectPropertyUtils.isWritableProperty(object, bindingPath)) {
2068 if (getExpressionEvaluator().containsElPlaceholder(defaultValue)) {
2069 Map<String, Object> context = getPreModelContext(view);
2070 defaultValue = getExpressionEvaluator().evaluateExpressionTemplate(context, defaultValue);
2071 }
2072
2073
2074
2075 Object currentValue = ObjectPropertyUtils.getPropertyValue(object, bindingPath);
2076 Class currentClazz = ObjectPropertyUtils.getPropertyType(object, bindingPath);
2077 if (currentValue == null || StringUtils.isBlank(currentValue.toString()) ||
2078 ClassUtils.isPrimitiveOrWrapper(currentClazz)) {
2079 ObjectPropertyUtils.setPropertyValue(object, bindingPath, defaultValue);
2080 }
2081 }
2082 }
2083 }
2084
2085
2086
2087
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102 protected void addCustomContainerComponents(View view, Object model, Container container) {
2103
2104 }
2105
2106
2107
2108
2109
2110
2111
2112
2113 protected void performCustomInitialization(View view, Component component) {
2114
2115 }
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126 protected void performCustomApplyModel(View view, Component component, Object model) {
2127
2128 }
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138 protected void performCustomFinalize(View view, Component component, Object model, Component parent) {
2139
2140 }
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153 protected void processBeforeAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
2154
2155 }
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169 protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine,
2170 boolean isValidLine) {
2171
2172 }
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184 protected void processBeforeSaveLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
2185
2186 }
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198 protected void processAfterSaveLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
2199
2200 }
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211 protected void processAfterDeleteLine(View view, CollectionGroup collectionGroup, Object model, int lineIndex) {
2212
2213 }
2214
2215
2216
2217
2218
2219
2220 protected void logAndThrowRuntime(String message) {
2221 LOG.error(message);
2222 throw new RuntimeException(message);
2223 }
2224
2225
2226
2227
2228
2229
2230 public BusinessObjectService getBusinessObjectService() {
2231 if (this.businessObjectService == null) {
2232 this.businessObjectService = KRADServiceLocator.getBusinessObjectService();
2233 }
2234 return businessObjectService;
2235 }
2236
2237
2238
2239
2240
2241
2242 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
2243 this.businessObjectService = businessObjectService;
2244 }
2245
2246
2247
2248
2249
2250
2251 public PersistenceService getPersistenceService() {
2252 if (this.persistenceService == null) {
2253 this.persistenceService = KRADServiceLocator.getPersistenceService();
2254 }
2255
2256 return this.persistenceService;
2257 }
2258
2259
2260
2261
2262
2263
2264 public void setPersistenceService(PersistenceService persistenceService) {
2265 this.persistenceService = persistenceService;
2266 }
2267
2268
2269
2270
2271
2272
2273 public PersistenceStructureService getPersistenceStructureService() {
2274 if (this.persistenceStructureService == null) {
2275 this.persistenceStructureService = KRADServiceLocator.getPersistenceStructureService();
2276 }
2277 return this.persistenceStructureService;
2278 }
2279
2280
2281
2282
2283
2284
2285 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
2286 this.persistenceStructureService = persistenceStructureService;
2287 }
2288
2289
2290
2291
2292
2293
2294 protected DataDictionaryService getDataDictionaryService() {
2295 if (this.dataDictionaryService == null) {
2296 this.dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
2297 }
2298
2299 return this.dataDictionaryService;
2300 }
2301
2302
2303
2304
2305
2306
2307 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
2308 this.dataDictionaryService = dataDictionaryService;
2309 }
2310
2311
2312
2313
2314
2315
2316 public ExpressionEvaluator getExpressionEvaluator() {
2317 if (this.expressionEvaluator == null) {
2318 this.expressionEvaluator = new DefaultExpressionEvaluator();
2319 }
2320
2321 return this.expressionEvaluator;
2322 }
2323
2324
2325
2326
2327
2328
2329 public void setExpressionEvaluator(ExpressionEvaluator expressionEvaluator) {
2330 this.expressionEvaluator = expressionEvaluator;
2331 }
2332
2333
2334
2335
2336
2337
2338 public ViewDictionaryService getViewDictionaryService() {
2339 if (this.viewDictionaryService == null) {
2340 this.viewDictionaryService = KRADServiceLocatorWeb.getViewDictionaryService();
2341 }
2342 return this.viewDictionaryService;
2343 }
2344
2345
2346
2347
2348
2349
2350 public void setViewDictionaryService(ViewDictionaryService viewDictionaryService) {
2351 this.viewDictionaryService = viewDictionaryService;
2352 }
2353
2354
2355
2356
2357
2358
2359 public ConfigurationService getConfigurationService() {
2360 if (this.configurationService == null) {
2361 this.configurationService = CoreApiServiceLocator.getKualiConfigurationService();
2362 }
2363 return this.configurationService;
2364 }
2365
2366
2367
2368
2369
2370
2371 public void setConfigurationService(ConfigurationService configurationService) {
2372 this.configurationService = configurationService;
2373 }
2374 }