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