Coverage Report - org.kuali.rice.kns.lookup.AbstractLookupableHelperServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
AbstractLookupableHelperServiceImpl
0%
0/557
0%
0/290
2.778
 
 1  
 /*
 2  
  * Copyright 2006-2011 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  
 
 17  
 package org.kuali.rice.kns.lookup;
 18  
 
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.kuali.rice.core.api.config.property.ConfigurationService;
 21  
 import org.kuali.rice.core.api.encryption.EncryptionService;
 22  
 import org.kuali.rice.core.api.services.CoreApiServiceLocator;
 23  
 import org.kuali.rice.core.framework.parameter.ParameterService;
 24  
 import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
 25  
 import org.kuali.rice.core.util.RiceKeyConstants;
 26  
 import org.kuali.rice.core.util.cache.CopiedObject;
 27  
 import org.kuali.rice.core.util.type.TypeUtils;
 28  
 import org.kuali.rice.core.web.format.DateFormatter;
 29  
 import org.kuali.rice.core.web.format.Formatter;
 30  
 import org.kuali.rice.kim.bo.Person;
 31  
 import org.kuali.rice.kns.authorization.BusinessObjectRestrictions;
 32  
 import org.kuali.rice.kns.authorization.FieldRestriction;
 33  
 import org.kuali.rice.kns.bo.BusinessObject;
 34  
 import org.kuali.rice.kns.bo.PersistableBusinessObject;
 35  
 import org.kuali.rice.kns.datadictionary.AttributeSecurity;
 36  
 import org.kuali.rice.kns.datadictionary.mask.MaskFormatter;
 37  
 import org.kuali.rice.kns.exception.ValidationException;
 38  
 import org.kuali.rice.kns.inquiry.Inquirable;
 39  
 import org.kuali.rice.kns.lookup.HtmlData.AnchorHtmlData;
 40  
 import org.kuali.rice.kns.lookup.HtmlData.InputHtmlData;
 41  
 import org.kuali.rice.kns.service.BusinessObjectAuthorizationService;
 42  
 import org.kuali.rice.kns.service.BusinessObjectDictionaryService;
 43  
 import org.kuali.rice.kns.service.BusinessObjectMetaDataService;
 44  
 import org.kuali.rice.kns.service.BusinessObjectService;
 45  
 import org.kuali.rice.kns.service.DataDictionaryService;
 46  
 import org.kuali.rice.kns.service.KNSServiceLocator;
 47  
 import org.kuali.rice.kns.service.KNSServiceLocatorWeb;
 48  
 import org.kuali.rice.kns.service.LookupService;
 49  
 import org.kuali.rice.kns.service.MaintenanceDocumentDictionaryService;
 50  
 import org.kuali.rice.kns.service.PersistenceStructureService;
 51  
 import org.kuali.rice.kns.service.SequenceAccessorService;
 52  
 import org.kuali.rice.kns.util.FieldUtils;
 53  
 import org.kuali.rice.kns.util.GlobalVariables;
 54  
 import org.kuali.rice.kns.util.KNSConstants;
 55  
 import org.kuali.rice.kns.util.ObjectUtils;
 56  
 import org.kuali.rice.kns.util.UrlFactory;
 57  
 import org.kuali.rice.kns.web.comparator.CellComparatorHelper;
 58  
 import org.kuali.rice.kns.web.struts.form.LookupForm;
 59  
 import org.kuali.rice.kns.web.struts.form.MultipleValueLookupForm;
 60  
 import org.kuali.rice.kns.web.ui.Column;
 61  
 import org.kuali.rice.kns.web.ui.Field;
 62  
 import org.kuali.rice.kns.web.ui.ResultRow;
 63  
 import org.kuali.rice.kns.web.ui.Row;
 64  
 
 65  
 import java.security.GeneralSecurityException;
 66  
 import java.sql.Date;
 67  
 import java.util.ArrayList;
 68  
 import java.util.Collection;
 69  
 import java.util.HashMap;
 70  
 import java.util.HashSet;
 71  
 import java.util.Iterator;
 72  
 import java.util.List;
 73  
 import java.util.Map;
 74  
 import java.util.Properties;
 75  
 import java.util.Set;
 76  
 
 77  
 /**
 78  
  * This class declares many of the common spring injected properties, the get/set-ers for them,
 79  
  * and some common util methods that require the injected services
 80  
  */
 81  
 public abstract class AbstractLookupableHelperServiceImpl implements LookupableHelperService {
 82  
 
 83  
     protected static final String TITLE_RETURN_URL_PREPENDTEXT_PROPERTY = "title.return.url.value.prependtext";
 84  
     protected static final String TITLE_ACTION_URL_PREPENDTEXT_PROPERTY = "title.action.url.value.prependtext";
 85  
     protected static final String ACTION_URLS_CHILDREN_SEPARATOR = " | ";
 86  
     protected static final String ACTION_URLS_CHILDREN_STARTER = " [";
 87  
     protected static final String ACTION_URLS_CHILDREN_END = "]";
 88  
     protected static final String ACTION_URLS_SEPARATOR = "  ";
 89  
     protected static final String ACTION_URLS_EMPTY = " ";
 90  
 
 91  0
     protected static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AbstractLookupableHelperServiceImpl.class);
 92  
 
 93  
     protected Class businessObjectClass;
 94  
     protected Map parameters;
 95  
     protected BusinessObjectDictionaryService businessObjectDictionaryService;
 96  
     protected BusinessObjectMetaDataService businessObjectMetaDataService;
 97  
     protected DataDictionaryService dataDictionaryService;
 98  
     protected PersistenceStructureService persistenceStructureService;
 99  
     protected EncryptionService encryptionService;
 100  
     protected List<String> readOnlyFieldsList;
 101  
     protected String backLocation;
 102  
     protected String docFormKey;
 103  
     protected Map fieldConversions;
 104  
     protected LookupService lookupService;
 105  
     protected List<Row> rows;
 106  
     protected String referencesToRefresh;
 107  
     protected SequenceAccessorService sequenceAccessorService;
 108  
     protected BusinessObjectService businessObjectService;
 109  
     protected LookupResultsService lookupResultsService;
 110  
     protected String docNum;
 111  
     protected ConfigurationService configurationService;
 112  
     protected ParameterService parameterService;
 113  
     protected BusinessObjectAuthorizationService businessObjectAuthorizationService;
 114  
 
 115  
     /**
 116  
      * @return the docNum
 117  
      */
 118  
     public String getDocNum() {
 119  0
         return this.docNum;
 120  
     }
 121  
 
 122  
     /**
 123  
      * @param docNum the docNum to set
 124  
      */
 125  
     public void setDocNum(String docNum) {
 126  0
         this.docNum = docNum;
 127  0
     }
 128  
 
 129  0
     public AbstractLookupableHelperServiceImpl() {
 130  0
         rows = null;
 131  0
     }
 132  
 
 133  
     /**
 134  
      * This implementation always returns false.
 135  
      *
 136  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#checkForAdditionalFields(java.util.Map)
 137  
      */
 138  
     public boolean checkForAdditionalFields(Map fieldValues) {
 139  0
         return false;
 140  
     }
 141  
 
 142  
     /**
 143  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getBusinessObjectClass()
 144  
      */
 145  
     public Class getBusinessObjectClass() {
 146  0
         return businessObjectClass;
 147  
     }
 148  
 
 149  
     /**
 150  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#setBusinessObjectClass(java.lang.Class)
 151  
      */
 152  
     public void setBusinessObjectClass(Class businessObjectClass) {
 153  0
         this.businessObjectClass = businessObjectClass;
 154  0
         setRows();
 155  0
     }
 156  
 
 157  
     /**
 158  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getParameters()
 159  
      */
 160  
     public Map getParameters() {
 161  0
         return parameters;
 162  
     }
 163  
 
 164  
     /**
 165  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#setParameters(java.util.Map)
 166  
      */
 167  
     public void setParameters(Map parameters) {
 168  0
         this.parameters = parameters;
 169  0
     }
 170  
 
 171  
     /**
 172  
      * Gets the dataDictionaryService attribute.
 173  
      *
 174  
      * @return Returns the dataDictionaryService.
 175  
      */
 176  
     public DataDictionaryService getDataDictionaryService() {
 177  0
         return dataDictionaryService != null ? dataDictionaryService : KNSServiceLocatorWeb.getDataDictionaryService();
 178  
     }
 179  
 
 180  
     /**
 181  
      * Sets the dataDictionaryService attribute value.
 182  
      *
 183  
      * @param dataDictionaryService The dataDictionaryService to set.
 184  
      */
 185  
     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
 186  0
         this.dataDictionaryService = dataDictionaryService;
 187  0
     }
 188  
 
 189  
     /**
 190  
      * Gets the businessObjectDictionaryService attribute.
 191  
      *
 192  
      * @return Returns the businessObjectDictionaryService.
 193  
      */
 194  
     public BusinessObjectDictionaryService getBusinessObjectDictionaryService() {
 195  0
         return businessObjectDictionaryService != null ? businessObjectDictionaryService : KNSServiceLocatorWeb.getBusinessObjectDictionaryService();
 196  
     }
 197  
 
 198  
     /**
 199  
      * Sets the businessObjectDictionaryService attribute value.
 200  
      *
 201  
      * @param businessObjectDictionaryService
 202  
      *         The businessObjectDictionaryService to set.
 203  
      */
 204  
     public void setBusinessObjectDictionaryService(BusinessObjectDictionaryService businessObjectDictionaryService) {
 205  0
         this.businessObjectDictionaryService = businessObjectDictionaryService;
 206  0
     }
 207  
 
 208  
     /**
 209  
      * Gets the businessObjectMetaDataService attribute.
 210  
      *
 211  
      * @return Returns the businessObjectMetaDataService.
 212  
      */
 213  
     public BusinessObjectMetaDataService getBusinessObjectMetaDataService() {
 214  0
         return businessObjectMetaDataService != null ? businessObjectMetaDataService : KNSServiceLocatorWeb.getBusinessObjectMetaDataService();
 215  
     }
 216  
 
 217  
     /**
 218  
      * Sets the businessObjectMetaDataService attribute value.
 219  
      *
 220  
      * @param businessObjectMetaDataService The businessObjectMetaDataService to set.
 221  
      */
 222  
     public void setBusinessObjectMetaDataService(BusinessObjectMetaDataService businessObjectMetaDataService) {
 223  0
         this.businessObjectMetaDataService = businessObjectMetaDataService;
 224  0
     }
 225  
 
 226  
     /**
 227  
      * Gets the persistenceStructureService attribute.
 228  
      *
 229  
      * @return Returns the persistenceStructureService.
 230  
      */
 231  
     protected PersistenceStructureService getPersistenceStructureService() {
 232  0
         return persistenceStructureService != null ? persistenceStructureService : KNSServiceLocator.getPersistenceStructureService();
 233  
     }
 234  
 
 235  
     /**
 236  
      * Sets the persistenceStructureService attribute value.
 237  
      *
 238  
      * @param persistenceStructureService The persistenceStructureService to set.
 239  
      */
 240  
     public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
 241  0
         this.persistenceStructureService = persistenceStructureService;
 242  0
     }
 243  
 
 244  
     /**
 245  
      * Gets the encryptionService attribute.
 246  
      *
 247  
      * @return Returns the encryptionService.
 248  
      */
 249  
     protected EncryptionService getEncryptionService() {
 250  0
         return encryptionService != null ? encryptionService : CoreApiServiceLocator.getEncryptionService();
 251  
     }
 252  
 
 253  
     /**
 254  
      * Sets the encryptionService attribute value.
 255  
      *
 256  
      * @param encryptionService The encryptionService to set.
 257  
      */
 258  
     public void setEncryptionService(EncryptionService encryptionService) {
 259  0
         this.encryptionService = encryptionService;
 260  0
     }
 261  
 
 262  
     protected MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService;
 263  
 
 264  
     public MaintenanceDocumentDictionaryService getMaintenanceDocumentDictionaryService() {
 265  0
         if (maintenanceDocumentDictionaryService == null) {
 266  0
             maintenanceDocumentDictionaryService = KNSServiceLocatorWeb.getMaintenanceDocumentDictionaryService();
 267  
         }
 268  0
         return maintenanceDocumentDictionaryService;
 269  
     }
 270  
 
 271  
 
 272  
     public BusinessObjectAuthorizationService getBusinessObjectAuthorizationService() {
 273  0
         if (businessObjectAuthorizationService == null) {
 274  0
             businessObjectAuthorizationService = KNSServiceLocatorWeb.getBusinessObjectAuthorizationService();
 275  
         }
 276  0
         return businessObjectAuthorizationService;
 277  
     }
 278  
 
 279  
     protected Inquirable kualiInquirable;
 280  
 
 281  
     public Inquirable getKualiInquirable() {
 282  0
         if (kualiInquirable == null) {
 283  0
             kualiInquirable = KNSServiceLocatorWeb.getKualiInquirable();
 284  
         }
 285  0
         return kualiInquirable;
 286  
     }
 287  
 
 288  
     public void setMaintenanceDocumentDictionaryService(MaintenanceDocumentDictionaryService maintenanceDocumentDictionaryService) {
 289  0
         this.maintenanceDocumentDictionaryService = maintenanceDocumentDictionaryService;
 290  0
     }
 291  
 
 292  
     public void setKualiInquirable(Inquirable kualiInquirable) {
 293  0
         this.kualiInquirable = kualiInquirable;
 294  0
     }
 295  
 
 296  
 
 297  
     public ConfigurationService getKualiConfigurationService() {
 298  0
         if (configurationService == null) {
 299  0
             configurationService = KNSServiceLocator.getKualiConfigurationService();
 300  
         }
 301  0
         return configurationService;
 302  
     }
 303  
 
 304  
     public void setParameterService(ConfigurationService configurationService) {
 305  0
         this.configurationService = configurationService;
 306  0
     }
 307  
 
 308  
 
 309  
     public ParameterService getParameterService() {
 310  0
         if (parameterService == null) {
 311  0
             parameterService = CoreFrameworkServiceLocator.getParameterService();
 312  
         }
 313  0
         return parameterService;
 314  
     }
 315  
 
 316  
     public void setParameterService(ParameterService parameterService) {
 317  0
         this.parameterService = parameterService;
 318  0
     }
 319  
 
 320  
     /**
 321  
      * Determines if underlying lookup bo has associated maintenance document that allows new or copy maintenance actions.
 322  
      *
 323  
      * @return true if bo has maint doc that allows new or copy actions
 324  
      */
 325  
     public boolean allowsMaintenanceNewOrCopyAction() {
 326  0
         boolean allowsNewOrCopy = false;
 327  
 
 328  0
         String maintDocTypeName = getMaintenanceDocumentTypeName();
 329  0
         Class boClass = this.getBusinessObjectClass();
 330  
 
 331  0
         if (StringUtils.isNotBlank(maintDocTypeName)) {
 332  0
             allowsNewOrCopy = getBusinessObjectAuthorizationService().canCreate(boClass, GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
 333  
         }
 334  0
         return allowsNewOrCopy;
 335  
     }
 336  
 
 337  
     protected boolean allowsMaintenanceEditAction(BusinessObject businessObject) {
 338  0
         boolean allowsEdit = false;
 339  
 
 340  0
         String maintDocTypeName = getMaintenanceDocumentTypeName();
 341  
 
 342  0
         if (StringUtils.isNotBlank(maintDocTypeName)) {
 343  0
             allowsEdit = getBusinessObjectAuthorizationService().canMaintain(businessObject, GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
 344  
         }
 345  0
         return allowsEdit;
 346  
     }
 347  
 
 348  
 
 349  
     /**
 350  
      * Build a maintenance url.
 351  
      *
 352  
      * @param bo           - business object representing the record for maint.
 353  
      * @param methodToCall - maintenance action
 354  
      * @return
 355  
      */
 356  
     final public String getMaintenanceUrl(BusinessObject businessObject, HtmlData htmlData, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) {
 357  0
         htmlData.setTitle(getActionUrlTitleText(businessObject, htmlData.getDisplayText(), pkNames, businessObjectRestrictions));
 358  0
         return htmlData.constructCompleteHtmlTag();
 359  
     }
 360  
 
 361  
     /**
 362  
      * This method is called by performLookup method to generate action urls.
 363  
      * It calls the method getCustomActionUrls to get html data, calls getMaintenanceUrl to get the actual html tag,
 364  
      * and returns a formatted/concatenated string of action urls.
 365  
      *
 366  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getActionUrls(org.kuali.rice.kns.bo.BusinessObject)
 367  
      */
 368  
     final public String getActionUrls(BusinessObject businessObject, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) {
 369  0
         StringBuffer actions = new StringBuffer();
 370  0
         List<HtmlData> htmlDataList = getCustomActionUrls(businessObject, pkNames);
 371  0
         for (HtmlData htmlData : htmlDataList) {
 372  0
             actions.append(getMaintenanceUrl(businessObject, htmlData, pkNames, businessObjectRestrictions));
 373  0
             if (htmlData.getChildUrlDataList() != null) {
 374  0
                 if (htmlData.getChildUrlDataList().size() > 0) {
 375  0
                     actions.append(ACTION_URLS_CHILDREN_STARTER);
 376  0
                     for (HtmlData childURLData : htmlData.getChildUrlDataList()) {
 377  0
                         actions.append(getMaintenanceUrl(businessObject, childURLData, pkNames, businessObjectRestrictions));
 378  0
                         actions.append(ACTION_URLS_CHILDREN_SEPARATOR);
 379  
                     }
 380  0
                     if (actions.toString().endsWith(ACTION_URLS_CHILDREN_SEPARATOR))
 381  0
                         actions.delete(actions.length() - ACTION_URLS_CHILDREN_SEPARATOR.length(), actions.length());
 382  0
                     actions.append(ACTION_URLS_CHILDREN_END);
 383  
                 }
 384  
             }
 385  0
             actions.append(ACTION_URLS_SEPARATOR);
 386  
         }
 387  0
         if (actions.toString().endsWith(ACTION_URLS_SEPARATOR))
 388  0
             actions.delete(actions.length() - ACTION_URLS_SEPARATOR.length(), actions.length());
 389  0
         return actions.toString();
 390  
     }
 391  
 
 392  
     /**
 393  
      * Child classes should override this method if they want to return some other action urls.
 394  
      *
 395  
      * @returns This default implementation returns links to edit and copy maintenance action for
 396  
      * the current maintenance record if the business object class has an associated maintenance document.
 397  
      * Also checks value of allowsNewOrCopy in maintenance document xml before rendering the copy link.
 398  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getCustomActionUrls(org.kuali.rice.kns.bo.BusinessObject, java.util.List, java.util.List pkNames)
 399  
      */
 400  
     public List<HtmlData> getCustomActionUrls(BusinessObject businessObject, List pkNames) {
 401  0
         List<HtmlData> htmlDataList = new ArrayList<HtmlData>();
 402  0
         if (allowsMaintenanceEditAction(businessObject)) {
 403  0
             htmlDataList.add(getUrlData(businessObject, KNSConstants.MAINTENANCE_EDIT_METHOD_TO_CALL, pkNames));
 404  
         }
 405  0
         if (allowsMaintenanceNewOrCopyAction()) {
 406  0
             htmlDataList.add(getUrlData(businessObject, KNSConstants.MAINTENANCE_COPY_METHOD_TO_CALL, pkNames));
 407  
         }
 408  0
         if (allowsMaintenanceDeleteAction(businessObject)) {
 409  0
             htmlDataList.add(getUrlData(businessObject, KNSConstants.MAINTENANCE_DELETE_METHOD_TO_CALL, pkNames));
 410  
         }
 411  0
         return htmlDataList;
 412  
     }
 413  
 
 414  
     /**
 415  
      * This method ...
 416  
      * for KULRice 3070
 417  
      *
 418  
      * @return
 419  
      */
 420  
     protected boolean allowsMaintenanceDeleteAction(BusinessObject businessObject) {
 421  
 
 422  0
         boolean allowsMaintain = false;
 423  0
         boolean allowsDelete = false;
 424  
 
 425  0
         String maintDocTypeName = getMaintenanceDocumentTypeName();
 426  
 
 427  0
         if (StringUtils.isNotBlank(maintDocTypeName)) {
 428  0
             allowsMaintain = getBusinessObjectAuthorizationService().canMaintain(businessObject, GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
 429  
         }
 430  
 
 431  0
         allowsDelete = KNSServiceLocatorWeb.getMaintenanceDocumentDictionaryService().getAllowsRecordDeletion(businessObjectClass);
 432  
 
 433  0
         return allowsDelete && allowsMaintain;
 434  
     }
 435  
 
 436  
     /**
 437  
      * This method constructs an AnchorHtmlData.
 438  
      * This method can be overriden by child classes if they want to construct the html data in a different way.
 439  
      * Foe example, if they want different type of html tag, like input/image.
 440  
      *
 441  
      * @param businessObject
 442  
      * @param methodToCall
 443  
      * @param displayText
 444  
      * @param pkNames
 445  
      * @return
 446  
      */
 447  
     protected AnchorHtmlData getUrlData(BusinessObject businessObject, String methodToCall, String displayText, List pkNames) {
 448  
 
 449  0
         String href = getActionUrlHref(businessObject, methodToCall, pkNames);
 450  
         //String title = StringUtils.isBlank(href)?"":getActionUrlTitleText(businessObject, displayText, pkNames);
 451  0
         AnchorHtmlData anchorHtmlData = new AnchorHtmlData(href, methodToCall, displayText);
 452  0
         return anchorHtmlData;
 453  
     }
 454  
 
 455  
     /**
 456  
      * This method calls its overloaded method with displayText as methodToCall
 457  
      *
 458  
      * @param businessObject
 459  
      * @param methodToCall
 460  
      * @param pkNames
 461  
      * @return
 462  
      */
 463  
     protected AnchorHtmlData getUrlData(BusinessObject businessObject, String methodToCall, List pkNames) {
 464  0
         return getUrlData(businessObject, methodToCall, methodToCall, pkNames);
 465  
     }
 466  
 
 467  
     /**
 468  
      * A utility method that returns an empty list of action urls.
 469  
      *
 470  
      * @return
 471  
      */
 472  
     protected List<HtmlData> getEmptyActionUrls() {
 473  0
         return new ArrayList<HtmlData>();
 474  
     }
 475  
 
 476  
     protected HtmlData getEmptyAnchorHtmlData() {
 477  0
         return new AnchorHtmlData();
 478  
     }
 479  
 
 480  
     /**
 481  
      * This method generates and returns href for the given parameters.
 482  
      * This method can be overridden by child classes if they have to generate href differently.
 483  
      * For example, refer to IntendedIncumbentLookupableHelperServiceImpl
 484  
      *
 485  
      * @param businessObject
 486  
      * @param methodToCall
 487  
      * @param pkNames
 488  
      * @return
 489  
      */
 490  
     protected String getActionUrlHref(BusinessObject businessObject, String methodToCall, List pkNames) {
 491  0
         Properties parameters = new Properties();
 492  0
         parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, methodToCall);
 493  
         // TODO: why is this not using the businessObject parmeter's class?
 494  0
         parameters.put(KNSConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, businessObject.getClass().getName());
 495  0
         parameters.putAll(getParametersFromPrimaryKey(businessObject, pkNames));
 496  0
         if (StringUtils.isNotBlank(getReturnLocation())) {
 497  0
             parameters.put(KNSConstants.RETURN_LOCATION_PARAMETER, getReturnLocation());
 498  
         }
 499  0
         return UrlFactory.parameterizeUrl(KNSConstants.MAINTENANCE_ACTION, parameters);
 500  
     }
 501  
 
 502  
     protected Properties getParametersFromPrimaryKey(BusinessObject businessObject, List pkNames) {
 503  0
         Properties parameters = new Properties();
 504  0
         for (Iterator iter = pkNames.iterator(); iter.hasNext();) {
 505  0
             String fieldNm = (String) iter.next();
 506  
 
 507  0
             Object fieldVal = ObjectUtils.getPropertyValue(businessObject, fieldNm);
 508  0
             if (fieldVal == null) {
 509  0
                 fieldVal = KNSConstants.EMPTY_STRING;
 510  
             }
 511  0
             if (fieldVal instanceof java.sql.Date) {
 512  0
                 String formattedString = "";
 513  0
                 if (Formatter.findFormatter(fieldVal.getClass()) != null) {
 514  0
                     Formatter formatter = Formatter.getFormatter(fieldVal.getClass());
 515  0
                     formattedString = (String) formatter.format(fieldVal);
 516  0
                     fieldVal = formattedString;
 517  
                 }
 518  
             }
 519  
 
 520  
             // Encrypt value if it is a secure field
 521  0
             if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, fieldNm)) {
 522  
                 try {
 523  0
                     fieldVal = getEncryptionService().encrypt(fieldVal) + EncryptionService.ENCRYPTION_POST_PREFIX;
 524  0
                 } catch (GeneralSecurityException e) {
 525  0
                     LOG.error("Exception while trying to encrypted value for inquiry framework.", e);
 526  0
                     throw new RuntimeException(e);
 527  0
                 }
 528  
 
 529  
             }
 530  
 
 531  0
             parameters.put(fieldNm, fieldVal.toString());
 532  0
         }
 533  0
         return parameters;
 534  
     }
 535  
 
 536  
     /**
 537  
      * This method generates and returns title text for action urls.
 538  
      * Child classes can override this if they want to generate the title text differently.
 539  
      * For example, refer to BatchJobStatusLookupableHelperServiceImpl
 540  
      *
 541  
      * @param businessObject
 542  
      * @param displayText
 543  
      * @param pkNames
 544  
      * @return
 545  
      */
 546  
     protected String getActionUrlTitleText(BusinessObject businessObject, String displayText, List pkNames, BusinessObjectRestrictions businessObjectRestrictions) {
 547  0
         String prependTitleText = displayText + " "
 548  
                 + getDataDictionaryService().getDataDictionary().getBusinessObjectEntry(getBusinessObjectClass().getName()).getObjectLabel()
 549  
                 + " "
 550  
                 + this.getKualiConfigurationService().getPropertyString(TITLE_ACTION_URL_PREPENDTEXT_PROPERTY);
 551  0
         return HtmlData.getTitleText(prependTitleText, businessObject, pkNames, businessObjectRestrictions);
 552  
     }
 553  
 
 554  
     /**
 555  
      * Returns the maintenance document type associated with the business object class or null if one does not
 556  
      * exist.
 557  
      *
 558  
      * @return String representing the maintenance document type name
 559  
      */
 560  
     protected String getMaintenanceDocumentTypeName() {
 561  0
         MaintenanceDocumentDictionaryService dd = getMaintenanceDocumentDictionaryService();
 562  0
         String maintDocTypeName = dd.getDocumentTypeName(getBusinessObjectClass());
 563  0
         return maintDocTypeName;
 564  
     }
 565  
 
 566  
     /**
 567  
      * Gets the readOnlyFieldsList attribute.
 568  
      *
 569  
      * @return Returns the readOnlyFieldsList.
 570  
      */
 571  
     public List<String> getReadOnlyFieldsList() {
 572  0
         return readOnlyFieldsList;
 573  
     }
 574  
 
 575  
 
 576  
     /**
 577  
      * Sets the readOnlyFieldsList attribute value.
 578  
      *
 579  
      * @param readOnlyFieldsList The readOnlyFieldsList to set.
 580  
      */
 581  
     public void setReadOnlyFieldsList(List<String> readOnlyFieldsList) {
 582  0
         this.readOnlyFieldsList = readOnlyFieldsList;
 583  0
     }
 584  
 
 585  0
     protected HashMap<String, Boolean> noLookupResultFieldInquiryCache = new HashMap<String, Boolean>();
 586  0
     protected HashMap<Class, Class> inquirableClassCache = new HashMap<Class, Class>();
 587  0
     protected HashMap<String, Boolean> forceLookupResultFieldInquiryCache = new HashMap<String, Boolean>();
 588  
 
 589  
     /**
 590  
      * Returns the inquiry url for a field if one exist.
 591  
      *
 592  
      * @param bo           the business object instance to build the urls for
 593  
      * @param propertyName the property which links to an inquirable
 594  
      * @return String url to inquiry
 595  
      */
 596  
     public HtmlData getInquiryUrl(BusinessObject bo, String propertyName) {
 597  0
         HtmlData inquiryUrl = new AnchorHtmlData();
 598  
 
 599  0
         String cacheKey = bo.getClass().getName() + "." + propertyName;
 600  0
         Boolean noLookupResultFieldInquiry = noLookupResultFieldInquiryCache.get(cacheKey);
 601  0
         if (noLookupResultFieldInquiry == null) {
 602  0
             noLookupResultFieldInquiry = getBusinessObjectDictionaryService().noLookupResultFieldInquiry(bo.getClass(), propertyName);
 603  0
             if (noLookupResultFieldInquiry == null) {
 604  0
                 noLookupResultFieldInquiry = Boolean.TRUE;
 605  
             }
 606  0
             noLookupResultFieldInquiryCache.put(cacheKey, noLookupResultFieldInquiry);
 607  
         }
 608  0
         if (!noLookupResultFieldInquiry) {
 609  
 
 610  0
             Class<Inquirable> inquirableClass = inquirableClassCache.get(bo.getClass());
 611  0
             if (!inquirableClassCache.containsKey(bo.getClass())) {
 612  0
                 inquirableClass = getBusinessObjectDictionaryService().getInquirableClass(bo.getClass());
 613  0
                 inquirableClassCache.put(bo.getClass(), inquirableClass);
 614  
             }
 615  0
             Inquirable inq = null;
 616  
             try {
 617  0
                 if (inquirableClass != null) {
 618  0
                     inq = inquirableClass.newInstance();
 619  
                 } else {
 620  0
                     inq = getKualiInquirable();
 621  0
                     if (LOG.isDebugEnabled()) {
 622  0
                         LOG.debug("Default Inquirable Class: " + inq.getClass());
 623  
                     }
 624  
                 }
 625  0
                 Boolean forceLookupResultFieldInquiry = forceLookupResultFieldInquiryCache.get(cacheKey);
 626  0
                 if (forceLookupResultFieldInquiry == null) {
 627  0
                     forceLookupResultFieldInquiry = getBusinessObjectDictionaryService().forceLookupResultFieldInquiry(bo.getClass(), propertyName);
 628  0
                     if (forceLookupResultFieldInquiry == null) {
 629  0
                         forceLookupResultFieldInquiry = Boolean.FALSE;
 630  
                     }
 631  0
                     forceLookupResultFieldInquiryCache.put(cacheKey, forceLookupResultFieldInquiry);
 632  
                 }
 633  0
                 inquiryUrl = inq.getInquiryUrl(bo, propertyName, forceLookupResultFieldInquiry);
 634  0
             } catch (Exception ex) {
 635  0
                 LOG.error("unable to create inquirable to get inquiry URL", ex);
 636  0
             }
 637  
         }
 638  
 
 639  0
         return inquiryUrl;
 640  
     }
 641  
 
 642  0
     protected CopiedObject<ArrayList<Column>> resultColumns = null;
 643  
 
 644  
     /**
 645  
      * Constructs the list of columns for the search results. All properties for the column objects come from the DataDictionary.
 646  
      */
 647  
     public List<Column> getColumns() {
 648  0
         if (resultColumns == null) {
 649  0
             ArrayList<Column> columns = new ArrayList<Column>();
 650  0
             for (String attributeName : getBusinessObjectDictionaryService().getLookupResultFieldNames(getBusinessObjectClass())) {
 651  0
                 Column column = new Column();
 652  0
                 column.setPropertyName(attributeName);
 653  0
                 String columnTitle = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), attributeName);
 654  0
                 Boolean useShortLabel = getBusinessObjectDictionaryService().getLookupResultFieldUseShortLabel(businessObjectClass, attributeName);
 655  0
                 if (useShortLabel != null && useShortLabel) {
 656  0
                     columnTitle = getDataDictionaryService().getAttributeShortLabel(getBusinessObjectClass(), attributeName);
 657  
                 }
 658  0
                 if (StringUtils.isBlank(columnTitle)) {
 659  0
                     columnTitle = getDataDictionaryService().getCollectionLabel(getBusinessObjectClass(), attributeName);
 660  
                 }
 661  0
                 column.setColumnTitle(columnTitle);
 662  0
                 column.setMaxLength(getColumnMaxLength(attributeName));
 663  
 
 664  0
                 if (!businessObjectClass.isInterface()) {
 665  
                     try {
 666  0
                         column.setFormatter(ObjectUtils.getFormatterWithDataDictionary(getBusinessObjectClass()
 667  
                                 .newInstance(), attributeName));
 668  0
                     } catch (InstantiationException e) {
 669  0
                         LOG.info("Unable to get new instance of business object class: " + businessObjectClass.getName(), e);
 670  
                         // just swallow exception and leave formatter blank
 671  0
                     } catch (IllegalAccessException e) {
 672  0
                         LOG.info("Unable to get new instance of business object class: " + businessObjectClass.getName(), e);
 673  
                         // just swallow exception and leave formatter blank
 674  0
                     }
 675  
                 }
 676  
 
 677  0
                 String alternateDisplayPropertyName = getBusinessObjectDictionaryService()
 678  
                         .getLookupFieldAlternateDisplayAttributeName(getBusinessObjectClass(), attributeName);
 679  0
                 if (StringUtils.isNotBlank(alternateDisplayPropertyName)) {
 680  0
                     column.setAlternateDisplayPropertyName(alternateDisplayPropertyName);
 681  
                 }
 682  
 
 683  0
                 String additionalDisplayPropertyName = getBusinessObjectDictionaryService()
 684  
                         .getLookupFieldAdditionalDisplayAttributeName(getBusinessObjectClass(), attributeName);
 685  0
                 if (StringUtils.isNotBlank(additionalDisplayPropertyName)) {
 686  0
                     column.setAdditionalDisplayPropertyName(additionalDisplayPropertyName);
 687  
                 } else {
 688  0
                     boolean translateCodes = getBusinessObjectDictionaryService().tranlateCodesInLookup(getBusinessObjectClass());
 689  0
                     if (translateCodes) {
 690  0
                         FieldUtils.setAdditionalDisplayPropertyForCodes(getBusinessObjectClass(), attributeName, column);
 691  
                     }
 692  
                 }
 693  
 
 694  0
                 column.setTotal(getBusinessObjectDictionaryService().getLookupResultFieldTotal(getBusinessObjectClass(), attributeName));
 695  
 
 696  0
                 columns.add(column);
 697  0
             }
 698  0
             resultColumns = ObjectUtils.deepCopyForCaching(columns);
 699  0
             return columns;
 700  
         }
 701  0
         return resultColumns.getContent();
 702  
     }
 703  
 
 704  0
     protected static Integer RESULTS_DEFAULT_MAX_COLUMN_LENGTH = null;
 705  
 
 706  
     protected int getColumnMaxLength(String attributeName) {
 707  0
         Integer fieldDefinedMaxLength = getBusinessObjectDictionaryService().getLookupResultFieldMaxLength(getBusinessObjectClass(), attributeName);
 708  0
         if (fieldDefinedMaxLength == null) {
 709  0
             if (RESULTS_DEFAULT_MAX_COLUMN_LENGTH == null) {
 710  
                 try {
 711  0
                     RESULTS_DEFAULT_MAX_COLUMN_LENGTH = Integer.valueOf(getParameterService().getParameterValueAsString(KNSConstants.KNS_NAMESPACE, KNSConstants.DetailTypes.LOOKUP_PARM_DETAIL_TYPE, KNSConstants.RESULTS_DEFAULT_MAX_COLUMN_LENGTH));
 712  0
                 } catch (NumberFormatException ex) {
 713  0
                     LOG.error("Lookup field max length parameter not found and unable to parse default set in system parameters (RESULTS_DEFAULT_MAX_COLUMN_LENGTH).");
 714  0
                 }
 715  
             }
 716  0
             return RESULTS_DEFAULT_MAX_COLUMN_LENGTH.intValue();
 717  
         }
 718  0
         return fieldDefinedMaxLength.intValue();
 719  
     }
 720  
 
 721  
     /**
 722  
      * @return Returns the backLocation.
 723  
      */
 724  
     public String getBackLocation() {
 725  0
         return backLocation;
 726  
     }
 727  
 
 728  
     /**
 729  
      * @param backLocation The backLocation to set.
 730  
      */
 731  
     public void setBackLocation(String backLocation) {
 732  0
         this.backLocation = backLocation;
 733  0
     }
 734  
 
 735  
     /**
 736  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getReturnLocation()
 737  
      */
 738  
     public String getReturnLocation() {
 739  0
         return backLocation;
 740  
     }
 741  
 
 742  
     /**
 743  
      * This method is for lookupable implementations
 744  
      *
 745  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getReturnUrl(org.kuali.rice.kns.bo.BusinessObject, java.util.Map, java.lang.String, java.util.List)
 746  
      */
 747  
     final public HtmlData getReturnUrl(BusinessObject businessObject, Map fieldConversions, String lookupImpl, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
 748  0
         String href = getReturnHref(businessObject, fieldConversions, lookupImpl, returnKeys);
 749  0
         String returnUrlAnchorLabel =
 750  
                 this.getKualiConfigurationService().getPropertyString(TITLE_RETURN_URL_PREPENDTEXT_PROPERTY);
 751  0
         AnchorHtmlData anchor = new AnchorHtmlData(href, HtmlData.getTitleText(returnUrlAnchorLabel, businessObject, returnKeys, businessObjectRestrictions));
 752  0
         anchor.setDisplayText(returnUrlAnchorLabel);
 753  0
         return anchor;
 754  
     }
 755  
 
 756  
     /**
 757  
      * This method is for lookupable implementations
 758  
      *
 759  
      * @param businessObject
 760  
      * @param fieldConversions
 761  
      * @param lookupImpl
 762  
      * @param returnKeys
 763  
      * @return
 764  
      */
 765  
     final protected String getReturnHref(BusinessObject businessObject, Map fieldConversions, String lookupImpl, List returnKeys) {
 766  0
         if (StringUtils.isNotBlank(backLocation)) {
 767  0
             return UrlFactory.parameterizeUrl(backLocation, getParameters(
 768  
                     businessObject, fieldConversions, lookupImpl, returnKeys));
 769  
         }
 770  0
         return "";
 771  
     }
 772  
 
 773  
     /**
 774  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getReturnUrl(org.kuali.core.bo.BusinessObject, java.util.Map, java.lang.String)
 775  
      */
 776  
     public HtmlData getReturnUrl(BusinessObject businessObject, LookupForm lookupForm, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
 777  0
         Properties parameters = getParameters(
 778  
                 businessObject, lookupForm.getFieldConversions(), lookupForm.getLookupableImplServiceName(), returnKeys);
 779  0
         if (StringUtils.isEmpty(lookupForm.getHtmlDataType()) || HtmlData.ANCHOR_HTML_DATA_TYPE.equals(lookupForm.getHtmlDataType()))
 780  0
             return getReturnAnchorHtmlData(businessObject, parameters, lookupForm, returnKeys, businessObjectRestrictions);
 781  
         else
 782  0
             return getReturnInputHtmlData(businessObject, parameters, lookupForm, returnKeys, businessObjectRestrictions);
 783  
     }
 784  
 
 785  
     protected HtmlData getReturnInputHtmlData(BusinessObject businessObject, Properties parameters, LookupForm lookupForm, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
 786  0
         String returnUrlAnchorLabel =
 787  
                 this.getKualiConfigurationService().getPropertyString(TITLE_RETURN_URL_PREPENDTEXT_PROPERTY);
 788  0
         String name = KNSConstants.MULTIPLE_VALUE_LOOKUP_SELECTED_OBJ_ID_PARAM_PREFIX + lookupForm.getLookupObjectId();
 789  0
         InputHtmlData input = new InputHtmlData(name, InputHtmlData.CHECKBOX_INPUT_TYPE);
 790  0
         input.setTitle(HtmlData.getTitleText(returnUrlAnchorLabel, businessObject, returnKeys, businessObjectRestrictions));
 791  0
         if (((MultipleValueLookupForm) lookupForm).getCompositeObjectIdMap() == null ||
 792  
                 ((MultipleValueLookupForm) lookupForm).getCompositeObjectIdMap().get(
 793  
                         ((PersistableBusinessObject) businessObject).getObjectId()) == null) {
 794  0
             input.setChecked("");
 795  
         } else {
 796  0
             input.setChecked(InputHtmlData.CHECKBOX_CHECKED_VALUE);
 797  
         }
 798  0
         input.setValue(InputHtmlData.CHECKBOX_CHECKED_VALUE);
 799  0
         return input;
 800  
     }
 801  
 
 802  
     protected HtmlData getReturnAnchorHtmlData(BusinessObject businessObject, Properties parameters, LookupForm lookupForm, List returnKeys, BusinessObjectRestrictions businessObjectRestrictions) {
 803  0
         String returnUrlAnchorLabel =
 804  
                 this.getKualiConfigurationService().getPropertyString(TITLE_RETURN_URL_PREPENDTEXT_PROPERTY);
 805  0
         AnchorHtmlData anchor = new AnchorHtmlData(
 806  
                 getReturnHref(parameters, lookupForm, returnKeys),
 807  
                 HtmlData.getTitleText(returnUrlAnchorLabel, businessObject, returnKeys, businessObjectRestrictions));
 808  0
         anchor.setDisplayText(returnUrlAnchorLabel);
 809  0
         return anchor;
 810  
     }
 811  
 
 812  
     protected String getReturnHref(Properties parameters, LookupForm lookupForm, List returnKeys) {
 813  0
         if (StringUtils.isNotBlank(backLocation)) {
 814  0
             String href = UrlFactory.parameterizeUrl(backLocation, parameters);
 815  0
             return addToReturnHref(href, lookupForm);
 816  
         }
 817  0
         return "";
 818  
     }
 819  
 
 820  
     protected String addToReturnHref(String href, LookupForm lookupForm) {
 821  0
         String lookupAnchor = "";
 822  0
         if (StringUtils.isNotEmpty(lookupForm.getAnchor())) {
 823  0
             lookupAnchor = lookupForm.getAnchor();
 824  
         }
 825  0
         href += "&anchor=" + lookupAnchor + "&docNum=" + (StringUtils.isEmpty(getDocNum()) ? "" : getDocNum());
 826  0
         return href;
 827  
     }
 828  
 
 829  
     protected Properties getParameters(BusinessObject bo, Map fieldConversions, String lookupImpl, List returnKeys) {
 830  0
         Properties parameters = new Properties();
 831  0
         parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, KNSConstants.RETURN_METHOD_TO_CALL);
 832  0
         if (getDocFormKey() != null) {
 833  0
             parameters.put(KNSConstants.DOC_FORM_KEY, getDocFormKey());
 834  
         }
 835  0
         if (lookupImpl != null) {
 836  0
             parameters.put(KNSConstants.REFRESH_CALLER, lookupImpl);
 837  
         }
 838  0
         if (getDocNum() != null) {
 839  0
             parameters.put(KNSConstants.DOC_NUM, getDocNum());
 840  
         }
 841  
 
 842  0
         if (getReferencesToRefresh() != null) {
 843  0
             parameters.put(KNSConstants.REFERENCES_TO_REFRESH, getReferencesToRefresh());
 844  
         }
 845  
 
 846  0
         Iterator returnKeysIt = getReturnKeys().iterator();
 847  0
         while (returnKeysIt.hasNext()) {
 848  0
             String fieldNm = (String) returnKeysIt.next();
 849  
 
 850  0
             Object fieldVal = ObjectUtils.getPropertyValue(bo, fieldNm);
 851  0
             if (fieldVal == null) {
 852  0
                 fieldVal = KNSConstants.EMPTY_STRING;
 853  
             }
 854  
 
 855  0
             if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, fieldNm)) {
 856  
                 try {
 857  0
                     fieldVal = getEncryptionService().encrypt(fieldVal) + EncryptionService.ENCRYPTION_POST_PREFIX;
 858  0
                 } catch (GeneralSecurityException e) {
 859  0
                     LOG.error("Exception while trying to encrypted value for inquiry framework.", e);
 860  0
                     throw new RuntimeException(e);
 861  0
                 }
 862  
 
 863  
             }
 864  
 
 865  
             //need to format date in url
 866  0
             if (fieldVal instanceof Date) {
 867  0
                 DateFormatter dateFormatter = new DateFormatter();
 868  0
                 fieldVal = dateFormatter.format(fieldVal);
 869  
             }
 870  
 
 871  0
             if (fieldConversions.containsKey(fieldNm)) {
 872  0
                 fieldNm = (String) fieldConversions.get(fieldNm);
 873  
             }
 874  
 
 875  0
             parameters.put(fieldNm, fieldVal.toString());
 876  0
         }
 877  
 
 878  0
         return parameters;
 879  
     }
 880  
 
 881  
     /**
 882  
      * @return a List of the names of fields which are marked in data dictionary as return fields.
 883  
      */
 884  
     public List getReturnKeys() {
 885  
         List returnKeys;
 886  0
         if (fieldConversions != null && !fieldConversions.isEmpty()) {
 887  0
             returnKeys = new ArrayList(fieldConversions.keySet());
 888  
         } else {
 889  0
             returnKeys = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
 890  
         }
 891  
 
 892  0
         return returnKeys;
 893  
     }
 894  
 
 895  
     /**
 896  
      * Gets the docFormKey attribute.
 897  
      *
 898  
      * @return Returns the docFormKey.
 899  
      */
 900  
     public String getDocFormKey() {
 901  0
         return docFormKey;
 902  
     }
 903  
 
 904  
     /**
 905  
      * Sets the docFormKey attribute value.
 906  
      *
 907  
      * @param docFormKey The docFormKey to set.
 908  
      */
 909  
     public void setDocFormKey(String docFormKey) {
 910  0
         this.docFormKey = docFormKey;
 911  0
     }
 912  
 
 913  
     /**
 914  
      * @see org.kuali.core.lookup.LookupableHelperService#setFieldConversions(java.util.Map)
 915  
      */
 916  
     public void setFieldConversions(Map fieldConversions) {
 917  0
         this.fieldConversions = fieldConversions;
 918  0
     }
 919  
 
 920  
     /**
 921  
      * Gets the lookupService attribute.
 922  
      *
 923  
      * @return Returns the lookupService.
 924  
      */
 925  
     protected LookupService getLookupService() {
 926  0
         return lookupService != null ? lookupService : KNSServiceLocatorWeb.getLookupService();
 927  
     }
 928  
 
 929  
     /**
 930  
      * Sets the lookupService attribute value.
 931  
      *
 932  
      * @param lookupService The lookupService to set.
 933  
      */
 934  
     public void setLookupService(LookupService lookupService) {
 935  0
         this.lookupService = lookupService;
 936  0
     }
 937  
 
 938  
     /**
 939  
      * Uses the DD to determine which is the default sort order.
 940  
      *
 941  
      * @return property names that will be used to sort on by default
 942  
      */
 943  
     public List getDefaultSortColumns() {
 944  0
         return getBusinessObjectDictionaryService().getLookupDefaultSortFieldNames(getBusinessObjectClass());
 945  
     }
 946  
 
 947  
     /**
 948  
      * Checks that any required search fields have value.
 949  
      *
 950  
      * @see org.kuali.core.lookup.LookupableHelperService#validateSearchParameters(java.util.Map)
 951  
      */
 952  
     public void validateSearchParameters(Map fieldValues) {
 953  0
         List<String> lookupFieldAttributeList = null;
 954  0
         if (getBusinessObjectMetaDataService().isLookupable(getBusinessObjectClass())) {
 955  0
             lookupFieldAttributeList = getBusinessObjectMetaDataService().getLookupableFieldNames(getBusinessObjectClass());
 956  
         }
 957  0
         if (lookupFieldAttributeList == null) {
 958  0
             throw new RuntimeException("Lookup not defined for business object " + getBusinessObjectClass());
 959  
         }
 960  0
         for (Iterator iter = lookupFieldAttributeList.iterator(); iter.hasNext();) {
 961  0
             String attributeName = (String) iter.next();
 962  0
             if (fieldValues.containsKey(attributeName)) {
 963  
                 // get label of attribute for message
 964  0
                 String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), attributeName);
 965  
 
 966  0
                 String attributeValue = (String) fieldValues.get(attributeName);
 967  
 
 968  
                 // check for required if field does not have value
 969  0
                 if (StringUtils.isBlank(attributeValue)) {
 970  0
                     if ((getBusinessObjectDictionaryService().getLookupAttributeRequired(getBusinessObjectClass(), attributeName)).booleanValue()) {
 971  0
                         GlobalVariables.getMessageMap().putError(attributeName, RiceKeyConstants.ERROR_REQUIRED, attributeLabel);
 972  
                     }
 973  
                 }
 974  0
                 validateSearchParameterWildcardAndOperators(attributeName, attributeValue);
 975  
             }
 976  0
         }
 977  
 
 978  0
         if (GlobalVariables.getMessageMap().hasErrors()) {
 979  0
             throw new ValidationException("errors in search criteria");
 980  
         }
 981  0
     }
 982  
 
 983  
     protected void validateSearchParameterWildcardAndOperators(String attributeName, String attributeValue) {
 984  0
         if (StringUtils.isBlank(attributeValue))
 985  0
             return;
 986  
 
 987  
         // make sure a wildcard/operator is in the value
 988  0
         boolean found = false;
 989  0
         for (int i = 0; i < KNSConstants.QUERY_CHARACTERS.length; i++) {
 990  0
             String queryCharacter = KNSConstants.QUERY_CHARACTERS[i];
 991  
 
 992  0
             if (attributeValue.contains(queryCharacter)) {
 993  0
                 found = true;
 994  
             }
 995  
         }
 996  0
         if (!found)
 997  0
             return;
 998  
 
 999  0
         String attributeLabel = getDataDictionaryService().getAttributeLabel(getBusinessObjectClass(), attributeName);
 1000  0
         if (getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(businessObjectClass, attributeName)) {
 1001  0
             BusinessObject example = null;
 1002  
             try {
 1003  0
                 example = (BusinessObject) businessObjectClass.newInstance();
 1004  0
             } catch (Exception e) {
 1005  0
                 LOG.error("Exception caught instantiating " + businessObjectClass.getName(), e);
 1006  0
                 throw new RuntimeException("Cannot instantiate " + businessObjectClass.getName(), e);
 1007  0
             }
 1008  
 
 1009  0
             Class propertyType = ObjectUtils.getPropertyType(example, attributeName, getPersistenceStructureService());
 1010  0
             if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) || TypeUtils.isTemporalClass(propertyType)) {
 1011  0
                 GlobalVariables.getMessageMap().putError(attributeName, RiceKeyConstants.ERROR_WILDCARDS_AND_OPERATORS_NOT_ALLOWED_ON_FIELD, attributeLabel);
 1012  
             }
 1013  0
             if (TypeUtils.isStringClass(propertyType)) {
 1014  0
                 GlobalVariables.getMessageMap().putInfo(attributeName, RiceKeyConstants.INFO_WILDCARDS_AND_OPERATORS_TREATED_LITERALLY, attributeLabel);
 1015  
             }
 1016  0
         } else {
 1017  0
             if (getBusinessObjectAuthorizationService().attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, attributeName)) {
 1018  0
                 if (!attributeValue.endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
 1019  
                     // encrypted values usually come from the DB, so we don't need to filter for wildcards
 1020  
 
 1021  
                     // wildcards are not allowed on restricted fields, because they are typically encrypted, and wildcard searches cannot be performed without
 1022  
                     // decrypting every row, which is currently not supported by KNS
 1023  
 
 1024  0
                     GlobalVariables.getMessageMap().putError(attributeName, RiceKeyConstants.ERROR_SECURE_FIELD, attributeLabel);
 1025  
                 }
 1026  
             }
 1027  
         }
 1028  0
     }
 1029  
 
 1030  
     /**
 1031  
      * Constructs the list of rows for the search fields. All properties for the field objects come
 1032  
      * from the DataDictionary. To be called by setBusinessObject
 1033  
      */
 1034  
     protected void setRows() {
 1035  0
         List<String> lookupFieldAttributeList = null;
 1036  0
         if (getBusinessObjectMetaDataService().isLookupable(getBusinessObjectClass())) {
 1037  0
             lookupFieldAttributeList = getBusinessObjectMetaDataService().getLookupableFieldNames(
 1038  
                     getBusinessObjectClass());
 1039  
         }
 1040  0
         if (lookupFieldAttributeList == null) {
 1041  0
             throw new RuntimeException("Lookup not defined for business object " + getBusinessObjectClass());
 1042  
         }
 1043  
 
 1044  
         // construct field object for each search attribute
 1045  0
         List fields = new ArrayList();
 1046  
         try {
 1047  0
             fields = FieldUtils.createAndPopulateFieldsForLookup(lookupFieldAttributeList, getReadOnlyFieldsList(),
 1048  
                     getBusinessObjectClass());
 1049  0
         } catch (InstantiationException e) {
 1050  0
             throw new RuntimeException("Unable to create instance of business object class" + e.getMessage());
 1051  0
         } catch (IllegalAccessException e) {
 1052  0
             throw new RuntimeException("Unable to create instance of business object class" + e.getMessage());
 1053  0
         }
 1054  
 
 1055  0
         int numCols = getBusinessObjectDictionaryService().getLookupNumberOfColumns(this.getBusinessObjectClass());
 1056  
 
 1057  0
         this.rows = FieldUtils.wrapFields(fields, numCols);
 1058  0
     }
 1059  
 
 1060  
     public List<Row> getRows() {
 1061  0
         return rows;
 1062  
     }
 1063  
 
 1064  
     public abstract List<? extends BusinessObject> getSearchResults(Map<String, String> fieldValues);
 1065  
 
 1066  
     /**
 1067  
      * This implementation of this method throws an UnsupportedOperationException, since not every implementation
 1068  
      * may actually want to use this operation.  Subclasses desiring other behaviors
 1069  
      * will need to override this.
 1070  
      *
 1071  
      * @see org.kuali.core.lookup.LookupableHelperService#getSearchResultsUnbounded(java.util.Map)
 1072  
      */
 1073  
     public List<? extends BusinessObject> getSearchResultsUnbounded(Map<String, String> fieldValues) {
 1074  0
         throw new UnsupportedOperationException("Lookupable helper services do not always support getSearchResultsUnbounded");
 1075  
     }
 1076  
 
 1077  
     /**
 1078  
      * Performs the lookup and returns a collection of lookup items
 1079  
      *
 1080  
      * @param lookupForm
 1081  
      * @param resultTable
 1082  
      * @param bounded
 1083  
      * @return
 1084  
      */
 1085  
     public Collection performLookup(LookupForm lookupForm, Collection resultTable, boolean bounded) {
 1086  0
         Map lookupFormFields = lookupForm.getFieldsForLookup();
 1087  
 
 1088  0
         setBackLocation((String) lookupForm.getFieldsForLookup().get(KNSConstants.BACK_LOCATION));
 1089  0
         setDocFormKey((String) lookupForm.getFieldsForLookup().get(KNSConstants.DOC_FORM_KEY));
 1090  
         Collection displayList;
 1091  
 
 1092  0
         preprocessDateFields(lookupFormFields);
 1093  
 
 1094  0
         Map fieldsForLookup = new HashMap(lookupForm.getFieldsForLookup());
 1095  
         // call search method to get results
 1096  0
         if (bounded) {
 1097  0
             displayList = getSearchResults(lookupForm.getFieldsForLookup());
 1098  
         } else {
 1099  0
             displayList = getSearchResultsUnbounded(lookupForm.getFieldsForLookup());
 1100  
         }
 1101  
 
 1102  0
         boolean hasReturnableRow = false;
 1103  
 
 1104  0
         List returnKeys = getReturnKeys();
 1105  0
         List pkNames = getBusinessObjectMetaDataService().listPrimaryKeyFieldNames(getBusinessObjectClass());
 1106  0
         Person user = GlobalVariables.getUserSession().getPerson();
 1107  
 
 1108  
         // iterate through result list and wrap rows with return url and action
 1109  
         // urls
 1110  0
         for (Iterator iter = displayList.iterator(); iter.hasNext();) {
 1111  0
             BusinessObject element = (BusinessObject) iter.next();
 1112  
 
 1113  0
             final String lookupId = KNSServiceLocatorWeb.getLookupResultsService().getLookupId(element);
 1114  0
             if (lookupId != null) {
 1115  0
                 lookupForm.setLookupObjectId(lookupId);
 1116  
             }
 1117  
 
 1118  0
             BusinessObjectRestrictions businessObjectRestrictions = getBusinessObjectAuthorizationService()
 1119  
                     .getLookupResultRestrictions(element, user);
 1120  
 
 1121  0
             HtmlData returnUrl = getReturnUrl(element, lookupForm, returnKeys, businessObjectRestrictions);
 1122  0
             String actionUrls = getActionUrls(element, pkNames, businessObjectRestrictions);
 1123  
             // Fix for JIRA - KFSMI-2417
 1124  0
             if ("".equals(actionUrls)) {
 1125  0
                 actionUrls = ACTION_URLS_EMPTY;
 1126  
             }
 1127  
 
 1128  0
             List<Column> columns = getColumns();
 1129  0
             for (Iterator iterator = columns.iterator(); iterator.hasNext();) {
 1130  0
                 Column col = (Column) iterator.next();
 1131  
 
 1132  0
                 String propValue = ObjectUtils.getFormattedPropertyValue(element, col.getPropertyName(), col.getFormatter());
 1133  0
                 Class propClass = getPropertyClass(element, col.getPropertyName());
 1134  
 
 1135  0
                 col.setComparator(CellComparatorHelper.getAppropriateComparatorForPropertyClass(propClass));
 1136  0
                 col.setValueComparator(CellComparatorHelper.getAppropriateValueComparatorForPropertyClass(propClass));
 1137  
 
 1138  0
                 String propValueBeforePotientalMasking = propValue;
 1139  0
                 propValue = maskValueIfNecessary(element.getClass(), col.getPropertyName(), propValue,
 1140  
                         businessObjectRestrictions);
 1141  0
                 col.setPropertyValue(propValue);
 1142  
 
 1143  
                 // if property value is masked, don't display additional or alternate properties, or allow totals
 1144  0
                 if (StringUtils.equals(propValueBeforePotientalMasking, propValue)) {
 1145  0
                     if (StringUtils.isNotBlank(col.getAlternateDisplayPropertyName())) {
 1146  0
                         String alternatePropertyValue = ObjectUtils.getFormattedPropertyValue(element, col
 1147  
                                 .getAlternateDisplayPropertyName(), null);
 1148  0
                         col.setPropertyValue(alternatePropertyValue);
 1149  
                     }
 1150  
 
 1151  0
                     if (StringUtils.isNotBlank(col.getAdditionalDisplayPropertyName())) {
 1152  0
                         String additionalPropertyValue = ObjectUtils.getFormattedPropertyValue(element, col
 1153  
                                 .getAdditionalDisplayPropertyName(), null);
 1154  0
                         col.setPropertyValue(col.getPropertyValue() + " *-* " + additionalPropertyValue);
 1155  0
                     }
 1156  
                 } else {
 1157  0
                     col.setTotal(false);
 1158  
                 }
 1159  
 
 1160  0
                 if (col.isTotal()) {
 1161  0
                     Object unformattedPropValue = ObjectUtils.getPropertyValue(element, col.getPropertyName());
 1162  0
                     col.setUnformattedPropertyValue(unformattedPropValue);
 1163  
                 }
 1164  
 
 1165  0
                 if (StringUtils.isNotBlank(propValue)) {
 1166  0
                     col.setColumnAnchor(getInquiryUrl(element, col.getPropertyName()));
 1167  
                 }
 1168  0
             }
 1169  
 
 1170  0
             ResultRow row = new ResultRow(columns, returnUrl.constructCompleteHtmlTag(), actionUrls);
 1171  0
             row.setRowId(returnUrl.getName());
 1172  0
             row.setReturnUrlHtmlData(returnUrl);
 1173  
 
 1174  
             // because of concerns of the BO being cached in session on the
 1175  
             // ResultRow,
 1176  
             // let's only attach it when needed (currently in the case of
 1177  
             // export)
 1178  0
             if (getBusinessObjectDictionaryService().isExportable(getBusinessObjectClass())) {
 1179  0
                 row.setBusinessObject(element);
 1180  
             }
 1181  
 
 1182  0
             if (lookupId != null) {
 1183  0
                 row.setObjectId(lookupId);
 1184  
             }
 1185  
 
 1186  0
             boolean rowReturnable = isResultReturnable(element);
 1187  0
             row.setRowReturnable(rowReturnable);
 1188  0
             if (rowReturnable) {
 1189  0
                 hasReturnableRow = true;
 1190  
             }
 1191  0
             resultTable.add(row);
 1192  0
         }
 1193  
 
 1194  0
         lookupForm.setHasReturnableRow(hasReturnableRow);
 1195  
 
 1196  0
         return displayList;
 1197  
     }
 1198  
 
 1199  
     /**
 1200  
      * Gets the Class for the property in the given BusinessObject instance, if
 1201  
      * property is not accessible then runtime exception is thrown
 1202  
      *
 1203  
      * @param element      BusinessObject instance that contains property
 1204  
      * @param propertyName Name of property in BusinessObject to get class for
 1205  
      * @return Type for property as Class
 1206  
      */
 1207  
     protected Class getPropertyClass(BusinessObject element, String propertyName) {
 1208  0
         Class propClass = null;
 1209  
 
 1210  
         try {
 1211  0
             propClass = ObjectUtils.getPropertyType(element, propertyName, getPersistenceStructureService());
 1212  
 
 1213  0
         } catch (Exception e) {
 1214  0
             throw new RuntimeException("Cannot access PropertyType for property " + "'" + propertyName + "' "
 1215  
                     + " on an instance of '" + element.getClass().getName() + "'.", e);
 1216  0
         }
 1217  
 
 1218  0
         return propClass;
 1219  
     }
 1220  
 
 1221  
     /**
 1222  
      * changes from/to dates into the range operators the lookupable dao expects ("..",">" etc)
 1223  
      * this method modifies the passed in map and returns a list containing only the modified fields
 1224  
      *
 1225  
      * @param lookupFormFields
 1226  
      */
 1227  
     protected Map<String, String> preprocessDateFields(Map lookupFormFields) {
 1228  0
         Map<String, String> fieldsToUpdate = new HashMap<String, String>();
 1229  0
         Set<String> fieldsForLookup = lookupFormFields.keySet();
 1230  0
         for (String propName : fieldsForLookup) {
 1231  0
             if (propName.startsWith(KNSConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX)) {
 1232  0
                 String fromDateValue = (String) lookupFormFields.get(propName);
 1233  0
                 String dateFieldName = StringUtils.remove(propName, KNSConstants.LOOKUP_RANGE_LOWER_BOUND_PROPERTY_PREFIX);
 1234  0
                 String dateValue = (String) lookupFormFields.get(dateFieldName);
 1235  0
                 String newPropValue = dateValue;//maybe clean above with ObjectUtils.clean(propertyValue)
 1236  0
                 if (StringUtils.isNotEmpty(fromDateValue) && StringUtils.isNotEmpty(dateValue)) {
 1237  0
                     newPropValue = fromDateValue + KNSConstants.BETWEEN_OPERATOR + dateValue;
 1238  0
                 } else if (StringUtils.isNotEmpty(fromDateValue) && StringUtils.isEmpty(dateValue)) {
 1239  0
                     newPropValue = ">=" + fromDateValue;
 1240  0
                 } else if (StringUtils.isNotEmpty(dateValue) && StringUtils.isEmpty(fromDateValue)) {
 1241  0
                     newPropValue = "<=" + dateValue;
 1242  
                 } //could optionally continue on else here
 1243  
 
 1244  0
                 fieldsToUpdate.put(dateFieldName, newPropValue);
 1245  0
             }
 1246  
         }
 1247  
         //update lookup values from found date values to update
 1248  0
         Set<String> keysToUpdate = fieldsToUpdate.keySet();
 1249  0
         for (String updateKey : keysToUpdate) {
 1250  0
             lookupFormFields.put(updateKey, fieldsToUpdate.get(updateKey));
 1251  
         }
 1252  0
         return fieldsToUpdate;
 1253  
     }
 1254  
 
 1255  
     protected String maskValueIfNecessary(Class businessObjectClass, String propertyName, String propertyValue, BusinessObjectRestrictions businessObjectRestrictions) {
 1256  0
         String maskedPropertyValue = propertyValue;
 1257  0
         if (businessObjectRestrictions != null) {
 1258  0
             FieldRestriction fieldRestriction = businessObjectRestrictions.getFieldRestriction(propertyName);
 1259  0
             if (fieldRestriction != null && (fieldRestriction.isMasked() || fieldRestriction.isPartiallyMasked())) {
 1260  0
                 maskedPropertyValue = fieldRestriction.getMaskFormatter().maskValue(propertyValue);
 1261  
             }
 1262  
         }
 1263  0
         return maskedPropertyValue;
 1264  
     }
 1265  
 
 1266  
 
 1267  
     protected void setReferencesToRefresh(String referencesToRefresh) {
 1268  0
         this.referencesToRefresh = referencesToRefresh;
 1269  0
     }
 1270  
 
 1271  
     public String getReferencesToRefresh() {
 1272  0
         return referencesToRefresh;
 1273  
     }
 1274  
 
 1275  
     protected SequenceAccessorService getSequenceAccessorService() {
 1276  0
         return sequenceAccessorService != null ? sequenceAccessorService : KNSServiceLocator.getSequenceAccessorService();
 1277  
     }
 1278  
 
 1279  
     public void setSequenceAccessorService(SequenceAccessorService sequenceAccessorService) {
 1280  0
         this.sequenceAccessorService = sequenceAccessorService;
 1281  0
     }
 1282  
 
 1283  
     public BusinessObjectService getBusinessObjectService() {
 1284  0
         return businessObjectService != null ? businessObjectService : KNSServiceLocator.getBusinessObjectService();
 1285  
     }
 1286  
 
 1287  
     public void setBusinessObjectService(BusinessObjectService businessObjectService) {
 1288  0
         this.businessObjectService = businessObjectService;
 1289  0
     }
 1290  
 
 1291  
     protected LookupResultsService getLookupResultsService() {
 1292  0
         return lookupResultsService != null ? lookupResultsService : KNSServiceLocatorWeb.getLookupResultsService();
 1293  
     }
 1294  
 
 1295  
     public void setLookupResultsService(LookupResultsService lookupResultsService) {
 1296  0
         this.lookupResultsService = lookupResultsService;
 1297  0
     }
 1298  
 
 1299  
     /**
 1300  
      * @return false always, subclasses should override to do something smarter
 1301  
      * @see org.kuali.core.lookup.LookupableHelperService#isSearchUsingOnlyPrimaryKeyValues()
 1302  
      */
 1303  
     public boolean isSearchUsingOnlyPrimaryKeyValues() {
 1304  
         // by default, this implementation returns false, as lookups may not necessarily support this
 1305  0
         return false;
 1306  
     }
 1307  
 
 1308  
     /**
 1309  
      * Returns "N/A"
 1310  
      *
 1311  
      * @return "N/A"
 1312  
      * @see org.kuali.core.lookup.LookupableHelperService#getPrimaryKeyFieldLabels()
 1313  
      */
 1314  
     public String getPrimaryKeyFieldLabels() {
 1315  0
         return KNSConstants.NOT_AVAILABLE_STRING;
 1316  
     }
 1317  
 
 1318  
     /**
 1319  
      * @see org.kuali.core.lookup.LookupableHelperService#isResultReturnable(org.kuali.core.bo.BusinessObject)
 1320  
      */
 1321  
     public boolean isResultReturnable(BusinessObject object) {
 1322  0
         return true;
 1323  
     }
 1324  
 
 1325  
     /**
 1326  
      * This method does the logic for the clear action.
 1327  
      *
 1328  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#performClear()
 1329  
      */
 1330  
     public void performClear(LookupForm lookupForm) {
 1331  0
         for (Iterator iter = this.getRows().iterator(); iter.hasNext();) {
 1332  0
             Row row = (Row) iter.next();
 1333  0
             for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
 1334  0
                 Field field = (Field) iterator.next();
 1335  0
                 if (field.isSecure()) {
 1336  0
                     field.setSecure(false);
 1337  0
                     field.setDisplayMaskValue(null);
 1338  0
                     field.setEncryptedValue(null);
 1339  
                 }
 1340  
 
 1341  0
                 if (!field.getFieldType().equals(Field.RADIO)) {
 1342  0
                     field.setPropertyValue(field.getDefaultValue());
 1343  
                 }
 1344  0
             }
 1345  0
         }
 1346  0
     }
 1347  
 
 1348  
     /**
 1349  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#shouldDisplayHeaderNonMaintActions()
 1350  
      */
 1351  
     public boolean shouldDisplayHeaderNonMaintActions() {
 1352  0
         return true;
 1353  
     }
 1354  
 
 1355  
     /**
 1356  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#shouldDisplayLookupCriteria()
 1357  
      */
 1358  
     public boolean shouldDisplayLookupCriteria() {
 1359  0
         return true;
 1360  
     }
 1361  
 
 1362  
     /**
 1363  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getSupplementalMenuBar()
 1364  
      */
 1365  
     public String getSupplementalMenuBar() {
 1366  0
         return new String();
 1367  
     }
 1368  
 
 1369  
     /**
 1370  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#getTitle()
 1371  
      */
 1372  
     public String getTitle() {
 1373  0
         return getBusinessObjectDictionaryService().getLookupTitle(getBusinessObjectClass());
 1374  
     }
 1375  
 
 1376  
     /**
 1377  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#performCustomAction(boolean)
 1378  
      */
 1379  
     public boolean performCustomAction(boolean ignoreErrors) {
 1380  0
         return false;
 1381  
     }
 1382  
 
 1383  
     /**
 1384  
      * @see org.kuali.rice.kns.lookup.Lookupable#getExtraField()
 1385  
      */
 1386  
     public Field getExtraField() {
 1387  0
         return null;
 1388  
     }
 1389  
 
 1390  
     public boolean allowsNewOrCopyAction(String documentTypeName) {
 1391  0
         throw new UnsupportedOperationException("Function not supported.");
 1392  
     }
 1393  
 
 1394  
     /**
 1395  
      * Functional requirements state that users are able to perform searches using criteria values that they are not allowed to view.
 1396  
      *
 1397  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#applyFieldAuthorizationsFromNestedLookups(org.kuali.rice.kns.web.ui.Field)
 1398  
      */
 1399  
     public void applyFieldAuthorizationsFromNestedLookups(Field field) {
 1400  0
         BusinessObjectAuthorizationService boAuthzService = this.getBusinessObjectAuthorizationService();
 1401  0
         if (!Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
 1402  0
             if (field.getPropertyValue() != null && field.getPropertyValue().endsWith(EncryptionService.ENCRYPTION_POST_PREFIX)) {
 1403  0
                 if (boAuthzService.attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, field.getPropertyName())) {
 1404  0
                     AttributeSecurity attributeSecurity = getDataDictionaryService().getAttributeSecurity(businessObjectClass.getName(), field.getPropertyName());
 1405  0
                     Person user = GlobalVariables.getUserSession().getPerson();
 1406  
                     String decryptedValue;
 1407  
                     try {
 1408  0
                         String cipherText = StringUtils.removeEnd(field.getPropertyValue(), EncryptionService.ENCRYPTION_POST_PREFIX);
 1409  0
                         decryptedValue = getEncryptionService().decrypt(cipherText);
 1410  0
                     } catch (GeneralSecurityException e) {
 1411  0
                         throw new RuntimeException("Error decrypting value for business object " + businessObjectClass + " attribute " + field.getPropertyName(), e);
 1412  0
                     }
 1413  0
                     if (attributeSecurity.isMask() && !boAuthzService.canFullyUnmaskField(user,
 1414  
                             businessObjectClass, field.getPropertyName(), null)) {
 1415  0
                         MaskFormatter maskFormatter = attributeSecurity.getMaskFormatter();
 1416  0
                         field.setEncryptedValue(field.getPropertyValue());
 1417  0
                         field.setDisplayMaskValue(maskFormatter.maskValue(decryptedValue));
 1418  0
                         field.setSecure(true);
 1419  0
                     } else if (attributeSecurity.isPartialMask() && !boAuthzService.canPartiallyUnmaskField(user,
 1420  
                             businessObjectClass, field.getPropertyName(), null)) {
 1421  0
                         MaskFormatter maskFormatter = attributeSecurity.getPartialMaskFormatter();
 1422  0
                         field.setEncryptedValue(field.getPropertyValue());
 1423  0
                         field.setDisplayMaskValue(maskFormatter.maskValue(decryptedValue));
 1424  0
                         field.setSecure(true);
 1425  0
                     } else {
 1426  0
                         field.setPropertyValue(LookupUtils.forceUppercase(businessObjectClass, field.getPropertyName(), decryptedValue));
 1427  
                     }
 1428  0
                 } else {
 1429  0
                     throw new RuntimeException("Field " + field.getPersonNameAttributeName() + " was encrypted on " + businessObjectClass.getName() +
 1430  
                             " lookup was encrypted when it should not have been encrypted according to the data dictionary.");
 1431  
                 }
 1432  
             }
 1433  
         } else {
 1434  0
             if (boAuthzService.attributeValueNeedsToBeEncryptedOnFormsAndLinks(businessObjectClass, field.getPropertyName())) {
 1435  0
                 LOG.error("Cannot handle multiple value field types that have field authorizations, please implement custom lookupable helper service");
 1436  0
                 throw new RuntimeException("Cannot handle multiple value field types that have field authorizations.");
 1437  
             }
 1438  
         }
 1439  0
     }
 1440  
 
 1441  
     /**
 1442  
      * Calls methods that can be overridden by child lookupables to implement conditional logic for setting
 1443  
      * read-only, required, and hidden attributes. Called in the last part of the lookup lifecycle so the
 1444  
      * fields values that will be sent will be correctly reflected in the rows (like after a clear).
 1445  
      *
 1446  
      * @see #getConditionallyReadOnlyPropertyNames()
 1447  
      * @see #getConditionallyRequiredPropertyNames()
 1448  
      * @see #getConditionallyHiddenPropertyNames()
 1449  
      * @see org.kuali.rice.kns.lookup.LookupableHelperService#applyConditionalLogicForFieldDisplay()
 1450  
      */
 1451  
     public void applyConditionalLogicForFieldDisplay() {
 1452  0
         Set<String> readOnlyFields = getConditionallyReadOnlyPropertyNames();
 1453  0
         Set<String> requiredFields = getConditionallyRequiredPropertyNames();
 1454  0
         Set<String> hiddenFields = getConditionallyHiddenPropertyNames();
 1455  
 
 1456  0
         for (Iterator iter = this.getRows().iterator(); iter.hasNext();) {
 1457  0
             Row row = (Row) iter.next();
 1458  0
             for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
 1459  0
                 Field field = (Field) iterator.next();
 1460  
 
 1461  0
                 if (readOnlyFields != null && readOnlyFields.contains(field.getPropertyName())) {
 1462  0
                     field.setReadOnly(true);
 1463  
                 }
 1464  
 
 1465  0
                 if (requiredFields != null && requiredFields.contains(field.getPropertyName())) {
 1466  0
                     field.setFieldRequired(true);
 1467  
                 }
 1468  
 
 1469  0
                 if (hiddenFields != null && hiddenFields.contains(field.getPropertyName())) {
 1470  0
                     field.setFieldType(Field.HIDDEN);
 1471  
                 }
 1472  0
             }
 1473  0
         }
 1474  0
     }
 1475  
 
 1476  
     /**
 1477  
      * @return Set of property names that should be set as read only based on the current search
 1478  
      *         contents, note request parms containing search field values can be retrieved with
 1479  
      *         {@link #getParameters()}
 1480  
      */
 1481  
     public Set<String> getConditionallyReadOnlyPropertyNames() {
 1482  0
         return new HashSet<String>();
 1483  
     }
 1484  
 
 1485  
     /**
 1486  
      * @return Set of property names that should be set as required based on the current search
 1487  
      *         contents, note request parms containing search field values can be retrieved with
 1488  
      *         {@link #getParameters()}
 1489  
      */
 1490  
     public Set<String> getConditionallyRequiredPropertyNames() {
 1491  0
         return new HashSet<String>();
 1492  
     }
 1493  
 
 1494  
     /**
 1495  
      * @return Set of property names that should be set as hidden based on the current search
 1496  
      *         contents, note request parms containing search field values can be retrieved with
 1497  
      *         {@link #getParameters()}
 1498  
      */
 1499  
     public Set<String> getConditionallyHiddenPropertyNames() {
 1500  0
         return new HashSet<String>();
 1501  
     }
 1502  
 
 1503  
     /**
 1504  
      * Helper method to get the value for a property out of the row-field graph. If property is
 1505  
      * multi-value then the values will be joined by a semi-colon.
 1506  
      *
 1507  
      * @param propertyName - name of property to retrieve value for
 1508  
      * @return current property value as a String
 1509  
      */
 1510  
     protected String getCurrentSearchFieldValue(String propertyName) {
 1511  0
         String currentValue = null;
 1512  
 
 1513  0
         boolean fieldFound = false;
 1514  0
         for (Iterator iter = this.getRows().iterator(); iter.hasNext();) {
 1515  0
             Row row = (Row) iter.next();
 1516  0
             for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
 1517  0
                 Field field = (Field) iterator.next();
 1518  
 
 1519  0
                 if (StringUtils.equalsIgnoreCase(propertyName, field.getPropertyName())) {
 1520  0
                     if (Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType())) {
 1521  0
                         currentValue = StringUtils.join(field.getPropertyValues(), ";");
 1522  
                     } else {
 1523  0
                         currentValue = field.getPropertyValue();
 1524  
                     }
 1525  0
                     fieldFound = true;
 1526  
                 }
 1527  
 
 1528  0
                 if (fieldFound) {
 1529  0
                     break;
 1530  
                 }
 1531  0
             }
 1532  
 
 1533  0
             if (fieldFound) {
 1534  0
                 break;
 1535  
             }
 1536  0
         }
 1537  
 
 1538  0
         return currentValue;
 1539  
     }
 1540  
 }