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