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