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