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