View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
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   * View type for lookups.
63   *
64   * <p>Supports doing a search against a data object class or performing a more advanced query. The view
65   * type is primarily made up of two groups, the search (or criteria) group and the results group. Many
66   * options are supported on the view to enable/disable certain features, like what actions are available
67   * on the search results.</p>
68   *
69   * <p>Works in conjunction with {@link org.kuali.rice.krad.lookup.Lookupable} which customizes the view and
70   * carries out the business functionality</p>
71   *
72   * @author Kuali Rice Team (rice.collab@kuali.org)
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      * Initializes Lookupable with data object class and sets the abstractTypeClasses map for the
138      * lookup object path.
139      *
140      * {@inheritDoc}
141      */
142     @Override
143     public void performInitialization(Object model) {
144         // init the view helper with the data object class
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      * Reads the convenience render flags and sets the corresponding component property, processing the criteria
160      * fields for any adjustments, and invokes the lookup authorizer to determine whether maintenance links should
161      * be shown.
162      *
163      * {@inheritDoc}
164      */
165     @Override
166     public void performApplyModel(Object model, LifecycleElement parent) {
167         LookupForm lookupForm = (LookupForm) model;
168 
169         // don't render criteria group footer/actions
170         if (!renderCriteriaActions || hideCriteriaOnSearch) {
171             criteriaGroup.getFooter().setRender(false);
172         }
173 
174         // don't render criteria if not supposed to or (hide on search results and displaying the results)
175         if (!renderLookupCriteria || (hideCriteriaOnSearch && lookupForm.isDisplayResults())) {
176             criteriaGroup.setRender(false);
177         }
178 
179         // if hide on search results and not displaying search results don't render results
180         if (hideCriteriaOnSearch && !lookupForm.isDisplayResults()) {
181             resultsGroup.setRender(false);
182         }
183 
184         boolean returnLinkAllowed = false;
185         boolean maintenanceLinksAllowed = false;
186 
187         // neither return nor maintenance links are shown for multi-value select
188         if (!multipleValuesSelect) {
189             // if coming from a quickfinder we will show the return URL
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         // only override view properties if they were not manually configured
201         if (renderReturnLink == null) {
202             renderReturnLink = returnLinkAllowed;
203         }
204 
205         if (renderMaintenanceLinks == null) {
206             renderMaintenanceLinks = maintenanceLinksAllowed;
207         }
208 
209         // if maintenance links enabled, verify the user had permission
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         // autoTruncateColumns: use system wide lookup result configuration if not specified
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      * Forces session persistence on the criteria fields so the search criteria can be validated on post.
233      *
234      * {@inheritDoc}
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      * Adds the 'active' property criteria to the criteria fields if the BO is inactivatable and their is
268      * not already a lookup field for the active property.
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      * Adds the list of criteria and result fields to their group prototypes, then adds the criteria and result
309      * groups to the items for the view.
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      * Performs conversions of the lookup criteria fields within the given group's items.
333      *
334      * <p>Max lengths are removed on text controls so wildcards can be added. Ranged date fields are
335      * converted to field groups with the from/to date fields</p>
336      */
337     protected void convertLookupCriteriaFields(Group lookupGroup) {
338         @SuppressWarnings("unchecked")
339         List<Component> criteriaGroupItems = (List<Component>) lookupGroup.getItems();
340 
341         // holds the index and range field group for replacement into the items
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                 // set the max length on the controls to allow for wildcards
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         // replace original fields with range field groups
377         for (Integer index : dateRangeFieldMap.keySet()) {
378             criteriaGroupItems.set(index, dateRangeFieldMap.get(index));
379         }
380 
381         criteriaGroup.setItems(criteriaGroupItems);
382     }
383 
384     /**
385      * Creates a {@link FieldGroup} instance to replace the given lookup input field as a
386      * date criteria range.
387      *
388      * <p>The field group is created by copying {@link LookupView#rangeFieldGroupPrototype}. This can be
389      * used to configure how the field group will appear. In addition, the two lookup fields are separated
390      * with a message that can be configured with {@link LookupView#rangedToMessage}</p>
391      *
392      * @param toDate lookup input field that field group should be build for
393      *
394      * @return field group that contains a from and to lookup input field for searching a date range
395      *
396      * @see LookupView#rangeFieldGroupPrototype
397      * @see LookupView#rangedToMessage
398      */
399     protected FieldGroup createDateRangeFieldGroup(LookupInputField toDate) {
400         // Generate an ID when the "to date" field is out of the normal lifecycle flow
401         if (toDate.getId() == null) {
402             toDate.setId(AssignIdsTask.generateId(toDate, ViewLifecycle.getView()));
403         }
404 
405         FieldGroup rangeFieldGroup = ComponentUtils.copy(getRangeFieldGroupPrototype());
406 
407         // Copy some properties from the "to date" field to the field group
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         // Reset some fields for the "to date" field
417         toDate.getFieldLabel().setRender(false);
418         toDate.setRefreshWhenChangedPropertyNames(null);
419         toDate.setForceSessionPersistence(true);
420 
421         // Create a "from date" field from the "to date" field
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         // add the criteria fields to the field group
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      * Class for the data object the lookup applies to.
442      *
443      * <p>The object class name is used to pick up a dictionary entry which will feed the attribute field
444      * definitions and other configuration. In addition it is to configure the
445      * {@link org.kuali.rice.krad.lookup.Lookupable} which will carry out the search action</p>
446      *
447      * @return lookup data object class
448      */
449     @BeanTagAttribute(name = "dataObjectClass")
450     public Class<?> getDataObjectClass() {
451         return this.dataObjectClass;
452     }
453 
454     /**
455      * @see LookupView#getDataObjectClass()
456      */
457     public void setDataObjectClass(Class<?> dataObjectClass) {
458         this.dataObjectClass = dataObjectClass;
459     }
460 
461     /**
462      * Convenience setter to configure the lookup data object class by class name.
463      *
464      * @param dataObjectClassName full class name for the lookup data object
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      * Indicates whether a return value link should be rendered for each result row.
476      *
477      * <p>When the lookup is called from a view (using a {@link org.kuali.rice.krad.uif.widget.QuickFinder} the return
478      * link can be returned to allow the user to return a value(s) for a selected row. Note, if this is not manually
479      * set the framework will determine when the lookup is called from a quickfinder and turn this flag on</p>
480      *
481      * @return boolean true if the return link should be rendered for each result row, false if not
482      */
483     @BeanTagAttribute(name = "renderReturnLink")
484     public Boolean isRenderReturnLink() {
485         return this.renderReturnLink;
486     }
487 
488     /**
489      * @see LookupView#isRenderReturnLink()
490      */
491     public void setRenderReturnLink(Boolean renderReturnLink) {
492         this.renderReturnLink = renderReturnLink;
493     }
494 
495     /**
496      * Indicates whether the actions column for the search results collection group should be rendered (default
497      * is true).
498      *
499      * <p>Note this is a convenience property for setting the render property on the result collection group</p>
500      *
501      * @return boolean true if the result actions column should be rendered, false if not
502      */
503     @BeanTagAttribute(name = "isRenderResultActions")
504     public boolean isRenderResultActions() {
505         return this.renderResultActions;
506     }
507 
508     /**
509      * @see LookupView#isRenderResultActions()
510      */
511     public void setRenderResultActions(boolean renderResultActions) {
512         this.renderResultActions = renderResultActions;
513     }
514 
515     /**
516      * Indicates whether links for maintenance actions (new, edit, copy, delete) should be rendered.
517      *
518      * <p>When this property is not manually set it will be enabled by the framework when a lookup is not invoked
519      * from a quickfinder (for example a standard link from a menu). Regardless if the flag is manually enabled
520      * or enabled by the framework, an additional authorization check will be performed to determine if the user
521      * has initiate permission for the maintenance document associated with the lookup data object class. If not,
522      * this flag will be disabled</p>
523      *
524      * @return boolean true if maintenance links should be rendered, false if not
525      */
526     @BeanTagAttribute(name = "renderMaintenanceLinks")
527     public Boolean isRenderMaintenanceLinks() {
528         return this.renderMaintenanceLinks;
529     }
530 
531     /**
532      * @see LookupView#isRenderMaintenanceLinks()
533      */
534     public void setRenderMaintenanceLinks(Boolean renderMaintenanceLinks) {
535         this.renderMaintenanceLinks = renderMaintenanceLinks;
536     }
537 
538     /**
539      * Indicates whether multiple values select should be enabled for the lookup.
540      *
541      * <p>When set to true, the select field is enabled for the lookup results group that allows the user
542      * to select one or more rows for returning. The framework will also set the {@link #isRenderReturnLink()}
543      * and {@link #isRenderMaintenanceLinks()} properties to false (unless manually overridden)</p>
544      *
545      * @return true if multiple values select should be enabled, false otherwise
546      */
547     @BeanTagAttribute(name = "multipleValueSelect")
548     public boolean isMultipleValuesSelect() {
549         return multipleValuesSelect;
550     }
551 
552     /**
553      * @see LookupView#isMultipleValuesSelect()
554      */
555     public void setMultipleValuesSelect(boolean multipleValuesSelect) {
556         this.multipleValuesSelect = multipleValuesSelect;
557     }
558 
559     /**
560      * List of fields that will be rendered for the lookup criteria.
561      *
562      * <p>This is a convenience property for setting the items in {@link #getCriteriaGroup()}, which is the
563      * group the criteria for the lookup is rendered in. This property can be bypassed and the items set
564      * directly in the criteria group (for more flexibility)</p>
565      *
566      * @return List of components to render as the lookup criteria
567      */
568     @ViewLifecycleRestriction
569     @BeanTagAttribute(name = "criteriaFields", type = BeanTagAttribute.AttributeType.LISTBEAN)
570     public List<Component> getCriteriaFields() {
571         return this.criteriaFields;
572     }
573 
574     /**
575      * @see LookupView#getCriteriaFields()
576      */
577     public void setCriteriaFields(List<Component> criteriaFields) {
578         this.criteriaFields = criteriaFields;
579     }
580 
581     /**
582      * Component {@link Group} instance to render as search criteria.
583      *
584      * <p>Fields that make up the criteria for the lookup will be rendered in this group. This can be used in a few
585      * different ways:
586      *
587      * <ul>
588      * <li>Set the group to have the desired layout, style, and other general group properties. Note this
589      * is done in the base lookup view. The actual criteria fields can then be configured using
590      * {@link #getCriteriaFields()}</li>
591      * <li>Configure the criteria group entirely (ignoring criteria fields). This would allow you to do things
592      * like have multiple groups for the criteria.</li>
593      * </ul></p>
594      *
595      * <p>Note the footer for the criteria group can contain actions (such as search, clear, custom actions)</p>
596      *
597      * @return group instance that will hold the search criteria fields
598      */
599     @ViewLifecycleRestriction
600     @BeanTagAttribute(name = "criteriaGroup", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
601     public Group getCriteriaGroup() {
602         return this.criteriaGroup;
603     }
604 
605     /**
606      * @see LookupView#getCriteriaGroup()
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      * List of fields that will be rendered for the result collection group, each field will be a column
622      * (assuming table layout is used).
623      *
624      * <p>This is a convenience property for setting the items in {@link #getResultsGroup()}, which is the
625      * collection group the results for the lookup is rendered in. This property can be bypassed and the items set
626      * directly in the results group (for more flexibility)</p>
627      *
628      * @return List of components to render in the results group
629      */
630     @ViewLifecycleRestriction
631     @BeanTagAttribute(name = "resultFields", type = BeanTagAttribute.AttributeType.LISTBEAN)
632     public List<Component> getResultFields() {
633         return this.resultFields;
634     }
635 
636     /**
637      * @see LookupView#getResultFields()
638      */
639     public void setResultFields(List<Component> resultFields) {
640         this.resultFields = resultFields;
641     }
642 
643     /**
644      * Component {@link CollectionGroup} instance to render for the lookup results.
645      *
646      * <p>After a search is performed, the resulting data objects will be rendered in this collection group. This
647      * collection group can be used in two ways:
648      *
649      * <ul>
650      * <li>Set the desired layout, style, and other general collection group properties. Note this is done
651      * in the base lookup view. Then the actual fields that are rendered in the collection group can be
652      * configured using {@link #getResultFields()}</li>
653      * <li>Configure the results group entirely (ignoring result fields)</li>
654      * </ul></p>
655      *
656      * <p>Note actions that are presented for the results can be configured using the
657      * {@link org.kuali.rice.krad.uif.container.CollectionGroup#getLineActions()} property</p>
658      *
659      * @return collection group instance to render for the lookup results
660      */
661     @ViewLifecycleRestriction
662     @BeanTagAttribute(name = "resultsGroup", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
663     public CollectionGroup getResultsGroup() {
664         return this.resultsGroup;
665     }
666 
667     /**
668      * @see LookupView#getResultsGroup()
669      */
670     public void setResultsGroup(CollectionGroup resultsGroup) {
671         this.resultsGroup = resultsGroup;
672     }
673 
674     /**
675      * List of property names on the configured data object class that will be used to perform the initial
676      * sorting of the search results.
677      *
678      * @return list of property names valid for the configured data object class
679      * @see LookupView#isDefaultSortAscending()
680      */
681     @BeanTagAttribute(name = "defaultSortAttributeNames", type = BeanTagAttribute.AttributeType.LISTVALUE)
682     public List<String> getDefaultSortAttributeNames() {
683         return this.defaultSortAttributeNames;
684     }
685 
686     /**
687      * @see LookupView#getDefaultSortAttributeNames()
688      */
689     public void setDefaultSortAttributeNames(List<String> defaultSortAttributeNames) {
690         this.defaultSortAttributeNames = defaultSortAttributeNames;
691     }
692 
693     /**
694      * Indicates whether the initial sort performed using {@link #getDefaultSortAttributeNames()} is done based
695      * on ascending or descending order (default is true, ascending).
696      *
697      * @return boolean true if ascending sort should be performed, false if descending sort should be
698      *         performed
699      */
700     @BeanTagAttribute(name = "defaultSortAscending")
701     public boolean isDefaultSortAscending() {
702         return this.defaultSortAscending;
703     }
704 
705     /**
706      * @see LookupView#isDefaultSortAscending()
707      */
708     public void setDefaultSortAscending(boolean defaultSortAscending) {
709         this.defaultSortAscending = defaultSortAscending;
710     }
711 
712     /**
713      * Retrieves the maximum number of records that will be listed as a result of the lookup search.
714      *
715      * @return Integer result set limit
716      */
717     @BeanTagAttribute(name = "resultSetLimit")
718     public Integer getResultSetLimit() {
719         return resultSetLimit;
720     }
721 
722     /**
723      * @see LookupView#getResultSetLimit()
724      */
725     public void setResultSetLimit(Integer resultSetLimit) {
726         this.resultSetLimit = resultSetLimit;
727     }
728 
729     /**
730      * Retrieves the maximum number of records that will be listed as a result of the multiple
731      * values select lookup search.
732      *
733      * @return multiple values select result set limit
734      */
735     @BeanTagAttribute(name = "multipleValuesSelectResultSetLimit")
736     public Integer getMultipleValuesSelectResultSetLimit() {
737         return multipleValuesSelectResultSetLimit;
738     }
739 
740     /**
741      * @see LookupView#getMultipleValuesSelectResultSetLimit()
742      */
743     public void setMultipleValuesSelectResultSetLimit(Integer multipleValuesSelectResultSetLimit) {
744         this.multipleValuesSelectResultSetLimit = multipleValuesSelectResultSetLimit;
745     }
746 
747     /**
748      * String that maps to the maintenance controller for the maintenance document (if any) associated with the
749      * lookup data object class.
750      *
751      * <p>Mapping will be used to build the maintenance action links (such as edit, copy, and new). If not given, the
752      * default maintenance mapping will be used</p>
753      *
754      * @return mapping string
755      */
756     @BeanTagAttribute(name = "maintenanceUrlMapping")
757     public String getMaintenanceUrlMapping() {
758         return maintenanceUrlMapping;
759     }
760 
761     /**
762      * @see LookupView#getMaintenanceUrlMapping()
763      */
764     public void setMaintenanceUrlMapping(String maintenanceUrlMapping) {
765         this.maintenanceUrlMapping = maintenanceUrlMapping;
766     }
767 
768     /**
769      * Indicates whether the action buttons like search in the criteria group footer should be rendered,
770      * defaults to true.
771      *
772      * @return boolean true if the criteria actions should be rendered, false if not
773      */
774     public boolean isRenderCriteriaActions() {
775         return renderCriteriaActions;
776     }
777 
778     /**
779      * @see LookupView#isRenderCriteriaActions()
780      */
781     public void setRenderCriteriaActions(boolean renderCriteriaActions) {
782         this.renderCriteriaActions = renderCriteriaActions;
783     }
784 
785     /**
786      * Indicates whether the lookup criteria group should be rendered, default to true.
787      *
788      * <p>Hiding the criteria group can be useful in cases where the criteria is passed in through the request and
789      * also the search is executed on the initial request</p>
790      *
791      * @return boolean true if criteria group should be rendered, false if not
792      */
793     public boolean isRenderLookupCriteria() {
794         return renderLookupCriteria;
795     }
796 
797     /**
798      * @see LookupView#isRenderLookupCriteria()
799      */
800     public void setRenderLookupCriteria(boolean renderLookupCriteria) {
801         this.renderLookupCriteria = renderLookupCriteria;
802     }
803 
804     /**
805      * Field group prototype that will be copied to create any date range field groups.
806      *
807      * @return field group instance to use for creating range field groups
808      */
809     @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
810     public FieldGroup getRangeFieldGroupPrototype() {
811         return rangeFieldGroupPrototype;
812     }
813 
814     /**
815      * @see LookupView#getRangeFieldGroupPrototype()
816      */
817     public void setRangeFieldGroupPrototype(FieldGroup rangeFieldGroupPrototype) {
818         this.rangeFieldGroupPrototype = rangeFieldGroupPrototype;
819     }
820 
821     /**
822      * Component {@link Message} instance to render between the range criteria fields within a range
823      * field group.
824      *
825      * @return message instance for range field group
826      */
827     @ViewLifecycleRestriction(UifConstants.ViewPhases.INITIALIZE)
828     public Message getRangedToMessage() {
829         return rangedToMessage;
830     }
831 
832     /**
833      * @see LookupView#getRangedToMessage()
834      */
835     public void setRangedToMessage(Message rangedToMessage) {
836         this.rangedToMessage = rangedToMessage;
837     }
838 
839     /**
840      * Indicates whether the 'active' criteria field must be added automatically for Inactivatable business
841      * objects.
842      *
843      * @return boolean true if active criteria should be added
844      */
845     public boolean isAutoAddActiveCriteria() {
846         return autoAddActiveCriteria;
847     }
848 
849     /**
850      * @see LookupView#isAutoAddActiveCriteria()
851      */
852     public void setAutoAddActiveCriteria(boolean autoAddActiveCriteria) {
853         this.autoAddActiveCriteria = autoAddActiveCriteria;
854     }
855 
856     /**
857      * List of secure property names that are in addition to the
858      * {@link org.kuali.rice.krad.uif.component.ComponentSecurity} or
859      * {@link org.kuali.rice.krad.datadictionary.AttributeSecurity} attributes.
860      *
861      * @return list of secure property names
862      */
863     @BeanTagAttribute(name = "additionalSecurePropertyNames", type = BeanTagAttribute.AttributeType.LISTVALUE)
864     public List<String> getAdditionalSecurePropertyNames() {
865         return additionalSecurePropertyNames;
866     }
867 
868     /**
869      * @see LookupView#getAdditionalSecurePropertyNames()
870      */
871     public void setAdditionalSecurePropertyNames(List<String> additionalSecurePropertyNames) {
872         this.additionalSecurePropertyNames = additionalSecurePropertyNames;
873     }
874 
875 }