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