View Javadoc

1   /**
2    * Copyright 2005-2012 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.kns.web.struts.form;
17  
18  import org.apache.commons.lang.BooleanUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.util.Truth;
21  import org.kuali.rice.kns.lookup.LookupUtils;
22  import org.kuali.rice.kns.lookup.Lookupable;
23  import org.kuali.rice.kns.service.KNSServiceLocator;
24  import org.kuali.rice.kns.web.ui.Field;
25  import org.kuali.rice.kns.web.ui.Row;
26  import org.kuali.rice.krad.bo.BusinessObject;
27  import org.kuali.rice.krad.service.DataDictionaryService;
28  import org.kuali.rice.krad.service.KRADServiceLocator;
29  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
30  import org.kuali.rice.krad.util.ExternalizableBusinessObjectUtils;
31  import org.kuali.rice.krad.util.KRADConstants;
32  
33  import javax.servlet.http.HttpServletRequest;
34  import java.util.HashMap;
35  import java.util.Iterator;
36  import java.util.List;
37  import java.util.Map;
38  
39  /**
40   * This class is the action form for all lookups.
41   */
42  public class LookupForm extends KualiForm {
43      private static final long serialVersionUID = 1L;
44  
45      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LookupForm.class);
46      protected static final String HEADER_BAR_ENABLED_PARAM = "headerBarEnabled";
47      protected static final String SEARCH_CRITERIA_ENABLED_PARAM = "searchCriteriaEnabled";
48  
49      private String formKey;
50      private Map<String, String> fields;
51      private Map<String, String> fieldsForLookup;
52      private String lookupableImplServiceName;
53      private String conversionFields;
54      private Map<String, String> fieldConversions;
55      private String businessObjectClassName;
56      private Lookupable lookupable;
57      private boolean hideReturnLink = false;
58      private boolean suppressActions = false;
59      private boolean multipleValues = false;
60      private String lookupAnchor;
61      private String readOnlyFields;
62      private List readOnlyFieldsList;
63      private String referencesToRefresh;
64      private boolean searchUsingOnlyPrimaryKeyValues;
65      private String primaryKeyFieldLabels;
66      private boolean showMaintenanceLinks = false;
67      private String docNum;
68      private String htmlDataType;
69      private String lookupObjectId;
70  	private boolean lookupCriteriaEnabled = true;
71      private boolean supplementalActionsEnabled = false;
72      private boolean actionUrlsExist = false;
73      private boolean ddExtraButton = false;
74  	private boolean headerBarEnabled = true;
75  	private boolean disableSearchButtons = false;
76      
77      /**
78       * @see KualiForm#addRequiredNonEditableProperties()
79       */
80      public void addRequiredNonEditableProperties(){
81      	super.addRequiredNonEditableProperties();
82      	registerRequiredNonEditableProperty(KRADConstants.LOOKUPABLE_IMPL_ATTRIBUTE_NAME);
83      	registerRequiredNonEditableProperty(KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
84      	registerRequiredNonEditableProperty(KRADConstants.DISPATCH_REQUEST_PARAMETER);
85      	registerRequiredNonEditableProperty(KRADConstants.DOC_FORM_KEY);
86      	registerRequiredNonEditableProperty(KRADConstants.REFRESH_CALLER);
87      	registerRequiredNonEditableProperty(KRADConstants.DOC_NUM);
88      	registerRequiredNonEditableProperty(KRADConstants.REFERENCES_TO_REFRESH);
89      	registerRequiredNonEditableProperty(KRADConstants.FORM_KEY);
90      	registerRequiredNonEditableProperty(KRADConstants.CONVERSION_FIELDS_PARAMETER);
91      	registerRequiredNonEditableProperty(KRADConstants.FIELDS_CONVERSION_PARAMETER);
92      	registerRequiredNonEditableProperty(KRADConstants.HIDE_LOOKUP_RETURN_LINK);
93      	registerRequiredNonEditableProperty(KRADConstants.MULTIPLE_VALUE);
94      	registerRequiredNonEditableProperty(KRADConstants.BACK_LOCATION);
95      	registerRequiredNonEditableProperty(KRADConstants.LOOKUP_ANCHOR);
96      	registerRequiredNonEditableProperty("searchUsingOnlyPrimaryKeyValues");
97      	registerRequiredNonEditableProperty(KRADConstants.MULTIPLE_VALUE_LOOKUP_PREVIOUSLY_SELECTED_OBJ_IDS_PARAM);
98      	registerRequiredNonEditableProperty(KRADConstants.TableRenderConstants.VIEWED_PAGE_NUMBER);
99      }
100     
101     /**
102 	 * @return the htmlDataType
103 	 */
104 	public String getHtmlDataType() {
105 		return this.htmlDataType;
106 	}
107 
108 	/**
109 	 * @param htmlDataType the htmlDataType to set
110 	 */
111 	public void setHtmlDataType(String htmlDataType) {
112 		this.htmlDataType = htmlDataType;
113 	}
114 
115 	/**
116 	 * @return the docNum
117 	 */
118 	public String getDocNum() {
119 		return this.docNum;
120 	}
121 
122 	/**
123 	 * @param docNum the docNum to set
124 	 */
125 	public void setDocNum(String docNum) {
126 		this.docNum = docNum;
127 	}
128 
129 	/**
130      * Whether the results contain at least one row that is returnable.
131      */
132     private boolean hasReturnableRow;
133     
134     
135     // used for internal purposes in populate
136     private Map requestParameters;
137     
138     /**
139      * Stores the incoming request parameters so that they can be passed to the Lookupable implementation.
140      */
141     @Override
142     public void postprocessRequestParameters(Map requestParameters) {
143         this.requestParameters = requestParameters;
144         super.postprocessRequestParameters(requestParameters);
145     }
146 
147     /**
148      * Picks out business object name from the request to get retrieve a lookupable and set properties.
149      */
150     public void populate(HttpServletRequest request) {
151         super.populate(request);
152 
153         DataDictionaryService ddService = KRADServiceLocatorWeb.getDataDictionaryService();
154 
155         try {
156             Lookupable localLookupable = null;
157             if (StringUtils.isBlank(getParameter(request, KRADConstants.LOOKUPABLE_IMPL_ATTRIBUTE_NAME)) && StringUtils.isBlank(getLookupableImplServiceName())) {
158                 // get the business object class for the lookup
159                 String localBusinessObjectClassName = getParameter(request, KRADConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE);
160                 if ( ExternalizableBusinessObjectUtils.isExternalizableBusinessObjectInterface(localBusinessObjectClassName) ) {
161                 	Class localBusinessObjectClass = Class.forName(localBusinessObjectClassName);
162                 	localBusinessObjectClassName = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(localBusinessObjectClass).getExternalizableBusinessObjectImplementation(localBusinessObjectClass).getName();
163                 }
164                 setBusinessObjectClassName(localBusinessObjectClassName);
165                 if (StringUtils.isBlank(localBusinessObjectClassName)) {
166                     LOG.error("Business object class not passed to lookup.");
167                     throw new RuntimeException("Business object class not passed to lookup.");
168                 }
169 
170                 // call data dictionary service to get lookup impl for bo class
171                 String lookupImplID = KNSServiceLocator.getBusinessObjectDictionaryService().getLookupableID(Class.forName(localBusinessObjectClassName));
172                 if (lookupImplID == null) {
173                     lookupImplID = "kualiLookupable";
174                 }
175 
176                 setLookupableImplServiceName(lookupImplID);
177             }
178             
179             localLookupable = this.getLookupable(getLookupableImplServiceName());
180 
181             if (localLookupable == null) {
182                 LOG.error("Lookup impl not found for lookup impl name " + getLookupableImplServiceName());
183                 throw new RuntimeException("Lookup impl not found for lookup impl name " + getLookupableImplServiceName());
184             }
185 
186 			// set parameters on lookupable
187             localLookupable.setParameters(requestParameters);
188             requestParameters = null;
189             
190             if (getParameter(request, KRADConstants.LOOKUPABLE_IMPL_ATTRIBUTE_NAME) != null) {
191                 setLookupableImplServiceName(getParameter(request, KRADConstants.LOOKUPABLE_IMPL_ATTRIBUTE_NAME));
192             }
193 
194             if (getParameter(request, KRADConstants.LOOKUPABLE_IMPL_ATTRIBUTE_NAME) != null) {
195                 setLookupableImplServiceName(getParameter(request, KRADConstants.LOOKUPABLE_IMPL_ATTRIBUTE_NAME));
196             }
197 
198             // check the doc form key is empty before setting so we don't override a restored lookup form
199             if (request.getAttribute(KRADConstants.DOC_FORM_KEY) != null && StringUtils.isBlank(this.getFormKey())) {
200                 setFormKey((String) request.getAttribute(KRADConstants.DOC_FORM_KEY));
201             }
202             else if (getParameter(request, KRADConstants.DOC_FORM_KEY) != null && StringUtils.isBlank(this.getFormKey())) {
203                 setFormKey(getParameter(request, KRADConstants.DOC_FORM_KEY));
204             }
205             
206             if (getParameter(request, KRADConstants.DOC_NUM) != null) {
207                 setDocNum(getParameter(request, KRADConstants.DOC_NUM));
208            }
209 
210             String returnLocation = getParameter(request, "returnLocation");
211             if (StringUtils.isNotBlank(returnLocation)) {
212                 setBackLocation(returnLocation);
213                 localLookupable.getLookupableHelperService().setBackLocation(returnLocation);
214             }
215 
216             if (getParameter(request, "conversionFields") != null) {
217                 setConversionFields(getParameter(request, "conversionFields"));
218             }
219             if (getParameter(request, KRADConstants.EXTRA_BUTTON_SOURCE) != null) {
220             	//these are not sourced from the DD/Lookupable
221             	ddExtraButton=false;
222                 setExtraButtonSource(getParameter(request, KRADConstants.EXTRA_BUTTON_SOURCE));
223             }
224             if (getParameter(request, KRADConstants.EXTRA_BUTTON_PARAMS) != null) {
225                 setExtraButtonParams(getParameter(request, KRADConstants.EXTRA_BUTTON_PARAMS));
226             }
227             String value = getParameter(request, "multipleValues");
228             if (value != null) {
229                 if ("YES".equals(value.toUpperCase())) {
230                     setMultipleValues(true);
231                 }
232                 else {
233                     setMultipleValues(new Boolean(getParameter(request, "multipleValues")).booleanValue());
234                 }
235             }
236             if (getParameter(request, KRADConstants.REFERENCES_TO_REFRESH) != null) {
237                 setReferencesToRefresh(getParameter(request, KRADConstants.REFERENCES_TO_REFRESH));
238             }
239 
240             if (getParameter(request, "readOnlyFields") != null) {
241                 setReadOnlyFields(getParameter(request, "readOnlyFields"));
242                 setReadOnlyFieldsList(LookupUtils.translateReadOnlyFieldsToList(this.readOnlyFields));
243                 localLookupable.setReadOnlyFieldsList(getReadOnlyFieldsList());
244             }
245 
246 
247             /* Show/Hide All Criteria and/or the Workflow Header Bar
248              * The default value of each of the following parameters is 'true' in order to always show both the criteria and the header bar.
249              * To hide the header bar use the URL parameter 'headerBarEnabled' and set the value to 'false'.
250              * To hide all the search criteria (including the buttons) set the URL parameter 'searchCriteriaEnabled' to 'false'.
251              */
252             setHeaderBarEnabled(Truth.strToBooleanIgnoreCase(getParameter(request, HEADER_BAR_ENABLED_PARAM), Boolean.TRUE));
253             setLookupCriteriaEnabled(Truth.strToBooleanIgnoreCase(getParameter(request, SEARCH_CRITERIA_ENABLED_PARAM), Boolean.TRUE));
254 
255             // init lookupable with bo class
256             localLookupable.setBusinessObjectClass((Class<? extends BusinessObject>) Class.forName(getBusinessObjectClassName()));
257             Map<String, String> fieldValues = new HashMap<String, String>();
258             Map<String, String> formFields = getFields();
259             Class boClass = Class.forName(getBusinessObjectClassName());
260 
261             for (Iterator iter = localLookupable.getRows().iterator(); iter.hasNext();) {
262                 Row row = (Row) iter.next();
263 
264                 for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
265                     Field field = (Field) iterator.next();
266 
267                     // check whether form already has value for field
268                     if (formFields != null && formFields.containsKey(field.getPropertyName())) {
269                         field.setPropertyValue(formFields.get(field.getPropertyName()));
270                     }
271 
272                     // override values with request
273                     if (getParameter(request, field.getPropertyName()) != null) {
274                     	if(!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
275                     		field.setPropertyValue(getParameter(request, field.getPropertyName()).trim());
276                     	} else {
277                     		//multi value, set to values
278                     		field.setPropertyValues(getParameterValues(request, field.getPropertyName()));
279                     	}
280                     }
281 
282             		field.setPropertyValue(org.kuali.rice.krad.lookup.LookupUtils
283                             .forceUppercase(boClass, field.getPropertyName(), field.getPropertyValue()));
284                 	fieldValues.put(field.getPropertyName(), field.getPropertyValue());
285                 	//LOG.info("field name/value added was: " + field.getPropertyName() + field.getPropertyValue());
286                 	localLookupable.applyFieldAuthorizationsFromNestedLookups(field);
287                 }
288             }
289 
290             if (localLookupable.checkForAdditionalFields(fieldValues)) {
291                 for (Iterator iter = localLookupable.getRows().iterator(); iter.hasNext();) {
292                     Row row = (Row) iter.next();
293 
294                     for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
295                         Field field = (Field) iterator.next();
296 
297                         // check whether form already has value for field
298                         if (formFields != null && formFields.containsKey(field.getPropertyName())) {
299                             field.setPropertyValue(formFields.get(field.getPropertyName()));
300                         }
301 
302                         // override values with request
303                         if (getParameter(request, field.getPropertyName()) != null) {
304                         	if(!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
305                         		field.setPropertyValue(getParameter(request, field.getPropertyName()).trim());
306                         	} else {
307                         		//multi value, set to values
308                         		field.setPropertyValues(getParameterValues(request, field.getPropertyName()));
309                         	}
310                         }
311                         fieldValues.put(field.getPropertyName(), field.getPropertyValue());
312                     }
313                 }
314                
315             }
316             fieldValues.put(KRADConstants.DOC_FORM_KEY, this.getFormKey());
317             fieldValues.put(KRADConstants.BACK_LOCATION, this.getBackLocation());
318             if(this.getDocNum() != null){
319             	fieldValues.put(KRADConstants.DOC_NUM, this.getDocNum());
320             }
321             if (StringUtils.isNotBlank(getReferencesToRefresh())) {
322                 fieldValues.put(KRADConstants.REFERENCES_TO_REFRESH, this.getReferencesToRefresh());
323             }
324 
325             this.setFields(fieldValues);
326 
327             setFieldConversions(LookupUtils.translateFieldConversions(this.conversionFields));
328             localLookupable.setFieldConversions(getFieldConversions());
329             if(StringUtils.isNotEmpty(localLookupable.getExtraButtonSource())) {
330             	setExtraButtonSource(localLookupable.getExtraButtonSource());
331             	//also set the boolean so the jsp can use an action button
332             	ddExtraButton=true;
333             }
334             if(StringUtils.isNotEmpty(localLookupable.getExtraButtonParams())) {
335             	setExtraButtonParams(localLookupable.getExtraButtonParams());
336             }
337             setLookupable(localLookupable);
338             setFieldsForLookup(fieldValues);
339 
340             // if showMaintenanceLinks is not already true, only show maintenance links if the lookup was called from the portal (or index.html for the generated applications)
341             if (!isShowMaintenanceLinks()) {
342             	if (StringUtils.contains(getBackLocation(), "/"+ KRADConstants.PORTAL_ACTION)
343             			|| StringUtils.contains(getBackLocation(), "/index.html")) {
344             		showMaintenanceLinks = true;
345             	}
346             }
347         }
348         catch (ClassNotFoundException e) {
349             LOG.error("Business Object class " + getBusinessObjectClassName() + " not found");
350             throw new RuntimeException("Business Object class " + getBusinessObjectClassName() + " not found", e);
351         }
352     }
353 
354     /**
355      * @return Returns the lookupableImplServiceName.
356      */
357     public String getLookupableImplServiceName() {
358         return lookupableImplServiceName;
359     }
360 
361     protected Lookupable getLookupable(String beanName) {
362         return KNSServiceLocator.getLookupable(beanName);
363     }
364 
365     /**
366      * @param lookupableImplServiceName The lookupableImplServiceName to set.
367      */
368     public void setLookupableImplServiceName(String lookupableImplServiceName) {
369         this.lookupableImplServiceName = lookupableImplServiceName;
370     }
371 
372     /**
373      * @return Returns the formKey.
374      */
375     public String getFormKey() {
376         return formKey;
377     }
378 
379     /**
380      * @param formKey The formKey to set.
381      */
382     public void setFormKey(String formKey) {
383         this.formKey = formKey;
384     }
385 
386     /**
387      * @return Returns the fields.
388      */
389     public Map<String, String> getFields() {
390         return fields;
391     }
392 
393     /**
394      * @param fields The fields to set.
395      */
396     public void setFields(Map<String, String> fields) {
397         this.fields = fields;
398     }
399 
400     /**
401      * @return Returns the conversionFields.
402      */
403     public String getConversionFields() {
404         return conversionFields;
405     }
406 
407     /**
408      * @param conversionFields The conversionFields to set.
409      */
410     public void setConversionFields(String conversionFields) {
411         this.conversionFields = conversionFields;
412     }
413 
414     /**
415      * @return Returns the fieldConversions.
416      */
417     public Map<String, String> getFieldConversions() {
418         return fieldConversions;
419     }
420 
421     /**
422      * @param fieldConversions The fieldConversions to set.
423      */
424     public void setFieldConversions(Map<String, String> fieldConversions) {
425         this.fieldConversions = fieldConversions;
426     }
427 
428     /**
429      * @return Returns the businessObjectClassName.
430      */
431     public String getBusinessObjectClassName() {
432         return businessObjectClassName;
433     }
434 
435     /**
436      * @param businessObjectClassName The businessObjectClassName to set.
437      */
438     public void setBusinessObjectClassName(String businessObjectClassName) {
439         this.businessObjectClassName = businessObjectClassName;
440     }
441 
442 
443     /**
444      * @return Returns the kualiLookupable.
445      */
446     public Lookupable getLookupable() {
447         return lookupable;
448     }
449 
450 
451     /**
452      * @param lookupable The kualiLookupable to set.
453      */
454     public void setLookupable(Lookupable lookupable) {
455         this.lookupable = lookupable;
456     }
457 
458 
459     /**
460      * @return Returns the hideReturnLink.
461      */
462     public boolean isHideReturnLink() {
463         return hideReturnLink;
464     }
465 
466     /**
467      * @param suppressActions The suppressActions to set.
468      */
469     public void setSuppressActions(boolean suppressActions) {
470         this.suppressActions = suppressActions;
471     }
472 
473     /**
474      * @return Returns the suppressActions.
475      */
476     public boolean isSuppressActions() {
477         return suppressActions;
478     }
479 
480 
481     /**
482      * @param hideReturnLink The hideReturnLink to set.
483      */
484     public void setHideReturnLink(boolean hideReturnLink) {
485         this.hideReturnLink = hideReturnLink;
486     }
487 
488     // TODO: remove these once DD changes have been made
489     public String getExtraButtonParams() {
490         return extraButtons.get(0).getExtraButtonParams();
491     }
492 
493     // TODO: remove these once DD changes have been made
494     public void setExtraButtonParams(String extraButtonParams) {
495         extraButtons.get(0).setExtraButtonParams( extraButtonParams );
496     }
497 
498     // TODO: remove these once DD changes have been made
499     public String getExtraButtonSource() {
500         return extraButtons.get(0).getExtraButtonSource();
501     }
502 
503     // TODO: remove these once DD changes have been made
504     public void setExtraButtonSource(String extraButtonSource) {
505         extraButtons.get(0).setExtraButtonSource( extraButtonSource );
506     }
507 
508 
509     /**
510      *
511      * @return whether this form returns multiple values
512      */
513     public boolean isMultipleValues() {
514         return multipleValues;
515     }
516 
517     /**
518      *
519      * @param multipleValues - specify whether this form returns multiple values (i.e. a Collection)
520      */
521     public void setMultipleValues(boolean multipleValues) {
522         this.multipleValues = multipleValues;
523     }
524 
525     public String getLookupAnchor() {
526         return lookupAnchor;
527     }
528 
529     public void setLookupAnchor(String lookupAnchor) {
530         this.lookupAnchor = lookupAnchor;
531     }
532 
533     /**
534      * Gets the fieldsForLookup attribute.
535      * @return Returns the fieldsForLookup.
536      */
537     public Map getFieldsForLookup() {
538         return fieldsForLookup;
539     }
540 
541     /**
542      * Sets the fieldsForLookup attribute value.
543      * @param fieldsForLookup The fieldsForLookup to set.
544      */
545     public void setFieldsForLookup(Map fieldsForLookup) {
546         this.fieldsForLookup = fieldsForLookup;
547     }
548 
549     /**
550      * Gets the readOnlyFields attribute.
551      * @return Returns the readOnlyFields.
552      */
553     public String getReadOnlyFields() {
554         return readOnlyFields;
555     }
556 
557     /**
558      * Sets the readOnlyFields attribute value.
559      * @param readOnlyFields The readOnlyFields to set.
560      */
561     public void setReadOnlyFields(String readOnlyFields) {
562         this.readOnlyFields = readOnlyFields;
563     }
564 
565     /**
566      * Gets the readOnlyFieldsList attribute.
567      * @return Returns the readOnlyFieldsList.
568      */
569     public List getReadOnlyFieldsList() {
570         return readOnlyFieldsList;
571     }
572 
573     /**
574      * Sets the readOnlyFieldsList attribute value.
575      * @param readOnlyFieldsList The readOnlyFieldsList to set.
576      */
577     public void setReadOnlyFieldsList(List readOnlyFieldsList) {
578         this.readOnlyFieldsList = readOnlyFieldsList;
579     }
580 
581     public String getReferencesToRefresh() {
582         return referencesToRefresh;
583     }
584 
585     public void setReferencesToRefresh(String referencesToRefresh) {
586         this.referencesToRefresh = referencesToRefresh;
587     }
588 
589     public String getPrimaryKeyFieldLabels() {
590         return primaryKeyFieldLabels;
591     }
592 
593     public void setPrimaryKeyFieldLabels(String primaryKeyFieldLabels) {
594         this.primaryKeyFieldLabels = primaryKeyFieldLabels;
595     }
596 
597     public boolean isSearchUsingOnlyPrimaryKeyValues() {
598         return searchUsingOnlyPrimaryKeyValues;
599     }
600 
601     public void setSearchUsingOnlyPrimaryKeyValues(boolean searchUsingOnlyPrimaryKeyValues) {
602         this.searchUsingOnlyPrimaryKeyValues = searchUsingOnlyPrimaryKeyValues;
603     }
604 
605     /**
606      * Gets the showMaintenanceLinks attribute.
607      * @return Returns the showMaintenanceLinks.
608      */
609     public boolean isShowMaintenanceLinks() {
610         return showMaintenanceLinks;
611     }
612 
613     /**
614      * Sets the showMaintenanceLinks attribute value.
615      * @param showMaintenanceLinks The showMaintenanceLinks to set.
616      */
617     public void setShowMaintenanceLinks(boolean showMaintenanceLinks) {
618         this.showMaintenanceLinks = showMaintenanceLinks;
619     }
620 
621     /**
622      * Returns whether the results contain at least one row that is returnable
623      * 
624      * @return
625      */
626     public boolean isHasReturnableRow() {
627         return this.hasReturnableRow;
628     }
629 
630     /**
631      * Sets whether the results contain at least one row that is returnable
632      * 
633      * @param hasReturnableRow
634      */
635     public void setHasReturnableRow(boolean hasReturnableRow) {
636         this.hasReturnableRow = hasReturnableRow;
637     }
638 
639 	/**
640 	 * @return the lookupObjectId
641 	 */
642 	public String getLookupObjectId() {
643 		return this.lookupObjectId;
644 	}
645 
646 	/**
647 	 * @param lookupObjectId the lookupObjectId to set
648 	 */
649 	public void setLookupObjectId(String lookupObjectId) {
650 		this.lookupObjectId = lookupObjectId;
651 	}
652 
653 	/**
654 	 * @return the lookupCriteriaEnabled
655 	 */
656 	public boolean isLookupCriteriaEnabled() {
657 		return this.lookupCriteriaEnabled;
658 	}
659 
660 	/**
661 	 * @param lookupCriteriaEnabled the lookupCriteriaEnabled to set
662 	 */
663 	public void setLookupCriteriaEnabled(boolean lookupCriteriaEnabled) {
664 		this.lookupCriteriaEnabled = lookupCriteriaEnabled;
665 	}
666 
667 	/**
668 	 * @return the supplementalActionsEnabled
669 	 */
670 	public boolean isSupplementalActionsEnabled() {
671 		return this.supplementalActionsEnabled;
672 	}
673 
674 	/**
675 	 * @param supplementalActionsEnabled the supplementalActionsEnabled to set
676 	 */
677 	public void setSupplementalActionsEnabled(boolean supplementalActionsEnabled) {
678 		this.supplementalActionsEnabled = supplementalActionsEnabled;
679 	}
680 
681 
682 	/**
683 	 * @param actionUrlsExist the actionUrlsExist to set
684 	 */
685 	public void setActionUrlsExist(boolean actionUrlsExist) {
686 		this.actionUrlsExist = actionUrlsExist;
687 	}
688 
689 	/**
690 	 * @return the actionUrlsExist
691 	 */
692 	public boolean isActionUrlsExist() {
693 		return actionUrlsExist;
694 	}
695 
696 	/**
697 	 * @return the ddExtraButton
698 	 */
699 	public boolean isDdExtraButton() {
700 		return this.ddExtraButton;
701 	}
702 
703 	/**
704 	 * @param ddExtraButton the ddExtraButton to set
705 	 */
706 	public void setDdExtraButton(boolean ddExtraButton) {
707 		this.ddExtraButton = ddExtraButton;
708 	}
709 
710 	public boolean isHeaderBarEnabled() {
711 		return headerBarEnabled;
712 	}
713 
714 	public void setHeaderBarEnabled(boolean headerBarEnabled) {
715 		this.headerBarEnabled = headerBarEnabled;
716 	}	
717 
718 	public boolean isDisableSearchButtons() {
719 		return this.disableSearchButtons;
720 	}
721 
722 	public void setDisableSearchButtons(boolean disableSearchButtons) {
723 		this.disableSearchButtons = disableSearchButtons;
724 	}
725 	
726 	/**
727 	 * Determines whether the search/clear buttons should be rendering based on the form property
728 	 * and what is configured in the data dictionary for the lookup
729 	 * 
730 	 * @return boolean true if the buttons should be rendered, false if they should not be
731 	 */
732 	public boolean getRenderSearchButtons() {
733 		boolean renderSearchButtons = true;
734 
735 		if (disableSearchButtons
736 				|| KNSServiceLocator.getBusinessObjectDictionaryService().disableSearchButtonsInLookup(
737 						getLookupable().getBusinessObjectClass())) {
738 			renderSearchButtons = false;
739 		}
740 
741 		return renderSearchButtons;
742 	}
743 }