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.exception.RiceRuntimeException;
20 import org.kuali.rice.kim.api.identity.Person;
21 import org.kuali.rice.krad.bo.ExternalizableBusinessObject;
22 import org.kuali.rice.krad.datadictionary.AttributeDefinition;
23 import org.kuali.rice.krad.inquiry.Inquirable;
24 import org.kuali.rice.krad.service.DataDictionaryService;
25 import org.kuali.rice.krad.service.KRADServiceLocator;
26 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
27 import org.kuali.rice.krad.service.ModuleService;
28 import org.kuali.rice.krad.uif.UifConstants;
29 import org.kuali.rice.krad.uif.authorization.Authorizer;
30 import org.kuali.rice.krad.uif.authorization.PresentationController;
31 import org.kuali.rice.krad.uif.component.BindingInfo;
32 import org.kuali.rice.krad.uif.component.ClientSideState;
33 import org.kuali.rice.krad.uif.component.Component;
34 import org.kuali.rice.krad.uif.component.DataBinding;
35 import org.kuali.rice.krad.uif.component.PropertyReplacer;
36 import org.kuali.rice.krad.uif.component.RequestParameter;
37 import org.kuali.rice.krad.uif.container.CollectionGroup;
38 import org.kuali.rice.krad.uif.container.Container;
39 import org.kuali.rice.krad.uif.control.Control;
40 import org.kuali.rice.krad.uif.field.DataField;
41 import org.kuali.rice.krad.uif.field.InputField;
42 import org.kuali.rice.krad.uif.field.Field;
43 import org.kuali.rice.krad.uif.field.RemoteFieldsHolder;
44 import org.kuali.rice.krad.uif.layout.LayoutManager;
45 import org.kuali.rice.krad.uif.modifier.ComponentModifier;
46 import org.kuali.rice.krad.uif.service.ExpressionEvaluatorService;
47 import org.kuali.rice.krad.uif.service.ViewDictionaryService;
48 import org.kuali.rice.krad.uif.service.ViewHelperService;
49 import org.kuali.rice.krad.uif.util.BooleanMap;
50 import org.kuali.rice.krad.uif.util.CloneUtils;
51 import org.kuali.rice.krad.uif.util.ComponentFactory;
52 import org.kuali.rice.krad.uif.util.ComponentUtils;
53 import org.kuali.rice.krad.uif.util.ExpressionUtils;
54 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
55 import org.kuali.rice.krad.uif.util.ScriptUtils;
56 import org.kuali.rice.krad.uif.util.ViewModelUtils;
57 import org.kuali.rice.krad.uif.view.View;
58 import org.kuali.rice.krad.uif.view.ViewModel;
59 import org.kuali.rice.krad.uif.widget.Inquiry;
60 import org.kuali.rice.krad.util.GlobalVariables;
61 import org.kuali.rice.krad.util.KRADConstants;
62 import org.kuali.rice.krad.util.ObjectUtils;
63 import org.kuali.rice.krad.valuefinder.ValueFinder;
64 import org.kuali.rice.krad.web.form.UifFormBase;
65 import org.springframework.util.MethodInvoker;
66
67 import java.io.Serializable;
68 import java.lang.annotation.Annotation;
69 import java.util.ArrayList;
70 import java.util.Collection;
71 import java.util.Collections;
72 import java.util.HashMap;
73 import java.util.HashSet;
74 import java.util.List;
75 import java.util.Map;
76 import java.util.Map.Entry;
77 import java.util.Set;
78
79
80
81
82
83
84 public class ViewHelperServiceImpl implements ViewHelperService, Serializable {
85 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ViewHelperServiceImpl.class);
86
87 private transient DataDictionaryService dataDictionaryService;
88 private transient ExpressionEvaluatorService expressionEvaluatorService;
89 private transient ViewDictionaryService viewDictionaryService;
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105 @Override
106 public void populateViewFromRequestParameters(View view, Map<String, String> parameters) {
107
108
109 Map<String, Set<PropertyReplacer>> viewPropertyReplacers = new HashMap<String, Set<PropertyReplacer>>();
110 for (PropertyReplacer replacer : view.getPropertyReplacers()) {
111 Set<PropertyReplacer> propertyReplacers = new HashSet<PropertyReplacer>();
112 if (viewPropertyReplacers.containsKey(replacer.getPropertyName())) {
113 propertyReplacers = viewPropertyReplacers.get(replacer.getPropertyName());
114 }
115 propertyReplacers.add(replacer);
116
117 viewPropertyReplacers.put(replacer.getPropertyName(), propertyReplacers);
118 }
119
120 Map<String, Annotation> annotatedFields = CloneUtils.getFieldsWithAnnotation(view.getClass(),
121 RequestParameter.class);
122
123
124
125 Map<String, String> viewRequestParameters = new HashMap<String, String>();
126 for (String fieldToPopulate : annotatedFields.keySet()) {
127 RequestParameter requestParameter = (RequestParameter) annotatedFields.get(fieldToPopulate);
128
129
130 String requestParameterName = requestParameter.parameterName();
131 if (StringUtils.isBlank(requestParameterName)) {
132 requestParameterName = fieldToPopulate;
133 }
134
135 if (!parameters.containsKey(requestParameterName)) {
136 continue;
137 }
138
139 String fieldValue = parameters.get(requestParameterName);
140 if (StringUtils.isNotBlank(fieldValue)) {
141 viewRequestParameters.put(requestParameterName, fieldValue);
142 ObjectPropertyUtils.setPropertyValue(view, fieldToPopulate, fieldValue);
143
144
145
146 if (view.getPropertyExpressions().containsKey(fieldToPopulate)) {
147 view.getPropertyExpressions().remove(fieldToPopulate);
148 }
149
150 if (viewPropertyReplacers.containsKey(fieldToPopulate)) {
151 Set<PropertyReplacer> propertyReplacers = viewPropertyReplacers.get(fieldToPopulate);
152 for (PropertyReplacer replacer : propertyReplacers) {
153 view.getPropertyReplacers().remove(replacer);
154 }
155 }
156 }
157 }
158
159 view.setViewRequestParameters(viewRequestParameters);
160 }
161
162
163
164
165
166 @Override
167 public void performInitialization(View view, Object model) {
168 view.assignComponentIds(view);
169 performComponentInitialization(view, model, view);
170 }
171
172
173
174
175
176
177
178
179
180
181
182
183 public void performComponentLifecycle(View view, Object model, Component component, String origId) {
184 Component origComponent = view.getViewIndex().getComponentById(origId);
185
186 Component parent = (Component) origComponent.getContext().get(UifConstants.ContextVariableNames.PARENT);
187 component.pushAllToContext(origComponent.getContext());
188
189
190 String suffix = StringUtils.replaceOnce(origComponent.getId(), origComponent.getFactoryId(), "");
191
192 if (suffix.endsWith(UifConstants.IdSuffixes.ATTRIBUTE)) {
193 suffix = StringUtils.removeEnd(suffix, UifConstants.IdSuffixes.ATTRIBUTE);
194 }
195 ComponentUtils.updateIdsWithSuffix(component, suffix);
196
197
198 if (component instanceof DataBinding) {
199 ((DataBinding) component).setBindingInfo(((DataBinding) origComponent).getBindingInfo());
200 ((DataBinding) component).getBindingInfo().setBindingPath(
201 ((DataBinding) origComponent).getBindingInfo().getBindingPath());
202 }
203
204
205 if (component instanceof Field) {
206 ((Field) component).setLabelFieldRendered(((Field) origComponent).isLabelFieldRendered());
207 } else if (component instanceof CollectionGroup) {
208 ((CollectionGroup) component).setSubCollectionSuffix(
209 ((CollectionGroup) origComponent).getSubCollectionSuffix());
210 }
211
212
213 if (component.isResetDataOnRefresh()) {
214
215 if (component instanceof DataField) {
216
217
218
219 ObjectPropertyUtils.initializeProperty(model,
220 ((DataField) component).getBindingInfo().getBindingPath());
221 }
222 }
223
224 performComponentInitialization(view, model, component);
225 performComponentApplyModel(view, component, model);
226
227
228 Map<String, Object> clientState = new HashMap<String, Object>();
229 performComponentFinalize(view, component, model, parent, clientState);
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253 String clientStateScript = buildClientSideStateScript(view, clientState, true);
254 String onLoadScript = component.getOnLoadScript();
255 if (StringUtils.isNotBlank(onLoadScript)) {
256 clientStateScript = onLoadScript + clientStateScript;
257 }
258 component.setOnLoadScript(clientStateScript);
259
260
261 view.getViewIndex().indexComponent(component);
262 }
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289 public void performComponentInitialization(View view, Object model, Component component) {
290 if (component == null) {
291 return;
292 }
293
294 if (StringUtils.isBlank(component.getId()) || StringUtils.isBlank(component.getFactoryId())) {
295 throw new RiceRuntimeException("Ids are not set, this should happen unless a component is misconfigured");
296 }
297
298
299
300 LOG.debug("Initializing component: " + component.getId() + " with type: " + component.getClass());
301
302
303 component.performInitialization(view, model);
304
305
306 if (component instanceof DataField) {
307 initializeDataFieldFromDataDictionary(view, (DataField) component);
308 }
309
310
311 view.getViewIndex().addInitialComponentState(component);
312
313 if (component instanceof Container) {
314 LayoutManager layoutManager = ((Container) component).getLayoutManager();
315
316
317 addCustomContainerComponents(view, model, (Container) component);
318
319
320 processAnyRemoteFieldsHolder(view, model, (Container) component);
321 }
322
323
324 if (component instanceof CollectionGroup) {
325
326 }
327
328
329 runComponentModifiers(view, component, null, UifConstants.ViewPhases.INITIALIZE);
330
331
332 for (Component nestedComponent : component.getComponentsForLifecycle()) {
333 performComponentInitialization(view, model, nestedComponent);
334 }
335
336
337 for (PropertyReplacer replacer : component.getPropertyReplacers()) {
338 for (Component replacerComponent : replacer.getNestedComponents()) {
339 performComponentInitialization(view, model, replacerComponent);
340 }
341 }
342
343
344 performCustomInitialization(view, component);
345 }
346
347
348
349
350
351
352
353
354
355
356 protected void processAnyRemoteFieldsHolder(View view, Object model, Container container) {
357 List<Component> processedItems = new ArrayList<Component>();
358
359
360
361 for (Component item : container.getItems()) {
362 if (item instanceof RemoteFieldsHolder) {
363 List<InputField> translatedFields = ((RemoteFieldsHolder) item).fetchAndTranslateRemoteFields(view,
364 model, container);
365 processedItems.addAll(translatedFields);
366 } else {
367 processedItems.add(item);
368 }
369 }
370
371
372 container.setItems(processedItems);
373 }
374
375
376
377
378
379
380
381
382 protected void initializeDataFieldFromDataDictionary(View view, DataField field) {
383 AttributeDefinition attributeDefinition = null;
384
385 String dictionaryAttributeName = field.getDictionaryAttributeName();
386 String dictionaryObjectEntry = field.getDictionaryObjectEntry();
387
388
389
390 if (StringUtils.isNotBlank(dictionaryObjectEntry) && StringUtils.isBlank(dictionaryAttributeName)) {
391 dictionaryAttributeName = field.getPropertyName();
392 }
393
394
395 if (StringUtils.isNotBlank(dictionaryAttributeName) && StringUtils.isNotBlank(dictionaryObjectEntry)) {
396 attributeDefinition = getDataDictionaryService().getAttributeDefinition(dictionaryObjectEntry,
397 dictionaryAttributeName);
398 }
399
400
401 if (attributeDefinition == null) {
402 String propertyPath = field.getBindingInfo().getBindingPath();
403 if (StringUtils.isNotBlank(field.getBindingInfo().getCollectionPath())) {
404 propertyPath = field.getBindingInfo().getCollectionPath();
405 if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
406 propertyPath += "." + field.getBindingInfo().getBindByNamePrefix();
407 }
408 propertyPath += "." + field.getBindingInfo().getBindingName();
409 }
410
411 attributeDefinition = findNestedDictionaryAttribute(view, field, null, propertyPath);
412 }
413
414
415 if (attributeDefinition != null) {
416 field.copyFromAttributeDefinition(view, attributeDefinition);
417 }
418
419
420 if (field instanceof InputField) {
421 InputField inputField = (InputField) field;
422 if (inputField.getControl() == null) {
423 Control control = ComponentFactory.getTextControl();
424 control.setId(view.getNextId());
425 control.setFactoryId(control.getId());
426
427 inputField.setControl(control);
428 }
429 }
430 }
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457 protected AttributeDefinition findNestedDictionaryAttribute(View view, DataField field, String parentPath,
458 String propertyPath) {
459 AttributeDefinition attributeDefinition = null;
460
461
462 String dictionaryAttributeName = propertyPath;
463 String dictionaryObjectEntry = null;
464
465 if (field.getBindingInfo().isBindToMap()) {
466 parentPath = "";
467 if (!field.getBindingInfo().isBindToForm() && StringUtils.isNotBlank(
468 field.getBindingInfo().getBindingObjectPath())) {
469 parentPath = field.getBindingInfo().getBindingObjectPath();
470 }
471 if (StringUtils.isNotBlank(field.getBindingInfo().getBindByNamePrefix())) {
472 if (StringUtils.isNotBlank(parentPath)) {
473 parentPath += "." + field.getBindingInfo().getBindByNamePrefix();
474 } else {
475 parentPath = field.getBindingInfo().getBindByNamePrefix();
476 }
477 }
478
479 dictionaryAttributeName = field.getBindingInfo().getBindingName();
480 }
481
482 if (StringUtils.isNotBlank(parentPath)) {
483 Class<?> dictionaryModelClass = ViewModelUtils.getPropertyTypeByClassAndView(view, parentPath);
484 if (dictionaryModelClass != null) {
485 dictionaryObjectEntry = dictionaryModelClass.getName();
486
487 attributeDefinition = getDataDictionaryService().getAttributeDefinition(dictionaryObjectEntry,
488 dictionaryAttributeName);
489 }
490 }
491
492
493
494 if ((attributeDefinition == null) && StringUtils.contains(propertyPath, ".")) {
495 String nextParentPath = StringUtils.substringBefore(propertyPath, ".");
496 if (StringUtils.isNotBlank(parentPath)) {
497 nextParentPath = parentPath + "." + nextParentPath;
498 }
499 String nextPropertyPath = StringUtils.substringAfter(propertyPath, ".");
500
501 return findNestedDictionaryAttribute(view, field, nextParentPath, nextPropertyPath);
502 }
503
504
505 if (attributeDefinition != null) {
506 field.setDictionaryAttributeName(dictionaryAttributeName);
507 field.setDictionaryObjectEntry(dictionaryObjectEntry);
508 }
509
510 return attributeDefinition;
511 }
512
513
514
515
516
517 @Override
518 public void performApplyModel(View view, Object model) {
519
520
521 invokeAuthorizerPresentationController(view, (UifFormBase) model);
522
523
524 setViewContext(view, model);
525
526 performComponentApplyModel(view, view, model);
527 }
528
529
530
531
532
533
534
535
536
537
538 protected void invokeAuthorizerPresentationController(View view, UifFormBase model) {
539 PresentationController presentationController = ObjectUtils.newInstance(view.getPresentationControllerClass());
540 Authorizer authorizer = ObjectUtils.newInstance(view.getAuthorizerClass());
541
542 Person user = GlobalVariables.getUserSession().getPerson();
543
544 Set<String> actionFlags = presentationController.getActionFlags(model);
545 actionFlags = authorizer.getActionFlags(model, user, actionFlags);
546
547 view.setActionFlags(new BooleanMap(actionFlags));
548
549 Set<String> editModes = presentationController.getEditModes(model);
550 editModes = authorizer.getEditModes(model, user, editModes);
551
552 view.setEditModes(new BooleanMap(editModes));
553 }
554
555
556
557
558
559
560
561
562 protected void setViewContext(View view, Object model) {
563 view.pushAllToContext(getPreModelContext(view));
564
565
566 for (Entry<String, String> variableExpression : view.getExpressionVariables().entrySet()) {
567 String variableName = variableExpression.getKey();
568 Object value = getExpressionEvaluatorService().evaluateExpression(model, view.getContext(),
569 variableExpression.getValue());
570 view.pushObjectToContext(variableName, value);
571 }
572 }
573
574
575
576
577
578
579
580
581 protected Map<String, Object> getPreModelContext(View view) {
582 Map<String, Object> context = new HashMap<String, Object>();
583
584 context.put(UifConstants.ContextVariableNames.VIEW, view);
585 context.put(UifConstants.ContextVariableNames.VIEW_HELPER, this);
586
587 Map<String, String> properties = KRADServiceLocator.getKualiConfigurationService().getAllProperties();
588 context.put(UifConstants.ContextVariableNames.CONFIG_PROPERTIES, properties);
589 context.put(UifConstants.ContextVariableNames.CONSTANTS, KRADConstants.class);
590
591 return context;
592 }
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609 protected void performComponentApplyModel(View view, Component component, Object model) {
610 if (component == null) {
611 return;
612 }
613
614
615 component.pushAllToContext(getCommonContext(view, component));
616 ExpressionUtils.adjustPropertyExpressions(view, component);
617 getExpressionEvaluatorService().evaluateObjectExpressions(component, model, component.getContext());
618
619 if (component instanceof Container) {
620 LayoutManager layoutManager = ((Container) component).getLayoutManager();
621
622 if (layoutManager != null) {
623 layoutManager.getContext().putAll(getCommonContext(view, component));
624 layoutManager.pushObjectToContext(UifConstants.ContextVariableNames.PARENT, component);
625 layoutManager.pushObjectToContext(UifConstants.ContextVariableNames.MANAGER, layoutManager);
626
627 ExpressionUtils.adjustPropertyExpressions(view, layoutManager);
628 getExpressionEvaluatorService().evaluateObjectExpressions(layoutManager, model,
629 layoutManager.getContext());
630 }
631 }
632
633 if (component instanceof DataBinding) {
634 BindingInfo bindingInfo = ((DataBinding) component).getBindingInfo();
635 ExpressionUtils.adjustPropertyExpressions(view, bindingInfo);
636 getExpressionEvaluatorService().evaluateObjectExpressions(bindingInfo, model, component.getContext());
637 }
638
639
640 syncClientSideStateForComponent(component, ((UifFormBase) model).getClientStateForSyncing());
641
642
643 Component parent = (Component) component.getContext().get(UifConstants.ContextVariableNames.PARENT);
644 component.performApplyModel(view, model, parent);
645
646
647 performCustomApplyModel(view, component, model);
648
649
650 runComponentModifiers(view, component, model, UifConstants.ViewPhases.APPLY_MODEL);
651
652
653 for (Component nestedComponent : component.getComponentsForLifecycle()) {
654 if (nestedComponent != null) {
655 nestedComponent.pushObjectToContext(UifConstants.ContextVariableNames.PARENT, component);
656 }
657
658 performComponentApplyModel(view, nestedComponent, model);
659 }
660 }
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677 protected void runComponentModifiers(View view, Component component, Object model, String runPhase) {
678 for (ComponentModifier modifier : component.getComponentModifiers()) {
679
680 if (StringUtils.equals(runPhase, UifConstants.ViewPhases.INITIALIZE)) {
681 modifier.performInitialization(view, model, component);
682 }
683
684
685 if (StringUtils.equals(modifier.getRunPhase(), runPhase)) {
686
687 boolean runModifier = true;
688 if (StringUtils.isNotBlank(modifier.getRunCondition())) {
689 Map<String, Object> context = new HashMap<String, Object>();
690 context.put(UifConstants.ContextVariableNames.COMPONENT, component);
691 context.put(UifConstants.ContextVariableNames.VIEW, view);
692
693 String conditionEvaluation = getExpressionEvaluatorService().evaluateExpressionTemplate(model,
694 context, modifier.getRunCondition());
695 runModifier = Boolean.parseBoolean(conditionEvaluation);
696 }
697
698 if (runModifier) {
699 modifier.performModification(view, model, component);
700 }
701 }
702 }
703 }
704
705
706
707
708
709
710
711
712 protected Map<String, Object> getCommonContext(View view, Component component) {
713 Map<String, Object> context = new HashMap<String, Object>();
714
715 context.putAll(view.getContext());
716 context.put(UifConstants.ContextVariableNames.COMPONENT, component);
717
718 return context;
719 }
720
721
722
723
724
725 @Override
726 public void performFinalize(View view, Object model) {
727 Map<String, Object> clientState = new HashMap<String, Object>();
728 performComponentFinalize(view, view, model, null, clientState);
729
730 String clientStateScript = buildClientSideStateScript(view, clientState, false);
731 String viewPreLoadScript = view.getPreLoadScript();
732 if (StringUtils.isNotBlank(viewPreLoadScript)) {
733 clientStateScript = viewPreLoadScript + clientStateScript;
734 }
735 view.setPreLoadScript(clientStateScript);
736
737
738 ((ViewModel) model).setDefaultsApplied(true);
739 }
740
741
742
743
744
745
746
747
748
749
750
751
752 protected String buildClientSideStateScript(View view, Map<String, Object> clientSideState, boolean updateOnly) {
753
754
755
756 for (Entry<String, Object> additionalState : view.getClientSideState().entrySet()) {
757 if (!clientSideState.containsKey(additionalState.getKey())) {
758 clientSideState.put(additionalState.getKey(), additionalState.getValue());
759 } else {
760 Object state = clientSideState.get(additionalState.getKey());
761 Object mergeState = additionalState.getValue();
762 if ((state instanceof Map) && (mergeState instanceof Map)) {
763 ((Map) state).putAll((Map) mergeState);
764 } else {
765 clientSideState.put(additionalState.getKey(), additionalState.getValue());
766 }
767 }
768 }
769
770
771 String clientStateScript = "";
772 if (!clientSideState.isEmpty()) {
773 if (updateOnly) {
774 clientStateScript = "updateViewState({";
775 } else {
776 clientStateScript = "initializeViewState({";
777 }
778
779 for (Entry<String, Object> stateEntry : clientSideState.entrySet()) {
780 clientStateScript += "'" + stateEntry.getKey() + "':";
781 clientStateScript += ScriptUtils.translateValue(stateEntry.getValue());
782 clientStateScript += ",";
783 }
784 clientStateScript = StringUtils.removeEnd(clientStateScript, ",");
785 clientStateScript += "});";
786 }
787
788
789 if (!updateOnly) {
790 String kradImageLocation = KRADServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
791 "krad.externalizable.images.url");
792 clientStateScript += "setConfigParam('"
793 + UifConstants.ClientSideVariables.KRAD_IMAGE_LOCATION
794 + "','"
795 + kradImageLocation
796 + "');";
797 }
798
799 return clientStateScript;
800 }
801
802
803
804
805
806
807
808
809
810
811
812 protected void performComponentFinalize(View view, Component component, Object model, Component parent,
813 Map<String, Object> clientSideState) {
814 if (component == null) {
815 return;
816 }
817
818
819 ViewModel viewModel = (ViewModel) model;
820 if ((component instanceof DataBinding) && view.isSupportsReadOnlyFieldsOverride() && !viewModel
821 .getReadOnlyFieldsList().isEmpty()) {
822 String propertyName = ((DataBinding) component).getPropertyName();
823 if (viewModel.getReadOnlyFieldsList().contains(propertyName)) {
824 component.setReadOnly(true);
825 }
826 }
827
828
829 invokeMethodFinalizer(view, component, model);
830
831
832 component.performFinalize(view, model, parent);
833
834
835 addClientSideStateForComponent(component, clientSideState);
836
837
838 performCustomFinalize(view, component, model, parent);
839
840
841 runComponentModifiers(view, component, model, UifConstants.ViewPhases.FINALIZE);
842
843
844 if ((component instanceof DataField) && !((ViewModel) model).isDefaultsApplied()) {
845 populateDefaultValueForField(view, model, (DataField) component,
846 ((DataField) component).getBindingInfo().getBindingPath());
847 }
848
849
850 for (Component nestedComponent : component.getComponentsForLifecycle()) {
851 performComponentFinalize(view, nestedComponent, model, component, clientSideState);
852 }
853 }
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869 protected void addClientSideStateForComponent(Component component, Map<String, Object> clientSideState) {
870 Map<String, Annotation> annotatedFields = CloneUtils.getFieldsWithAnnotation(component.getClass(),
871 ClientSideState.class);
872
873 if (!annotatedFields.isEmpty()) {
874 Map<String, Object> componentClientState = null;
875 if (component instanceof View) {
876 componentClientState = clientSideState;
877 } else {
878 if (clientSideState.containsKey(component.getId())) {
879 componentClientState = (Map<String, Object>) clientSideState.get(component.getId());
880 } else {
881 componentClientState = new HashMap<String, Object>();
882 clientSideState.put(component.getId(), componentClientState);
883 }
884 }
885
886 for (Entry<String, Annotation> annotatedField : annotatedFields.entrySet()) {
887 ClientSideState clientSideStateAnnot = (ClientSideState) annotatedField.getValue();
888
889 String variableName = clientSideStateAnnot.variableName();
890 if (StringUtils.isBlank(variableName)) {
891 variableName = annotatedField.getKey();
892 }
893
894 Object value = ObjectPropertyUtils.getPropertyValue(component, annotatedField.getKey());
895 componentClientState.put(variableName, value);
896 }
897 }
898 }
899
900
901
902
903
904
905
906
907 protected void syncClientSideStateForComponent(Component component, Map<String, Object> clientSideState) {
908
909 Map<String, Object> componentState = null;
910 if (component instanceof View) {
911 componentState = clientSideState;
912 } else {
913 if (clientSideState.containsKey(component.getId())) {
914 componentState = (Map<String, Object>) clientSideState.get(component.getId());
915 }
916 }
917
918
919 if ((componentState != null) && (!componentState.isEmpty())) {
920 Map<String, Annotation> annotatedFields = CloneUtils.getFieldsWithAnnotation(component.getClass(),
921 ClientSideState.class);
922
923 for (Entry<String, Annotation> annotatedField : annotatedFields.entrySet()) {
924 ClientSideState clientSideStateAnnot = (ClientSideState) annotatedField.getValue();
925
926 String variableName = clientSideStateAnnot.variableName();
927 if (StringUtils.isBlank(variableName)) {
928 variableName = annotatedField.getKey();
929 }
930
931 if (componentState.containsKey(variableName)) {
932 Object value = componentState.get(variableName);
933 ObjectPropertyUtils.setPropertyValue(component, annotatedField.getKey(), value);
934 }
935 }
936 }
937 }
938
939
940
941
942
943
944
945
946
947
948 protected void invokeMethodFinalizer(View view, Component component, Object model) {
949 String finalizeMethodToCall = component.getFinalizeMethodToCall();
950 MethodInvoker finalizeMethodInvoker = component.getFinalizeMethodInvoker();
951
952 if (StringUtils.isBlank(finalizeMethodToCall) && (finalizeMethodInvoker == null)) {
953 return;
954 }
955
956 if (finalizeMethodInvoker == null) {
957 finalizeMethodInvoker = new MethodInvoker();
958 }
959
960
961
962 if (StringUtils.isBlank(finalizeMethodInvoker.getTargetMethod())) {
963 finalizeMethodInvoker.setTargetMethod(finalizeMethodToCall);
964 }
965
966
967 if ((finalizeMethodInvoker.getTargetClass() == null) && (finalizeMethodInvoker.getTargetObject() == null)) {
968 finalizeMethodInvoker.setTargetObject(view.getViewHelperService());
969 }
970
971
972 List<Object> additionalArguments = component.getFinalizeMethodAdditionalArguments();
973 if (additionalArguments == null) {
974 additionalArguments = new ArrayList<Object>();
975 }
976
977 Object[] arguments = new Object[2 + additionalArguments.size()];
978 arguments[0] = component;
979 arguments[1] = model;
980
981 int argumentIndex = 1;
982 for (Object argument : additionalArguments) {
983 argumentIndex++;
984 arguments[argumentIndex] = argument;
985 }
986 finalizeMethodInvoker.setArguments(arguments);
987
988
989 try {
990 LOG.debug("Invoking render method: "
991 + finalizeMethodInvoker.getTargetMethod()
992 + " for component: "
993 + component.getId());
994 finalizeMethodInvoker.prepare();
995
996 Class<?> methodReturnType = finalizeMethodInvoker.getPreparedMethod().getReturnType();
997 if (StringUtils.equals("void", methodReturnType.getName())) {
998 finalizeMethodInvoker.invoke();
999 } else {
1000 String renderOutput = (String) finalizeMethodInvoker.invoke();
1001
1002 component.setSelfRendered(true);
1003 component.setRenderOutput(renderOutput);
1004 }
1005 } catch (Exception e) {
1006 LOG.error("Error invoking rendering method for component: " + component.getId(), e);
1007 throw new RuntimeException("Error invoking rendering method for component: " + component.getId(), e);
1008 }
1009 }
1010
1011
1012
1013
1014
1015 @Override
1016 public void processCollectionAddLine(View view, Object model, String collectionPath) {
1017
1018 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1019 if (collectionGroup == null) {
1020 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
1021 }
1022
1023
1024 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
1025 if (collection == null) {
1026 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
1027 }
1028
1029
1030 String addLinePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
1031 Object addLine = ObjectPropertyUtils.getPropertyValue(model, addLinePath);
1032 if (addLine == null) {
1033 logAndThrowRuntime("Add line instance not found for path: " + addLinePath);
1034 }
1035
1036 processBeforeAddLine(view, collectionGroup, model, addLine);
1037
1038
1039 boolean isValidLine = performAddLineValidation(view, collectionGroup, model, addLine);
1040 if (isValidLine) {
1041
1042
1043
1044 if (collection instanceof List) {
1045 ((List) collection).add(0, addLine);
1046 } else {
1047 collection.add(addLine);
1048 }
1049
1050
1051 collectionGroup.initializeNewCollectionLine(view, model, collectionGroup, true);
1052 }
1053
1054 processAfterAddLine(view, collectionGroup, model, addLine);
1055 }
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069 protected boolean performAddLineValidation(View view, CollectionGroup collectionGroup, Object model,
1070 Object addLine) {
1071 boolean isValid = true;
1072
1073
1074
1075
1076 return isValid;
1077 }
1078
1079
1080
1081
1082
1083 public void processCollectionDeleteLine(View view, Object model, String collectionPath, int lineIndex) {
1084
1085 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1086 if (collectionGroup == null) {
1087 logAndThrowRuntime("Unable to get collection group component for path: " + collectionPath);
1088 }
1089
1090
1091 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model, collectionPath);
1092 if (collection == null) {
1093 logAndThrowRuntime("Unable to get collection property from model for path: " + collectionPath);
1094 }
1095
1096
1097
1098 if (collection instanceof List) {
1099 Object deleteLine = ((List<Object>) collection).get(lineIndex);
1100
1101
1102 boolean isValid = performDeleteLineValidation(view, collectionGroup, deleteLine);
1103 if (isValid) {
1104 ((List<Object>) collection).remove(lineIndex);
1105 processAfterDeleteLine(view, collectionGroup, model, lineIndex);
1106 }
1107 } else {
1108 logAndThrowRuntime("Only List collection implementations are supported for the delete by index method");
1109 }
1110 }
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122 protected boolean performDeleteLineValidation(View view, CollectionGroup collectionGroup, Object deleteLine) {
1123 boolean isValid = true;
1124
1125
1126
1127
1128 return isValid;
1129 }
1130
1131
1132
1133
1134 public void processMultipleValueLookupResults(View view, Object model, String collectionPath,
1135 String lookupResultValues) {
1136
1137 if (StringUtils.isBlank(lookupResultValues)) {
1138 return;
1139 }
1140
1141
1142 CollectionGroup collectionGroup = view.getViewIndex().getCollectionGroupByPath(collectionPath);
1143 if (collectionGroup == null) {
1144 throw new RuntimeException("Unable to find collection group for path: " + collectionPath);
1145 }
1146
1147 Class<?> collectionObjectClass = collectionGroup.getCollectionObjectClass();
1148 Collection<Object> collection = ObjectPropertyUtils.getPropertyValue(model,
1149 collectionGroup.getBindingInfo().getBindingPath());
1150 if (collection == null) {
1151 Class<?> collectionClass = ObjectPropertyUtils.getPropertyType(model,
1152 collectionGroup.getBindingInfo().getBindingPath());
1153 collection = (Collection<Object>) ObjectUtils.newInstance(collectionClass);
1154 ObjectPropertyUtils.setPropertyValue(model, collectionGroup.getBindingInfo().getBindingPath(), collection);
1155 }
1156
1157 Map<String, String> fieldConversions = collectionGroup.getCollectionLookup().getFieldConversions();
1158 List<String> toFieldNamesColl = new ArrayList(fieldConversions.values());
1159 Collections.sort(toFieldNamesColl);
1160 String[] toFieldNames = new String[toFieldNamesColl.size()];
1161 toFieldNamesColl.toArray(toFieldNames);
1162
1163
1164 String[] lineValues = StringUtils.split(lookupResultValues, ",");
1165
1166
1167 for (String lineValue : lineValues) {
1168 Object lineDataObject = null;
1169
1170
1171 ModuleService moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(
1172 collectionObjectClass);
1173 if (moduleService != null && moduleService.isExternalizable(collectionObjectClass)) {
1174 lineDataObject = moduleService.createNewObjectFromExternalizableClass(collectionObjectClass.asSubclass(
1175 ExternalizableBusinessObject.class));
1176 } else {
1177 lineDataObject = ObjectUtils.newInstance(collectionObjectClass);
1178 }
1179
1180
1181 applyDefaultValuesForCollectionLine(view, model, collectionGroup, lineDataObject);
1182
1183 String[] fieldValues = StringUtils.split(lineValue, ":");
1184 if (fieldValues.length != toFieldNames.length) {
1185 throw new RuntimeException(
1186 "Value count passed back from multi-value lookup does not match field conversion count");
1187 }
1188
1189
1190 for (int i = 0; i < fieldValues.length; i++) {
1191 String fieldName = toFieldNames[i];
1192 ObjectPropertyUtils.setPropertyValue(lineDataObject, fieldName, fieldValues[i]);
1193 }
1194
1195
1196
1197 collection.add(lineDataObject);
1198 }
1199 }
1200
1201
1202
1203
1204
1205
1206
1207
1208 public void buildInquiryLink(Object dataObject, String propertyName, Inquiry inquiry) {
1209 Inquirable inquirable = getViewDictionaryService().getInquirable(dataObject.getClass(), inquiry.getViewName());
1210 if (inquirable != null) {
1211 inquirable.buildInquirableLink(dataObject, propertyName, inquiry);
1212 } else {
1213
1214 inquiry.setRender(false);
1215 }
1216 }
1217
1218
1219
1220
1221
1222
1223 public void applyDefaultValuesForCollectionLine(View view, Object model, CollectionGroup collectionGroup,
1224 Object line) {
1225
1226 List<DataField> dataFields = ComponentUtils.getComponentsOfTypeDeep(
1227 collectionGroup.getAddLineFields(), DataField.class);
1228 for (DataField dataField : dataFields) {
1229 String bindingPath = "";
1230 if (StringUtils.isNotBlank(dataField.getBindingInfo().getBindByNamePrefix())) {
1231 bindingPath = dataField.getBindingInfo().getBindByNamePrefix() + ".";
1232 }
1233 bindingPath += dataField.getBindingInfo().getBindingName();
1234
1235 populateDefaultValueForField(view, line, dataField, bindingPath);
1236 }
1237 }
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255 protected void populateDefaultValueForField(View view, Object object, DataField dataField,
1256 String bindingPath) {
1257
1258 String defaultValue = dataField.getDefaultValue();
1259 if (StringUtils.isBlank(defaultValue) && (dataField.getDefaultValueFinderClass() != null)) {
1260 ValueFinder defaultValueFinder = ObjectUtils.newInstance(dataField.getDefaultValueFinderClass());
1261 defaultValue = defaultValueFinder.getValue();
1262 }
1263
1264
1265 if (StringUtils.isNotBlank(defaultValue) && ObjectPropertyUtils.isWritableProperty(object, bindingPath)) {
1266 if (getExpressionEvaluatorService().containsElPlaceholder(defaultValue)) {
1267 Map<String, Object> context = getPreModelContext(view);
1268 defaultValue = getExpressionEvaluatorService().evaluateExpressionTemplate(null, context, defaultValue);
1269 }
1270
1271
1272 ObjectPropertyUtils.setPropertyValue(object, bindingPath, defaultValue);
1273 }
1274 }
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293 protected void addCustomContainerComponents(View view, Object model, Container container) {
1294
1295 }
1296
1297
1298
1299
1300
1301
1302
1303
1304 protected void performCustomInitialization(View view, Component component) {
1305
1306 }
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317 protected void performCustomApplyModel(View view, Component component, Object model) {
1318
1319 }
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329 protected void performCustomFinalize(View view, Component component, Object model, Component parent) {
1330
1331 }
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344 protected void processBeforeAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
1345
1346 }
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359 protected void processAfterAddLine(View view, CollectionGroup collectionGroup, Object model, Object addLine) {
1360
1361 }
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372 protected void processAfterDeleteLine(View view, CollectionGroup collectionGroup, Object model, int lineIndex) {
1373
1374 }
1375
1376 protected void logAndThrowRuntime(String message) {
1377 LOG.error(message);
1378 throw new RuntimeException(message);
1379 }
1380
1381 protected DataDictionaryService getDataDictionaryService() {
1382 if (this.dataDictionaryService == null) {
1383 this.dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
1384 }
1385
1386 return this.dataDictionaryService;
1387 }
1388
1389 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
1390 this.dataDictionaryService = dataDictionaryService;
1391 }
1392
1393 protected ExpressionEvaluatorService getExpressionEvaluatorService() {
1394 if (this.expressionEvaluatorService == null) {
1395 this.expressionEvaluatorService = KRADServiceLocatorWeb.getExpressionEvaluatorService();
1396 }
1397
1398 return this.expressionEvaluatorService;
1399 }
1400
1401 public void setExpressionEvaluatorService(ExpressionEvaluatorService expressionEvaluatorService) {
1402 this.expressionEvaluatorService = expressionEvaluatorService;
1403 }
1404
1405 public ViewDictionaryService getViewDictionaryService() {
1406 if (this.viewDictionaryService == null) {
1407 this.viewDictionaryService = KRADServiceLocatorWeb.getViewDictionaryService();
1408 }
1409 return this.viewDictionaryService;
1410 }
1411
1412 public void setViewDictionaryService(ViewDictionaryService viewDictionaryService) {
1413 this.viewDictionaryService = viewDictionaryService;
1414 }
1415 }