1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.lookup;
17
18 import java.util.ArrayList;
19 import java.util.Arrays;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.apache.commons.lang.StringUtils;
25 import org.kuali.rice.core.api.mo.common.active.Inactivatable;
26 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
27 import org.kuali.rice.kim.api.identity.Person;
28 import org.kuali.rice.krad.datadictionary.AttributeDefinition;
29 import org.kuali.rice.krad.datadictionary.parse.BeanTag;
30 import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
31 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
32 import org.kuali.rice.krad.uif.UifConstants;
33 import org.kuali.rice.krad.uif.UifConstants.ViewType;
34 import org.kuali.rice.krad.uif.UifParameters;
35 import org.kuali.rice.krad.uif.UifPropertyPaths;
36 import org.kuali.rice.krad.uif.component.Component;
37 import org.kuali.rice.krad.uif.component.RequestParameter;
38 import org.kuali.rice.krad.uif.container.CollectionGroup;
39 import org.kuali.rice.krad.uif.container.Group;
40 import org.kuali.rice.krad.uif.control.Control;
41 import org.kuali.rice.krad.uif.control.FilterableLookupCriteriaControl;
42 import org.kuali.rice.krad.uif.control.FilterableLookupCriteriaControlPostData;
43 import org.kuali.rice.krad.uif.control.TextAreaControl;
44 import org.kuali.rice.krad.uif.control.TextControl;
45 import org.kuali.rice.krad.uif.element.Action;
46 import org.kuali.rice.krad.uif.element.Message;
47 import org.kuali.rice.krad.uif.field.FieldGroup;
48 import org.kuali.rice.krad.uif.field.InputField;
49 import org.kuali.rice.krad.uif.layout.TableLayoutManager;
50 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
51 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleRestriction;
52 import org.kuali.rice.krad.uif.lifecycle.ViewLifecycleUtils;
53 import org.kuali.rice.krad.uif.lifecycle.ViewPostMetadata;
54 import org.kuali.rice.krad.uif.lifecycle.initialize.AssignIdsTask;
55 import org.kuali.rice.krad.uif.util.ComponentFactory;
56 import org.kuali.rice.krad.uif.util.ComponentUtils;
57 import org.kuali.rice.krad.uif.util.LifecycleElement;
58 import org.kuali.rice.krad.uif.view.FormView;
59 import org.kuali.rice.krad.util.GlobalVariables;
60 import org.kuali.rice.krad.util.KRADConstants;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 @BeanTag(name = "lookupView", parent = "Uif-LookupView")
76 public class LookupView extends FormView {
77
78 private static final long serialVersionUID = 716926008488403616L;
79
80 private Class<?> dataObjectClass;
81
82 private List<Component> criteriaFields;
83 private Group criteriaGroup;
84
85 @RequestParameter
86 private boolean hideCriteriaOnSearch;
87
88 private List<Component> resultFields;
89 private CollectionGroup resultsGroup;
90
91 private List<String> defaultSortAttributeNames;
92 private boolean defaultSortAscending;
93
94 @RequestParameter
95 private Boolean renderReturnLink;
96
97 @RequestParameter
98 private boolean renderResultActions;
99
100 @RequestParameter
101 private Boolean renderMaintenanceLinks;
102
103 @RequestParameter
104 private boolean multipleValuesSelect;
105
106 @RequestParameter
107 private boolean renderLookupCriteria;
108
109 @RequestParameter
110 private boolean renderCriteriaActions;
111
112 private Integer resultSetLimit;
113 private Integer multipleValuesSelectResultSetLimit;
114
115 private String maintenanceUrlMapping;
116
117 private FieldGroup rangeFieldGroupPrototype;
118 private Message rangedToMessage;
119
120 private boolean autoAddActiveCriteria;
121
122 private List<String> additionalSecurePropertyNames;
123
124 public LookupView() {
125 super();
126
127 setViewTypeName(ViewType.LOOKUP);
128
129 defaultSortAscending = true;
130 autoAddActiveCriteria = true;
131 renderLookupCriteria = true;
132 renderCriteriaActions = true;
133 renderResultActions = true;
134
135 additionalSecurePropertyNames = new ArrayList<String>();
136 }
137
138
139
140
141
142
143
144 @Override
145 public void performInitialization(Object model) {
146
147 Lookupable lookupable = (Lookupable) getViewHelperService();
148 lookupable.setDataObjectClass(dataObjectClass);
149
150 initializeGroups();
151
152 super.performInitialization(model);
153
154 getObjectPathToConcreteClassMapping().put(UifPropertyPaths.LOOKUP_CRITERIA, getDataObjectClass());
155 if (StringUtils.isNotBlank(getDefaultBindingObjectPath())) {
156 getObjectPathToConcreteClassMapping().put(getDefaultBindingObjectPath(), getDataObjectClass());
157 }
158 }
159
160
161
162
163
164
165
166
167 @Override
168 public void performApplyModel(Object model, LifecycleElement parent) {
169 LookupForm lookupForm = (LookupForm) model;
170
171
172 if (!renderCriteriaActions || hideCriteriaOnSearch) {
173 criteriaGroup.getFooter().setRender(false);
174 }
175
176
177 if (!renderLookupCriteria || (hideCriteriaOnSearch && lookupForm.isDisplayResults())) {
178 criteriaGroup.setRender(false);
179 }
180
181
182 if (hideCriteriaOnSearch && !lookupForm.isDisplayResults()) {
183 resultsGroup.setRender(false);
184 }
185
186 boolean returnLinkAllowed = false;
187 boolean maintenanceLinksAllowed = false;
188
189
190 if (!multipleValuesSelect) {
191
192 if ((lookupForm.getInitialRequestParameters() != null) && lookupForm.getInitialRequestParameters()
193 .containsKey(UifParameters.CONVERSION_FIELDS)) {
194 returnLinkAllowed = true;
195 } else {
196 maintenanceLinksAllowed = true;
197 }
198 } else {
199 renderResultActions = false;
200 }
201
202
203 if (renderReturnLink == null) {
204 renderReturnLink = returnLinkAllowed;
205 }
206
207 if (renderMaintenanceLinks == null) {
208 renderMaintenanceLinks = maintenanceLinksAllowed;
209 }
210
211
212 if (renderMaintenanceLinks) {
213 LookupViewAuthorizerBase lookupAuthorizer = (LookupViewAuthorizerBase) getAuthorizer();
214
215 Person user = GlobalVariables.getUserSession().getPerson();
216 renderMaintenanceLinks = lookupAuthorizer.canInitiateMaintenanceDocument(getDataObjectClass().getName(),
217 user);
218 }
219
220
221 if (this.getResultsGroup().getLayoutManager() instanceof TableLayoutManager) {
222 TableLayoutManager resultsTableLayoutManager =
223 (TableLayoutManager) this.getResultsGroup().getLayoutManager();
224 if (resultsTableLayoutManager.isAutoTruncateColumns() == null) {
225 resultsTableLayoutManager.setAutoTruncateColumns(
226 CoreFrameworkServiceLocator.getParameterService().getParameterValueAsBoolean(
227 KRADConstants.KRAD_NAMESPACE, KRADConstants.DetailTypes.LOOKUP_PARM_DETAIL_TYPE,
228 KRADConstants.SystemGroupParameterNames.AUTO_TRUNCATE_COLUMNS, false));
229 }
230 }
231
232 convertLookupCriteriaFields(criteriaGroup);
233
234 super.performApplyModel(model, parent);
235 }
236
237
238
239
240
241
242 @Override
243 public void performFinalize(Object model, LifecycleElement parent) {
244 super.performFinalize(model, parent);
245
246 LookupForm lookupForm = (LookupForm) model;
247 String viewId = lookupForm.getViewId();
248
249 Map<String, FilterableLookupCriteriaControlPostData> filterableLookupCriteria =
250 new HashMap<String, FilterableLookupCriteriaControlPostData>();
251
252 List<InputField> fields = ViewLifecycleUtils.getElementsOfTypeDeep(criteriaGroup, InputField.class);
253
254 for (InputField field : fields) {
255 field.setForceSessionPersistence(true);
256
257 String propertyName = field.getPropertyName();
258
259 if (field.getControl() instanceof FilterableLookupCriteriaControl) {
260 FilterableLookupCriteriaControl control = (FilterableLookupCriteriaControl) field.getControl();
261 filterableLookupCriteria.put(propertyName, control.getPostData(propertyName));
262 }
263 }
264
265 ViewPostMetadata viewPostMetadata = ViewLifecycle.getViewPostMetadata();
266 viewPostMetadata.addComponentPostData(viewId, UifConstants.PostMetadata.FILTERABLE_LOOKUP_CRITERIA,
267 filterableLookupCriteria);
268
269 if (lookupForm.isReturnByScript()) {
270 getAdditionalHiddenValues().put(UifParameters.RETURN_BY_SCRIPT, "true");
271 }
272
273
274 String dialogId = lookupForm.getShowDialogId();
275 if (StringUtils.isNotBlank(dialogId)) {
276 List<Action> actions = ViewLifecycleUtils.getElementsOfTypeDeep(getFooter().getItems(), Action.class);
277
278 for (Action action : actions) {
279 action.addActionParameter(UifParameters.DIALOG_ID, dialogId);
280 }
281 } else {
282 dialogId = lookupForm.getActionParamaterValue(UifParameters.DIALOG_ID);
283 lookupForm.setShowDialogId(dialogId);
284 }
285 }
286
287
288
289
290
291 protected void addActiveCriteriaIfNecessary() {
292 boolean isInactivatableClass = Inactivatable.class.isAssignableFrom(dataObjectClass);
293
294 if (!autoAddActiveCriteria || !isInactivatableClass) {
295 return;
296 }
297
298 boolean hasActiveCriteria = false;
299 for (Component field : getCriteriaFields()) {
300 if (((InputField) field).getPropertyName().equals(UifPropertyPaths.ACTIVE)) {
301 hasActiveCriteria = true;
302 }
303 }
304
305 if (hasActiveCriteria) {
306 return;
307 }
308
309 AttributeDefinition attributeDefinition =
310 KRADServiceLocatorWeb.getDataDictionaryService().getAttributeDefinition(dataObjectClass.getName(),
311 UifPropertyPaths.ACTIVE);
312
313 LookupInputField activeLookupField;
314 if (attributeDefinition == null) {
315 activeLookupField = (LookupInputField) ComponentFactory.getNewComponentInstance(
316 ComponentFactory.LOOKUP_ACTIVE_INPUT_FIELD);
317 } else {
318 activeLookupField = (LookupInputField) ComponentFactory.getNewComponentInstance(
319 ComponentFactory.LOOKUP_INPUT_FIELD);
320
321 activeLookupField.setPropertyName(UifPropertyPaths.ACTIVE);
322 activeLookupField.copyFromAttributeDefinition(attributeDefinition);
323 }
324
325 getCriteriaFields().add(activeLookupField);
326 }
327
328
329
330
331
332 protected void initializeGroups() {
333 if ((getCriteriaGroup() != null) && (getCriteriaGroup().getItems().isEmpty())) {
334 getCriteriaGroup().setItems(getCriteriaFields());
335 }
336
337 if (getResultsGroup() != null) {
338 if ((getResultsGroup().getItems().isEmpty()) && (getResultFields() != null)) {
339 getResultsGroup().setItems(getResultFields());
340 }
341
342 if (getResultsGroup().getCollectionObjectClass() == null) {
343 getResultsGroup().setCollectionObjectClass(getDataObjectClass());
344 }
345 }
346
347 if (getItems().isEmpty()) {
348 setItems(Arrays.asList(getCriteriaGroup(), getResultsGroup()));
349 }
350 }
351
352
353
354
355
356
357
358 protected void convertLookupCriteriaFields(Group lookupGroup) {
359 @SuppressWarnings("unchecked")
360 List<Component> criteriaGroupItems = (List<Component>) lookupGroup.getItems();
361
362
363 HashMap<Integer, Component> dateRangeFieldMap = new HashMap<Integer, Component>();
364
365 int rangeIndex = 0;
366 for (Component component : criteriaGroupItems) {
367 if (component == null) {
368 continue;
369 }
370
371 if (Group.class.isAssignableFrom(component.getClass())) {
372 convertLookupCriteriaFields((Group) component);
373 } else if (FieldGroup.class.isAssignableFrom(component.getClass())) {
374 convertLookupCriteriaFields(((FieldGroup) component).getGroup());
375 } else if (LookupInputField.class.isAssignableFrom(component.getClass())) {
376 LookupInputField lookupInputField = (LookupInputField) component;
377
378
379 Control control = lookupInputField.getControl();
380
381 if (control instanceof TextControl) {
382 ((TextControl) control).setMaxLength(null);
383 } else if (control instanceof TextAreaControl) {
384 ((TextAreaControl) control).setMaxLength(null);
385 }
386
387 if (lookupInputField.isRanged()) {
388 FieldGroup rangeFieldGroup = createDateRangeFieldGroup(lookupInputField);
389
390 dateRangeFieldMap.put(rangeIndex, rangeFieldGroup);
391 }
392 }
393
394 rangeIndex++;
395 }
396
397
398 for (Integer index : dateRangeFieldMap.keySet()) {
399 criteriaGroupItems.set(index, dateRangeFieldMap.get(index));
400 }
401
402 criteriaGroup.setItems(criteriaGroupItems);
403 }
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419 protected FieldGroup createDateRangeFieldGroup(LookupInputField toDate) {
420
421 if (toDate.getId() == null) {
422 toDate.setId(AssignIdsTask.generateId(toDate, ViewLifecycle.getView()));
423 }
424
425 FieldGroup rangeFieldGroup = ComponentUtils.copy(getRangeFieldGroupPrototype());
426
427
428 rangeFieldGroup.setFieldLabel(ComponentUtils.copy(toDate.getFieldLabel()));
429 rangeFieldGroup.setPropertyExpressions(toDate.getPropertyExpressions());
430 rangeFieldGroup.setProgressiveRender(toDate.getProgressiveRender());
431 rangeFieldGroup.setProgressiveRenderViaAJAX(toDate.isProgressiveRenderViaAJAX());
432 rangeFieldGroup.setConditionalRefresh(toDate.getConditionalRefresh());
433 rangeFieldGroup.setRefreshWhenChangedPropertyNames(toDate.getRefreshWhenChangedPropertyNames());
434 rangeFieldGroup.setForceSessionPersistence(true);
435
436
437 toDate.getFieldLabel().setRender(false);
438 toDate.setRefreshWhenChangedPropertyNames(null);
439 toDate.setForceSessionPersistence(true);
440
441
442 LookupInputField fromDate = ComponentUtils.copy(toDate,
443 KRADConstants.LOOKUP_DEFAULT_RANGE_SEARCH_LOWER_BOUND_LABEL);
444 fromDate.getBindingInfo().setBindingName(
445 KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + fromDate.getPropertyName());
446 fromDate.setPropertyName(KRADConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX + fromDate.getPropertyName());
447 fromDate.setOrder(0);
448
449
450 List<Component> fieldGroupItems = new ArrayList<Component>();
451 fieldGroupItems.add(fromDate);
452 fieldGroupItems.add(rangedToMessage);
453 fieldGroupItems.add(toDate);
454 rangeFieldGroup.setItems(fieldGroupItems);
455
456 return rangeFieldGroup;
457 }
458
459
460
461
462
463
464
465
466
467
468 @BeanTagAttribute(name = "dataObjectClass")
469 public Class<?> getDataObjectClass() {
470 return this.dataObjectClass;
471 }
472
473
474
475
476 public void setDataObjectClass(Class<?> dataObjectClass) {
477 this.dataObjectClass = dataObjectClass;
478 }
479
480
481
482
483
484
485 public void setDataObjectClassName(String dataObjectClassName) {
486 try {
487 this.dataObjectClass = Class.forName(dataObjectClassName);
488 } catch (ClassNotFoundException e) {
489 throw new RuntimeException("Unable to set class for class name: " + dataObjectClassName, e);
490 }
491 }
492
493
494
495
496
497
498
499
500
501
502 @BeanTagAttribute(name = "renderReturnLink")
503 public Boolean isRenderReturnLink() {
504 return this.renderReturnLink;
505 }
506
507
508
509
510 public void setRenderReturnLink(Boolean renderReturnLink) {
511 this.renderReturnLink = renderReturnLink;
512 }
513
514
515
516
517
518
519
520
521
522 @BeanTagAttribute(name = "isRenderResultActions")
523 public boolean isRenderResultActions() {
524 return this.renderResultActions;
525 }
526
527
528
529
530 public void setRenderResultActions(boolean renderResultActions) {
531 this.renderResultActions = renderResultActions;
532 }
533
534
535
536
537
538
539
540
541
542
543
544
545 @BeanTagAttribute(name = "renderMaintenanceLinks")
546 public Boolean isRenderMaintenanceLinks() {
547 return this.renderMaintenanceLinks;
548 }
549
550
551
552
553 public void setRenderMaintenanceLinks(Boolean renderMaintenanceLinks) {
554 this.renderMaintenanceLinks = renderMaintenanceLinks;
555 }
556
557
558
559
560
561
562
563
564
565
566 @BeanTagAttribute(name = "multipleValueSelect")
567 public boolean isMultipleValuesSelect() {
568 return multipleValuesSelect;
569 }
570
571
572
573
574 public void setMultipleValuesSelect(boolean multipleValuesSelect) {
575 this.multipleValuesSelect = multipleValuesSelect;
576 }
577
578
579
580
581
582
583
584
585
586
587 @ViewLifecycleRestriction
588 @BeanTagAttribute(name = "criteriaFields", type = BeanTagAttribute.AttributeType.LISTBEAN)
589 public List<Component> getCriteriaFields() {
590 return this.criteriaFields;
591 }
592
593
594
595
596 public void setCriteriaFields(List<Component> criteriaFields) {
597 this.criteriaFields = criteriaFields;
598 }
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618 @ViewLifecycleRestriction
619 @BeanTagAttribute(name = "criteriaGroup", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
620 public Group getCriteriaGroup() {
621 return this.criteriaGroup;
622 }
623
624
625
626
627 public void setCriteriaGroup(Group criteriaGroup) {
628 this.criteriaGroup = criteriaGroup;
629 }
630
631 public boolean isHideCriteriaOnSearch() {
632 return hideCriteriaOnSearch;
633 }
634
635 public void setHideCriteriaOnSearch(boolean hideCriteriaOnSearch) {
636 this.hideCriteriaOnSearch = hideCriteriaOnSearch;
637 }
638
639
640
641
642
643
644
645
646
647
648
649 @ViewLifecycleRestriction
650 @BeanTagAttribute(name = "resultFields", type = BeanTagAttribute.AttributeType.LISTBEAN)
651 public List<Component> getResultFields() {
652 return this.resultFields;
653 }
654
655
656
657
658 public void setResultFields(List<Component> resultFields) {
659 this.resultFields = resultFields;
660 }
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680 @ViewLifecycleRestriction
681 @BeanTagAttribute(name = "resultsGroup", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
682 public CollectionGroup getResultsGroup() {
683 return this.resultsGroup;
684 }
685
686
687
688
689 public void setResultsGroup(CollectionGroup resultsGroup) {
690 this.resultsGroup = resultsGroup;
691 }
692
693
694
695
696
697
698
699
700
701 @BeanTagAttribute(name = "defaultSortAttributeNames", type = BeanTagAttribute.AttributeType.LISTVALUE)
702 public List<String> getDefaultSortAttributeNames() {
703 return this.defaultSortAttributeNames;
704 }
705
706
707
708
709 public void setDefaultSortAttributeNames(List<String> defaultSortAttributeNames) {
710 this.defaultSortAttributeNames = defaultSortAttributeNames;
711 }
712
713
714
715
716
717
718
719
720 @BeanTagAttribute(name = "defaultSortAscending")
721 public boolean isDefaultSortAscending() {
722 return this.defaultSortAscending;
723 }
724
725
726
727
728 public void setDefaultSortAscending(boolean defaultSortAscending) {
729 this.defaultSortAscending = defaultSortAscending;
730 }
731
732
733
734
735
736
737 @BeanTagAttribute(name = "resultSetLimit")
738 public Integer getResultSetLimit() {
739 return resultSetLimit;
740 }
741
742
743
744
745 public void setResultSetLimit(Integer resultSetLimit) {
746 this.resultSetLimit = resultSetLimit;
747 }
748
749
750
751
752
753
754
755 @BeanTagAttribute(name = "multipleValuesSelectResultSetLimit")
756 public Integer getMultipleValuesSelectResultSetLimit() {
757 return multipleValuesSelectResultSetLimit;
758 }
759
760
761
762
763 public void setMultipleValuesSelectResultSetLimit(Integer multipleValuesSelectResultSetLimit) {
764 this.multipleValuesSelectResultSetLimit = multipleValuesSelectResultSetLimit;
765 }
766
767
768
769
770
771
772
773
774
775
776 @BeanTagAttribute(name = "maintenanceUrlMapping")
777 public String getMaintenanceUrlMapping() {
778 return maintenanceUrlMapping;
779 }
780
781
782
783
784 public void setMaintenanceUrlMapping(String maintenanceUrlMapping) {
785 this.maintenanceUrlMapping = maintenanceUrlMapping;
786 }
787
788
789
790
791
792
793
794 public boolean isRenderCriteriaActions() {
795 return renderCriteriaActions;
796 }
797
798
799
800
801 public void setRenderCriteriaActions(boolean renderCriteriaActions) {
802 this.renderCriteriaActions = renderCriteriaActions;
803 }
804
805
806
807
808
809
810
811
812
813 public boolean isRenderLookupCriteria() {
814 return renderLookupCriteria;
815 }
816
817
818
819
820 public void setRenderLookupCriteria(boolean renderLookupCriteria) {
821 this.renderLookupCriteria = renderLookupCriteria;
822 }
823
824
825
826
827
828
829 @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
830 public FieldGroup getRangeFieldGroupPrototype() {
831 return rangeFieldGroupPrototype;
832 }
833
834
835
836
837 public void setRangeFieldGroupPrototype(FieldGroup rangeFieldGroupPrototype) {
838 this.rangeFieldGroupPrototype = rangeFieldGroupPrototype;
839 }
840
841
842
843
844
845
846
847 @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
848 public Message getRangedToMessage() {
849 return rangedToMessage;
850 }
851
852
853
854
855 public void setRangedToMessage(Message rangedToMessage) {
856 this.rangedToMessage = rangedToMessage;
857 }
858
859
860
861
862
863
864
865 public boolean isAutoAddActiveCriteria() {
866 return autoAddActiveCriteria;
867 }
868
869
870
871
872 public void setAutoAddActiveCriteria(boolean autoAddActiveCriteria) {
873 this.autoAddActiveCriteria = autoAddActiveCriteria;
874 }
875
876
877
878
879
880
881
882
883 @BeanTagAttribute(name = "additionalSecurePropertyNames", type = BeanTagAttribute.AttributeType.LISTVALUE)
884 public List<String> getAdditionalSecurePropertyNames() {
885 return additionalSecurePropertyNames;
886 }
887
888
889
890
891 public void setAdditionalSecurePropertyNames(List<String> additionalSecurePropertyNames) {
892 this.additionalSecurePropertyNames = additionalSecurePropertyNames;
893 }
894 }