001    /**
002     * Copyright 2005-2014 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.krad.uif.widget;
017    
018    import com.google.common.collect.Maps;
019    import org.apache.commons.lang.StringUtils;
020    import org.kuali.rice.krad.bo.DataObjectRelationship;
021    import org.kuali.rice.krad.datadictionary.parse.BeanTag;
022    import org.kuali.rice.krad.datadictionary.parse.BeanTagAttribute;
023    import org.kuali.rice.krad.datadictionary.parse.BeanTags;
024    import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
025    import org.kuali.rice.krad.uif.UifParameters;
026    import org.kuali.rice.krad.uif.component.BindingInfo;
027    import org.kuali.rice.krad.uif.component.Component;
028    import org.kuali.rice.krad.uif.container.CollectionGroup;
029    import org.kuali.rice.krad.uif.element.Action;
030    import org.kuali.rice.krad.uif.field.InputField;
031    import org.kuali.rice.krad.uif.util.ViewModelUtils;
032    import org.kuali.rice.krad.uif.view.View;
033    import org.kuali.rice.krad.util.KRADConstants;
034    import org.kuali.rice.krad.util.KRADUtils;
035    
036    import java.util.HashMap;
037    import java.util.List;
038    import java.util.Map;
039    
040    /**
041     * Widget for navigating to a lookup from a field (called a quickfinder)
042     *
043     * @author Kuali Rice Team (rice.collab@kuali.org)
044     */
045    @BeanTags({@BeanTag(name = "quickFinder-bean", parent = "Uif-QuickFinder"),
046            @BeanTag(name = "quickFinderByScript-bean", parent = "Uif-QuickFinderByScript"),
047            @BeanTag(name = "collectionQuickFinder-bean", parent = "Uif-CollectionQuickFinder")})
048    public class QuickFinder extends WidgetBase {
049        private static final long serialVersionUID = 3302390972815386785L;
050    
051        // lookup configuration
052        private String baseLookupUrl;
053        private String dataObjectClassName;
054        private String viewName;
055    
056        private String referencesToRefresh;
057    
058        private Map<String, String> fieldConversions;
059        private Map<String, String> lookupParameters;
060    
061        // lookup view options
062        private String readOnlySearchFields;
063    
064        private Boolean hideReturnLink;
065        private Boolean suppressActions;
066        private Boolean autoSearch;
067        private Boolean renderLookupCriteria;
068        private Boolean supplementalActionsEnabled;
069        private Boolean renderSearchButtons;
070        private Boolean renderHeader;
071        private Boolean showMaintenanceLinks;
072    
073        private Boolean multipleValuesSelect;
074        private String lookupCollectionName;
075    
076        private Action quickfinderAction;
077        private LightBox lightBoxLookup;
078    
079        public QuickFinder() {
080            super();
081    
082            fieldConversions = new HashMap<String, String>();
083            lookupParameters = new HashMap<String, String>();
084        }
085    
086        /**
087         * The following initialization is performed:
088         *
089         * <ul>
090         * <li>Set defaults for binding</li>
091         * </ul>
092         *
093         * @see org.kuali.rice.krad.uif.component.ComponentBase#performInitialization(org.kuali.rice.krad.uif.view.View,
094         *      java.lang.Object)
095         */
096        @Override
097        public void performInitialization(View view, Object model) {
098            super.performInitialization(view, model);
099    
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    }