View Javadoc

1   /**
2    * Copyright 2005-2013 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.uif.widget;
17  
18  import java.util.ArrayList;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  
23  import org.apache.commons.lang.StringUtils;
24  import org.kuali.rice.krad.bo.DataObjectRelationship;
25  import org.kuali.rice.krad.datadictionary.parse.BeanTag;
26  import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
27  import org.kuali.rice.krad.datadictionary.parse.BeanTags;
28  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
29  import org.kuali.rice.krad.uif.UifConstants;
30  import org.kuali.rice.krad.uif.UifParameters;
31  import org.kuali.rice.krad.uif.component.BindingInfo;
32  import org.kuali.rice.krad.uif.component.Component;
33  import org.kuali.rice.krad.uif.container.CollectionGroup;
34  import org.kuali.rice.krad.uif.element.Action;
35  import org.kuali.rice.krad.uif.field.InputField;
36  import org.kuali.rice.krad.uif.lifecycle.LifecycleEventListener;
37  import org.kuali.rice.krad.uif.lifecycle.ViewLifecycle;
38  import org.kuali.rice.krad.uif.service.ViewHelperService;
39  import org.kuali.rice.krad.uif.util.ScriptUtils;
40  import org.kuali.rice.krad.uif.util.ViewModelUtils;
41  import org.kuali.rice.krad.uif.view.View;
42  import org.kuali.rice.krad.util.KRADConstants;
43  import org.kuali.rice.krad.util.KRADUtils;
44  
45  /**
46   * Widget for navigating to a lookup from a field (called a quickfinder).
47   *
48   * @author Kuali Rice Team (rice.collab@kuali.org)
49   */
50  @BeanTags({@BeanTag(name = "quickFinder-bean", parent = "Uif-QuickFinder"),
51          @BeanTag(name = "quickFinderByScript-bean", parent = "Uif-QuickFinderByScript"),
52          @BeanTag(name = "collectionQuickFinder-bean", parent = "Uif-CollectionQuickFinder")})
53  public class QuickFinder extends WidgetBase implements LifecycleEventListener {
54      private static final long serialVersionUID = 3302390972815386785L;
55  
56      // lookup configuration
57      private String baseLookupUrl;
58      private String dataObjectClassName;
59      private String viewName;
60  
61      private boolean returnByScript;
62      private String readOnlyLookupFields;
63      private String referencesToRefresh;
64      private String lookupCollectionName;
65  
66      private Map<String, String> fieldConversions;
67      private Map<String, String> lookupParameters;
68  
69      private Action quickfinderAction;
70      private LightBox lightBox;
71  
72      // lookup view options
73      private Boolean renderReturnLink;
74      private Boolean renderResultActions;
75      private Boolean autoSearch;
76      private Boolean renderLookupCriteria;
77      private Boolean renderCriteriaActions;
78      private Boolean renderMaintenanceLinks;
79      private Boolean multipleValuesSelect;
80  
81      public QuickFinder() {
82          super();
83  
84          fieldConversions = new HashMap<String, String>();
85          lookupParameters = new HashMap<String, String>();
86      }
87  
88      /**
89       * The following initialization is performed:
90       *
91       * <ul>
92       * <li>Registers an event on the quickfinder action</li>
93       * </ul>
94       *
95       * {@inheritDoc}
96       */
97      @Override
98      public void performInitialization(Object model) {
99          super.performInitialization(model);
100 
101         ViewLifecycle viewLifecycle = ViewLifecycle.getActiveLifecycle();
102         viewLifecycle.registerLifecycleCompleteListener(quickfinderAction, this);
103     }
104 
105     /**
106      * The following finalization is performed:
107      *
108      * <ul>
109      * <li>Sets up the quickfinder based on whether the parent is an input field or collection group</li>
110      * <li>Adds action parameters to the quickfinder action based on the quickfinder configuration</li>
111      * </ul>
112      *
113      * {@inheritDoc}
114      */
115     @Override
116     public void performFinalize(Object model, Component parent) {
117         super.performFinalize(model, parent);
118 
119         if (parent.isReadOnly()) {
120             setRender(false);
121         }
122 
123         if (!isRender()) {
124             return;
125         }
126         
127         View view = ViewLifecycle.getActiveLifecycle().getView();
128 
129         if (parent instanceof InputField) {
130             setupForInputField(view, model, (InputField) parent);
131         } else if (parent instanceof CollectionGroup) {
132             setupForCollectionGroup(view, model, (CollectionGroup) parent);
133         }
134 
135         setupQuickfinderAction(view, model, parent);
136     }
137 
138     /**
139      * If quickfinder not manually configured attempts to find a relationship to build the quickfinder on, then also
140      * adjusts the path for any configured field conversions, lookup parameters, and refresh refreshes.
141      *
142      * @param view view instance the quickfinder is associated with
143      * @param model object containing the view data
144      * @param inputField input field instance the quickfinder should apply to
145      */
146     protected void setupForInputField(View view, Object model, InputField inputField) {
147         // if quickfinder class name not specified, attempt to find a relationship to build the quickfinder from
148         if (StringUtils.isBlank(dataObjectClassName)) {
149             DataObjectRelationship relationship = getRelationshipForField(view, model, inputField);
150 
151             // if no relationship found cannot have a quickfinder
152             if (relationship == null) {
153                 setRender(false);
154 
155                 return;
156             }
157 
158             dataObjectClassName = relationship.getRelatedClass().getName();
159 
160             if ((fieldConversions == null) || fieldConversions.isEmpty()) {
161                 generateFieldConversions(relationship);
162             }
163 
164             if ((lookupParameters == null) || lookupParameters.isEmpty()) {
165                 generateLookupParameters(relationship);
166             }
167         }
168 
169         // adjust paths based on associated attribute field
170         updateFieldConversions(inputField.getBindingInfo());
171         updateLookupParameters(inputField.getBindingInfo());
172         updateReferencesToRefresh(inputField.getBindingInfo());
173     }
174 
175     /**
176      * Retrieves any {@link org.kuali.rice.krad.bo.DataObjectRelationship} that is associated with the given
177      * field and has a configured lookup view.
178      *
179      * @param view view instance the quickfinder is associated with
180      * @param model object containing the view data
181      * @param field input field instance the quickfinder should apply to
182      * @return data object relationship for the field, or null if one could not be found
183      */
184     protected DataObjectRelationship getRelationshipForField(View view, Object model, InputField field) {
185         String propertyName = field.getBindingInfo().getBindingName();
186 
187         // get object instance and class for parent
188         Object parentObject = ViewModelUtils.getParentObjectForMetadata(view, model, field);
189         Class<?> parentObjectClass = null;
190         if (parentObject != null) {
191             parentObjectClass = parentObject.getClass();
192         }
193 
194         // get relationship from metadata service
195         return KRADServiceLocatorWeb.getLegacyDataAdapter().getDataObjectRelationship(parentObject,
196                 parentObjectClass, propertyName, "", true, true, false);
197     }
198 
199     /**
200      * Generates the lookup field conversions based on the references from the given relationship.
201      *
202      * @param relationship relationship field conversions will be generated from
203      */
204     protected void generateFieldConversions(DataObjectRelationship relationship) {
205         fieldConversions = new HashMap<String, String>();
206 
207         for (Map.Entry<String, String> entry : relationship.getParentToChildReferences().entrySet()) {
208             String fromField = entry.getValue();
209             String toField = entry.getKey();
210 
211             fieldConversions.put(fromField, toField);
212         }
213     }
214 
215     /**
216      * Generates the lookup parameters based on the references from the given relationship.
217      *
218      * @param relationship relationship lookup parameters will be generated from
219      */
220     protected void generateLookupParameters(DataObjectRelationship relationship) {
221         lookupParameters = new HashMap<String, String>();
222 
223         for (Map.Entry<String, String> entry : relationship.getParentToChildReferences().entrySet()) {
224             String fromField = entry.getKey();
225             String toField = entry.getValue();
226 
227             if (relationship.getUserVisibleIdentifierKey() == null || relationship.getUserVisibleIdentifierKey().equals(
228                     fromField)) {
229                 lookupParameters.put(fromField, toField);
230             }
231         }
232     }
233 
234     /**
235      * Adjusts the path on the field conversion to property to match the binding path prefix of the
236      * given {@link org.kuali.rice.krad.uif.component.BindingInfo}.
237      *
238      * @param bindingInfo binding info instance to copy binding path prefix from
239      */
240     protected void updateFieldConversions(BindingInfo bindingInfo) {
241         Map<String, String> adjustedFieldConversions = new HashMap<String, String>();
242         for (String fromField : fieldConversions.keySet()) {
243             String toField = fieldConversions.get(fromField);
244             String adjustedToFieldPath = bindingInfo.getPropertyAdjustedBindingPath(toField);
245 
246             adjustedFieldConversions.put(fromField, adjustedToFieldPath);
247         }
248 
249         this.fieldConversions = adjustedFieldConversions;
250     }
251 
252     /**
253      * Adjusts the path on the lookup parameter from property to match the binding path prefix of the
254      * given {@link org.kuali.rice.krad.uif.component.BindingInfo}.
255      *
256      * @param bindingInfo binding info instance to copy binding path prefix from
257      */
258     protected void updateLookupParameters(BindingInfo bindingInfo) {
259         Map<String, String> adjustedLookupParameters = new HashMap<String, String>();
260         for (String fromField : lookupParameters.keySet()) {
261             String toField = lookupParameters.get(fromField);
262             String adjustedFromFieldPath = bindingInfo.getPropertyAdjustedBindingPath(fromField);
263 
264             adjustedLookupParameters.put(adjustedFromFieldPath, toField);
265         }
266 
267         this.lookupParameters = adjustedLookupParameters;
268     }
269 
270     /**
271      * Adjust the path on the referencesToRefresh parameter to match the binding path prefix of the
272      * given {@link org.kuali.rice.krad.uif.component.BindingInfo}.
273      *
274      * @param bindingInfo binding info instance to copy binding path prefix from
275      */
276     protected void updateReferencesToRefresh(BindingInfo bindingInfo) {
277         List<String> adjustedReferencesToRefresh = new ArrayList<String>();
278 
279         if (referencesToRefresh == null) {
280             referencesToRefresh = new String();
281         }
282 
283         for (String reference : StringUtils.split(referencesToRefresh, KRADConstants.REFERENCES_TO_REFRESH_SEPARATOR)) {
284             adjustedReferencesToRefresh.add(bindingInfo.getPropertyAdjustedBindingPath(reference));
285         }
286 
287         this.referencesToRefresh = StringUtils.join(adjustedReferencesToRefresh,
288                 KRADConstants.REFERENCES_TO_REFRESH_SEPARATOR);
289     }
290 
291     /**
292      * Configures the quickfinder for the given collection group instance by setting the data object class,
293      * field conversions, and lookup collection name (if necessary).
294      *
295      * @param view view instance the quickfinder is associated with
296      * @param model object containing the view data
297      * @param collectionGroup collection group instance to build quickfinder for
298      */
299     protected void setupForCollectionGroup(View view, Object model, CollectionGroup collectionGroup) {
300         // check to see if data object class is configured for lookup, if so we will assume it should be enabled
301         // if not and the class configured for the collection group is lookupable, use that
302         if (StringUtils.isBlank(getDataObjectClassName())) {
303             Class<?> collectionObjectClass = collectionGroup.getCollectionObjectClass();
304 
305             boolean isCollectionClassLookupable = KRADServiceLocatorWeb.getViewDictionaryService().isLookupable(
306                     collectionObjectClass);
307             if (isCollectionClassLookupable) {
308                 setDataObjectClassName(collectionObjectClass.getName());
309 
310                 // use PK fields for collection class as default field conversions
311                 if ((fieldConversions == null) || fieldConversions.isEmpty()) {
312                     List<String> collectionObjectPKFields =
313                             KRADServiceLocatorWeb.getLegacyDataAdapter().listPrimaryKeyFieldNames(
314                                     collectionObjectClass);
315 
316                     fieldConversions = new HashMap<String, String>();
317                     for (String pkField : collectionObjectPKFields) {
318                         fieldConversions.put(pkField, pkField);
319                     }
320                 }
321             } else {
322                 // no available data object class to lookup so disable quickfinder
323                 setRender(false);
324             }
325         }
326 
327         // set the lookup return collection name to this collection path
328         if (isRender() && StringUtils.isBlank(getLookupCollectionName())) {
329             setLookupCollectionName(collectionGroup.getBindingInfo().getBindingPath());
330         }
331     }
332 
333     /**
334      * Adjusts the id for the quickfinder action, and then adds action parameters for passing along the
335      * quickfinder configuration to the lookup view.
336      *
337      * @param view view instance the quickfinder is associated with
338      * @param model object containing the view data
339      * @param parent component instance the quickfinder is associated with
340      */
341     protected void setupQuickfinderAction(View view, Object model, Component parent) {
342         quickfinderAction.setId(getId() + UifConstants.IdSuffixes.ACTION);
343 
344         if ((lightBox != null) && lightBox.isRender()) {
345             String lightboxScript = UifConstants.JsFunctions.CREATE_LIGHTBOX_POST + "(\"" + quickfinderAction.getId()
346                     + "\"," + lightBox.getTemplateOptionsJSString() + "," + returnByScript + ");";
347 
348             quickfinderAction.setActionScript(lightboxScript);
349         }
350 
351         quickfinderAction.addActionParameter(UifParameters.BASE_LOOKUP_URL, baseLookupUrl);
352         quickfinderAction.addActionParameter(UifParameters.DATA_OBJECT_CLASS_NAME, dataObjectClassName);
353 
354         if (!fieldConversions.isEmpty()) {
355             quickfinderAction.addActionParameter(UifParameters.CONVERSION_FIELDS, KRADUtils.buildMapParameterString(
356                     fieldConversions));
357         }
358 
359         if (!lookupParameters.isEmpty()) {
360             quickfinderAction.addActionParameter(UifParameters.LOOKUP_PARAMETERS, KRADUtils.buildMapParameterString(
361                     lookupParameters));
362         }
363 
364         addActionParameterIfNotNull(UifParameters.VIEW_NAME, viewName);
365         addActionParameterIfNotNull(UifParameters.READ_ONLY_FIELDS, readOnlyLookupFields);
366         addActionParameterIfNotNull(UifParameters.RENDER_RETURN_LINK, renderReturnLink);
367         addActionParameterIfNotNull(UifParameters.RENDER_RESULT_ACTIONS, renderResultActions);
368         addActionParameterIfNotNull(UifParameters.REFERENCES_TO_REFRESH, referencesToRefresh);
369         addActionParameterIfNotNull(UifParameters.AUTO_SEARCH, autoSearch);
370         addActionParameterIfNotNull(UifParameters.RENDER_LOOKUP_CRITERIA, renderLookupCriteria);
371         addActionParameterIfNotNull(UifParameters.RENDER_CRITERIA_ACTIONS, renderCriteriaActions);
372         addActionParameterIfNotNull(UifParameters.RENDER_MAINTENANCE_LINKS, renderMaintenanceLinks);
373         addActionParameterIfNotNull(UifParameters.MULTIPLE_VALUES_SELECT, multipleValuesSelect);
374         addActionParameterIfNotNull(UifParameters.LOOKUP_COLLECTION_NAME, lookupCollectionName);
375         addActionParameterIfNotNull(UifParameters.QUICKFINDER_ID, getId());
376     }
377 
378     /**
379      * Utility method to add an action parameter to the quickfinder action if the given parameter value
380      * is non blank.
381      *
382      * @param parameterName name of the parameter to add
383      * @param parameterValue value for the parameter to add
384      */
385     protected void addActionParameterIfNotNull(String parameterName, Object parameterValue) {
386         if ((parameterValue != null) && StringUtils.isNotBlank(parameterValue.toString())) {
387             quickfinderAction.addActionParameter(parameterName, parameterValue.toString());
388         }
389     }
390 
391     /**
392      * {@inheritDoc}
393      */
394     @Override
395     public List<Component> getComponentsForLifecycle() {
396         List<Component> components = super.getComponentsForLifecycle();
397 
398         components.add(quickfinderAction);
399         components.add(lightBox);
400 
401         return components;
402     }
403 
404     /**
405      * Adds post context data for the quickfinder so when the lookup return occurs the focus and jump point
406      * of the quickfinder action can be retrieved.
407      *
408      * @see org.kuali.rice.krad.uif.lifecycle.LifecycleEventListener#processEvent(org.kuali.rice.krad.uif.lifecycle.ViewLifecycle.LifecycleEvent,
409      *      org.kuali.rice.krad.uif.view.View, java.lang.Object, org.kuali.rice.krad.uif.component.Component)
410      */
411     @Override
412     public void processEvent(ViewLifecycle.LifecycleEvent lifecycleEvent, View view, Object model,
413             Component eventComponent) {
414         Action finalQuickfinderAction = (Action) eventComponent;
415 
416         // add post metadata for focus point when the associated lookup returns
417         view.getViewIndex().addPostContextEntry(getId(), UifConstants.PostContextKeys.QUICKFINDER_FOCUS_ID,
418                 finalQuickfinderAction.getFocusOnIdAfterSubmit());
419         view.getViewIndex().addPostContextEntry(getId(), UifConstants.PostContextKeys.QUICKFINDER_JUMP_TO_ID,
420                 finalQuickfinderAction.getJumpToIdAfterSubmit());
421     }
422 
423     /**
424      * Returns the URL for the lookup for which parameters will be added.
425      *
426      * <p>The base URL includes the domain, context, and controller mapping for the lookup invocation. Parameters are
427      * then added based on configuration to complete the URL. This is generally defaulted to the application URL and
428      * internal KRAD servlet mapping, but can be changed to invoke another application such as the Rice standalone
429      * server</p>
430      *
431      * @return lookup base URL
432      */
433     @BeanTagAttribute(name = "baseLookupUrl")
434     public String getBaseLookupUrl() {
435         return this.baseLookupUrl;
436     }
437 
438     /**
439      * @see QuickFinder#getBaseLookupUrl()
440      */
441     public void setBaseLookupUrl(String baseLookupUrl) {
442         this.baseLookupUrl = baseLookupUrl;
443     }
444 
445     /**
446      * Full class name the lookup should be provided for.
447      *
448      * <p>This is passed on to the lookup request for the data object the lookup should be rendered for. This is then
449      * used by the lookup framework to select the lookup view (if more than one lookup view exists for the same
450      * data object class name, the {@link #getViewName()} property should be specified to select the view to
451      * render).</p>
452      *
453      * @return lookup class name
454      */
455     @BeanTagAttribute(name = "dataOjbectClassName")
456     public String getDataObjectClassName() {
457         return this.dataObjectClassName;
458     }
459 
460     /**
461      * @see QuickFinder#getDataObjectClassName()
462      */
463     public void setDataObjectClassName(String dataObjectClassName) {
464         this.dataObjectClassName = dataObjectClassName;
465     }
466 
467     /**
468      * When multiple target lookup views exists for the same data object class, the view name can be set to
469      * determine which one to use.
470      *
471      * <p>When creating multiple lookup views for the same data object class, the view name can be specified for the
472      * different versions (for example 'simple' and 'advanced'). When multiple lookup views exist the view name must
473      * be sent with the data object class for the request. Note the view id can be alternatively used to uniquely
474      * identify the lookup view</p>
475      *
476      * @return String name of lookup view
477      */
478     @BeanTagAttribute(name = "viewName")
479     public String getViewName() {
480         return this.viewName;
481     }
482 
483     /**
484      * @see QuickFinder#getViewName()
485      */
486     public void setViewName(String viewName) {
487         this.viewName = viewName;
488     }
489 
490     /**
491      * Indicates whether the lookup return should occur through script, or by refresing the page (making server
492      * request).
493      *
494      * <p>For quickfinders that do not need any additional server side action, return through script can be
495      * much faster and prevents a page refresh.</p>
496      *
497      * @return boolean true if the return should occur through script, false if not (default)
498      */
499     public boolean isReturnByScript() {
500         return returnByScript;
501     }
502 
503     /**
504      * @see QuickFinder#isReturnByScript()
505      */
506     public void setReturnByScript(boolean returnByScript) {
507         this.returnByScript = returnByScript;
508     }
509 
510     /**
511      * Comma delimited String of property names on the lookup view that should be read only.
512      *
513      * <p>When requesting a lookup view, property names for fields that are rendered as search criteria can be marked
514      * as read-only. This is usually done when a lookup parameter for that property is sent in and the user should
515      * not be allowed to change the value</p>
516      *
517      * @return property names (delimited by a comma) whose criteria fields should be read-only on the
518      *         lookup view
519      */
520     @BeanTagAttribute(name = "readOnlyLookupFields")
521     public String getReadOnlyLookupFields() {
522         return this.readOnlyLookupFields;
523     }
524 
525     /**
526      * @see QuickFinder#setReadOnlyLookupFields(java.lang.String)
527      */
528     public void setReadOnlyLookupFields(String readOnlyLookupFields) {
529         this.readOnlyLookupFields = readOnlyLookupFields;
530     }
531 
532     /**
533      * List of property names on the model that should be refreshed when the lookup returns.
534      *
535      * <p>Note this is only relevant when the return by script option is not enabled (meaning the server will be
536      * invoked
537      * on the lookup return call)</p>
538      *
539      * <p>When a lookup return call is made (to return a result value) the controller refresh method will be invoked.
540      * If
541      * refresh properties are configured, a call to refresh those references from the database will be made. This is
542      * useful if the lookup returns a foreign key field and the related record is needed.</p>
543      *
544      * @return list of property names to refresh
545      */
546     @BeanTagAttribute(name = "referencesToRefresh")
547     public String getReferencesToRefresh() {
548         return this.referencesToRefresh;
549     }
550 
551     /**
552      * @see QuickFinder#getReferencesToRefresh()
553      */
554     public void setReferencesToRefresh(String referencesToRefresh) {
555         this.referencesToRefresh = referencesToRefresh;
556     }
557 
558     /**
559      * Map that determines what properties from a result lookup row (if selected) will be returned to properties on
560      * the calling view.
561      *
562      * <p>The purpose of using the lookup is to search for a particular value and return that value to the form being
563      * completed. In order for the lookup framework to return the field back to us, we must specify the name of the
564      * field on the data object class whose value we need, and the name of the field on the calling view. Furthermore,
565      * we can choose to have the lookup return additional fields that populate other form fields or informational
566      * properties (see ‘Field Queries and Informational Properties’). These pairs of fields are known as
567      * ‘field conversions’.</p>
568      *
569      * <p>The fieldConversions property is a Map. Each entry represents a field that will be returned back from the
570      * lookup, with the entry key being the field name on the data object class, and the entry value being the field
571      * name on the calling view. It is helpful to think of this as a from-to mapping. Pulling from the data object
572      * field (map key) to the calling view field (map value).</p>
573      *
574      * @return mapping of lookup data object property names to view property names
575      */
576     @BeanTagAttribute(name = "fieldConversions", type = BeanTagAttribute.AttributeType.MAPVALUE)
577     public Map<String, String> getFieldConversions() {
578         return this.fieldConversions;
579     }
580 
581     /**
582      * @see QuickFinder#getFieldConversions()
583      */
584     public void setFieldConversions(Map<String, String> fieldConversions) {
585         this.fieldConversions = fieldConversions;
586     }
587 
588     /**
589      * Map that determines what properties from a calling view will be sent to properties on that are rendered
590      * for the lookup view's search fields (they can be hidden).
591      *
592      * <p> When invoking a lookup view, we can pre-populate search fields on the lookup view with data from the view
593      * that called the lookup. The user can then perform the search with these values, or (if edited is allowed or
594      * the fields are not hidden) change the passed in values. When the lookup is invoked, the values for the
595      * properties configured within the lookup parameters Map will be pulled and passed along as values for the
596      * lookup view properties</p>
597      *
598      * @return mapping of calling view properties to lookup view search fields
599      */
600     @BeanTagAttribute(name = "lookupParameters", type = BeanTagAttribute.AttributeType.MAPVALUE)
601     public Map<String, String> getLookupParameters() {
602         return this.lookupParameters;
603     }
604 
605     /**
606      * @see QuickFinder#getLookupParameters()
607      */
608     public void setLookupParameters(Map<String, String> lookupParameters) {
609         this.lookupParameters = lookupParameters;
610     }
611 
612     /**
613      * Indicates whether the return links for lookup results should be rendered.
614      *
615      * <p>A lookup view can be invoked to allow the user to select a value (or set of values) to return back to the
616      * calling view. For single value lookups this is done with a return link that is rendered for each row. This
617      * return link can be disabled by setting this property to false</p>
618      *
619      * @return true if the return link should not be shown, false if it should be
620      */
621     @BeanTagAttribute(name = "renderReturnLink")
622     public Boolean getRenderReturnLink() {
623         return this.renderReturnLink;
624     }
625 
626     /**
627      * @see QuickFinder#getRenderReturnLink()
628      */
629     public void setRenderReturnLink(Boolean renderReturnLink) {
630         this.renderReturnLink = renderReturnLink;
631     }
632 
633     /**
634      * Indicates whether the maintenance actions (or others) are rendered on the invoked lookup view.
635      *
636      * <p>By default a lookup view will add an actions column for the result table that display maintenance links (in
637      * addition to a new link at the top of the page) if a maintenance action is available. Custom links can also be
638      * added to the action column as necessary. This flag can be set to true to suppress the rendering of the actions
639      * for the lookup call.</p>
640      *
641      * @return true if actions should be rendered, false if not
642      */
643     @BeanTagAttribute(name = "renderResultActions")
644     public Boolean getRenderResultActions() {
645         return renderResultActions;
646     }
647 
648     /**
649      * @see QuickFinder#getRenderResultActions()
650      */
651     public void setRenderResultActions(Boolean renderResultActions) {
652         this.renderResultActions = renderResultActions;
653     }
654 
655     /**
656      * Indicates whether the search should be executed when first rendering the lookup view.
657      *
658      * <p>By default the lookup view is rendered, the user enters search values and executes the results. This flag can
659      * be set to true to indicate the search should be performed before showing the screen to the user. This is
660      * generally used when search criteria is being passed in as well</p>
661      *
662      * @return true if the search should be performed initially, false if not
663      */
664     @BeanTagAttribute(name = "autoSearch")
665     public Boolean getAutoSearch() {
666         return this.autoSearch;
667     }
668 
669     /**
670      * @see org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute#name()
671      */
672     public void setAutoSearch(Boolean autoSearch) {
673         this.autoSearch = autoSearch;
674     }
675 
676     /**
677      * Indicates whether the lookup criteria (search group) should be enabled on the invoked lookup view.
678      *
679      * <p> Setting the this to false will not display the lookup criteria but only the results. Therefore this is only
680      * useful when setting {@link #getAutoSearch()} to true and passing in criteria</p>
681      *
682      * @return true if lookup criteria should be displayed, false if not
683      */
684     @BeanTagAttribute(name = "renderLookupCriteria")
685     public Boolean getRenderLookupCriteria() {
686         return this.renderLookupCriteria;
687     }
688 
689     /**
690      * @see QuickFinder#getRenderLookupCriteria()
691      */
692     public void setRenderLookupCriteria(Boolean renderLookupCriteria) {
693         this.renderLookupCriteria = renderLookupCriteria;
694     }
695 
696     /**
697      * Indicates whether the criteria actions (footer) should be rendered on the invoked lookup view.
698      *
699      * @return boolean true if actions should be rendered (default), false if not
700      */
701     @BeanTagAttribute(name = "renderCriteriaActions")
702     public Boolean getRenderCriteriaActions() {
703         return this.renderCriteriaActions;
704     }
705 
706     /**
707      * @see QuickFinder#getRenderCriteriaActions()
708      */
709     public void setRenderCriteriaActions(Boolean renderCriteriaActions) {
710         this.renderCriteriaActions = renderCriteriaActions;
711     }
712 
713     /**
714      * Indicates whether the maintenance action links should be rendered for the invoked lookup view.
715      *
716      * <p>If a maintenance view exists for the data object associated with the lookup view, the framework will add
717      * links to initiate a new maintenance document. This flag can be used to disable the rendering of these links</p>
718      *
719      * <p> Note this serves similar purpose to {@link #getRenderResultActions()} but the intent is to only remove the
720      * maintenance links in this situation, not the complete actions column</p>
721      *
722      * @return true if maintenance links should be shown on the lookup view, false if not
723      */
724     @BeanTagAttribute(name = "renderMaintenanceLinks")
725     public Boolean getRenderMaintenanceLinks() {
726         return this.renderMaintenanceLinks;
727     }
728 
729     /**
730      * @see QuickFinder#getRenderMaintenanceLinks()
731      */
732     public void setRenderMaintenanceLinks(Boolean renderMaintenanceLinks) {
733         this.renderMaintenanceLinks = renderMaintenanceLinks;
734     }
735 
736     /**
737      * Action component that is used to rendered for the field for invoking the quickfinder action (bringing up the
738      * lookup).
739      *
740      * <p>Through the action configuration the image (or link, button) rendered for the quickfinder can be modified. In
741      * addition to other action component settings</p>
742      *
743      * @return Action instance rendered for quickfinder
744      */
745     @BeanTagAttribute(name = "quickfinderAction", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
746     public Action getQuickfinderAction() {
747         return this.quickfinderAction;
748     }
749 
750     /**
751      * @see QuickFinder#getQuickfinderAction()
752      */
753     public void setQuickfinderAction(Action quickfinderAction) {
754         this.quickfinderAction = quickfinderAction;
755     }
756 
757     /**
758      * Lightbox widget that will be used to view the invoked lookup view.
759      *
760      * <p>Note if the lightbox is not configured, or set to not render the lookup will be invoked based on
761      * the action alone (for example a new tab/window)</p>
762      *
763      * @return lightbox instance for viewing the lookup
764      */
765     @BeanTagAttribute(name = "lightBox", type = BeanTagAttribute.AttributeType.SINGLEBEAN)
766     public LightBox getLightBox() {
767         return lightBox;
768     }
769 
770     /**
771      * @see QuickFinder#getLightBox()
772      */
773     public void setLightBox(LightBox lightBox) {
774         this.lightBox = lightBox;
775     }
776 
777     /**
778      * Indicates whether the invoked lookup view should allow multiple values to be selected and returned.
779      *
780      * @return true if multi-value lookup should be requested, false for normal lookup
781      */
782     @BeanTagAttribute(name = "MultipleValuesSelect")
783     public Boolean getMultipleValuesSelect() {
784         return multipleValuesSelect;
785     }
786 
787     /**
788      * @see QuickFinder#getMultipleValuesSelect()
789      */
790     public void setMultipleValuesSelect(Boolean multipleValuesSelect) {
791         this.multipleValuesSelect = multipleValuesSelect;
792     }
793 
794     /**
795      * For the case of multi-value lookup, indicates the collection that should be populated with
796      * the return results.
797      *
798      * <p>Note when the quickfinder is associated with a {@link CollectionGroup}, this property is
799      * set automatically from the collection name associated with the group</p>
800      *
801      * @return collection name (must be full binding path)
802      */
803     @BeanTagAttribute(name = "lookupCollectionName")
804     public String getLookupCollectionName() {
805         return lookupCollectionName;
806     }
807 
808     /**
809      * @see QuickFinder#getLookupCollectionName()
810      */
811     public void setLookupCollectionName(String lookupCollectionName) {
812         this.lookupCollectionName = lookupCollectionName;
813     }
814 
815     /**
816      * @see org.kuali.rice.krad.datadictionary.DictionaryBeanBase#copyProperties(Object)
817      */
818     @Override
819     protected <T> void copyProperties(T component) {
820         super.copyProperties(component);
821 
822         QuickFinder quickFinderCopy = (QuickFinder) component;
823 
824         quickFinderCopy.setBaseLookupUrl(this.baseLookupUrl);
825         quickFinderCopy.setDataObjectClassName(this.dataObjectClassName);
826         quickFinderCopy.setViewName(this.viewName);
827         quickFinderCopy.setReferencesToRefresh(this.referencesToRefresh);
828 
829         if (fieldConversions != null) {
830             quickFinderCopy.setFieldConversions(new HashMap<String, String>(this.fieldConversions));
831         }
832 
833         if (lookupParameters != null) {
834             quickFinderCopy.setLookupParameters(new HashMap<String, String>(this.lookupParameters));
835         }
836 
837         quickFinderCopy.setReturnByScript(this.returnByScript);
838         quickFinderCopy.setReadOnlyLookupFields(this.readOnlyLookupFields);
839         quickFinderCopy.setRenderReturnLink(this.renderReturnLink);
840         quickFinderCopy.setRenderResultActions(this.renderResultActions);
841         quickFinderCopy.setAutoSearch(this.autoSearch);
842         quickFinderCopy.setRenderLookupCriteria(this.renderLookupCriteria);
843         quickFinderCopy.setRenderCriteriaActions(this.renderCriteriaActions);
844         quickFinderCopy.setRenderMaintenanceLinks(this.renderMaintenanceLinks);
845         quickFinderCopy.setMultipleValuesSelect(this.multipleValuesSelect);
846         quickFinderCopy.setLookupCollectionName(this.lookupCollectionName);
847 
848         if (lightBox != null) {
849             quickFinderCopy.setLightBox((LightBox) this.lightBox.copy());
850         }
851 
852         if (this.quickfinderAction != null) {
853             quickFinderCopy.setQuickfinderAction((Action) this.quickfinderAction.copy());
854         }
855     }
856 }