Coverage Report - org.kuali.rice.krad.web.struts.action.KualiMultipleValueLookupAction
 
Classes in this File Line Coverage Branch Coverage Complexity
KualiMultipleValueLookupAction
0%
0/212
0%
0/42
3.158
 
 1  
 /*
 2  
  * Copyright 2007 The Kuali Foundation
 3  
  * 
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  * 
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  * 
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.krad.web.struts.action;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.util.ArrayList;
 20  
 import java.util.Collection;
 21  
 import java.util.Collections;
 22  
 import java.util.HashMap;
 23  
 import java.util.List;
 24  
 import java.util.Map;
 25  
 import java.util.Properties;
 26  
 import java.util.Set;
 27  
 
 28  
 import javax.servlet.ServletException;
 29  
 import javax.servlet.http.HttpServletRequest;
 30  
 import javax.servlet.http.HttpServletResponse;
 31  
 
 32  
 import org.apache.commons.beanutils.BeanComparator;
 33  
 import org.apache.commons.lang.StringUtils;
 34  
 import org.apache.struts.action.ActionForm;
 35  
 import org.apache.struts.action.ActionForward;
 36  
 import org.apache.struts.action.ActionMapping;
 37  
 import org.kuali.rice.core.util.RiceConstants;
 38  
 import org.kuali.rice.krad.lookup.CollectionIncomplete;
 39  
 import org.kuali.rice.krad.lookup.LookupResultsService;
 40  
 import org.kuali.rice.krad.lookup.LookupUtils;
 41  
 import org.kuali.rice.krad.lookup.Lookupable;
 42  
 import org.kuali.rice.krad.lookup.HtmlData.InputHtmlData;
 43  
 import org.kuali.rice.krad.service.KRADServiceLocator;
 44  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 45  
 import org.kuali.rice.krad.service.SequenceAccessorService;
 46  
 import org.kuali.rice.krad.util.GlobalVariables;
 47  
 import org.kuali.rice.krad.util.KRADConstants;
 48  
 import org.kuali.rice.krad.util.UrlFactory;
 49  
 import org.kuali.rice.krad.web.struts.form.MultipleValueLookupForm;
 50  
 import org.kuali.rice.krad.web.ui.Column;
 51  
 import org.kuali.rice.krad.web.ui.ResultRow;
 52  
 
 53  
 /**
 54  
  * This class serves as the struts action for implementing multiple value lookups
 55  
  */
 56  0
 public class KualiMultipleValueLookupAction extends KualiLookupAction implements KualiTableRenderAction {
 57  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiMultipleValueLookupAction.class);
 58  
     
 59  
     /**
 60  
      * If there is no app param defined for the # rows/page, then this value
 61  
      * will be used for the default
 62  
      * 
 63  
      * @see KualiMultipleValueLookupAction#getMaxRowsPerPage(MultipleValueLookupForm)
 64  
      */
 65  
     public static final int DEFAULT_MAX_ROWS_PER_PAGE = 50;
 66  
     
 67  
     
 68  
     /**
 69  
      * This method performs the search, and will be responsible for persisting the results via the LookupResultsService.
 70  
      * This overrides the superclass's search action method b/c of the differences in how the results are generated and it populates
 71  
      * certain attributes that are specific to MultipleValueLookupForm
 72  
      * 
 73  
      * @param mapping
 74  
      * @param form must be an instance of MultipleValueLookupForm
 75  
      * @param request
 76  
      * @param response 
 77  
      */
 78  
     @Override
 79  
     public ActionForward search(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 80  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 81  
         
 82  
         // If this is a new search, clear out the old search results.
 83  0
             String methodToCall = findMethodToCall(form, request);
 84  0
                 if (methodToCall.equalsIgnoreCase("search")) {
 85  0
                         GlobalVariables.getUserSession().removeObjectsByPrefix(KRADConstants.SEARCH_METHOD);
 86  
                 }
 87  
                 
 88  0
         Lookupable kualiLookupable = multipleValueLookupForm.getLookupable();
 89  0
         if (kualiLookupable == null) {
 90  0
             LOG.error("Lookupable is null.");
 91  0
             throw new RuntimeException("Lookupable is null.");
 92  
         }
 93  
         
 94  0
         Collection displayList = new ArrayList();
 95  0
         ArrayList<ResultRow> resultTable = new ArrayList<ResultRow>();
 96  
 
 97  
         // validate search parameters
 98  0
         kualiLookupable.validateSearchParameters(multipleValueLookupForm.getFields());
 99  
 
 100  0
         boolean bounded = true;
 101  
 
 102  0
         displayList = performMultipleValueLookup(multipleValueLookupForm, resultTable, getMaxRowsPerPage(multipleValueLookupForm), bounded);
 103  0
         if (kualiLookupable.isSearchUsingOnlyPrimaryKeyValues()) {
 104  0
             multipleValueLookupForm.setSearchUsingOnlyPrimaryKeyValues(true);
 105  0
             multipleValueLookupForm.setPrimaryKeyFieldLabels(kualiLookupable.getPrimaryKeyFieldLabels());
 106  
         }
 107  
         else {
 108  0
             multipleValueLookupForm.setSearchUsingOnlyPrimaryKeyValues(false);
 109  0
             multipleValueLookupForm.setPrimaryKeyFieldLabels(KRADConstants.EMPTY_STRING);
 110  
         }
 111  
         
 112  
         //request.setAttribute("reqSearchResultsActualSize", ((CollectionIncomplete) displayList).getActualSizeIfTruncated());
 113  
         
 114  0
         if ( displayList instanceof CollectionIncomplete ){
 115  0
             request.setAttribute("reqSearchResultsActualSize", ((CollectionIncomplete) displayList).getActualSizeIfTruncated());
 116  
         } else {
 117  0
             request.setAttribute("reqSearchResultsActualSize", displayList.size() );
 118  
         }
 119  
         
 120  0
         request.setAttribute("reqSearchResults", resultTable);
 121  
         
 122  
         //multipleValueLookupForm.setResultsActualSize((int) ((CollectionIncomplete) displayList).getActualSizeIfTruncated().longValue());
 123  
         
 124  0
         if ( displayList instanceof CollectionIncomplete ){
 125  0
                 multipleValueLookupForm.setResultsActualSize((int) ((CollectionIncomplete) displayList).getActualSizeIfTruncated().longValue());    
 126  
         } else {
 127  0
                 multipleValueLookupForm.setResultsActualSize(displayList.size()); 
 128  
         }
 129  
         
 130  
         
 131  0
         multipleValueLookupForm.setResultsLimitedSize(resultTable.size());
 132  
 
 133  0
         if (request.getParameter(KRADConstants.SEARCH_LIST_REQUEST_KEY) != null) {
 134  0
             GlobalVariables.getUserSession().removeObject(request.getParameter(KRADConstants.SEARCH_LIST_REQUEST_KEY));
 135  
         }
 136  0
         request.setAttribute(KRADConstants.SEARCH_LIST_REQUEST_KEY, GlobalVariables.getUserSession().addObjectWithGeneratedKey(resultTable, KRADConstants.SEARCH_LIST_KEY_PREFIX));
 137  
 
 138  0
         request.getParameter(KRADConstants.REFRESH_CALLER);
 139  
 
 140  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 141  
     }
 142  
 
 143  
     /**
 144  
      * This method switches to another page on a multi-value lookup
 145  
      * 
 146  
      * @param mapping
 147  
      * @param form must be an instance of MultipleValueLookupForm
 148  
      * @param request
 149  
      * @param response
 150  
      * @return
 151  
      * @throws Exception
 152  
      */
 153  
     @Override
 154  
         public ActionForward switchToPage(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 155  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 156  0
         List<ResultRow> resultTable = switchToPage(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
 157  0
         request.setAttribute("reqSearchResults", resultTable);
 158  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 159  
     }
 160  
     
 161  
     /**
 162  
      * This method sorts a column.  If the page is currently sorted on a certain column,
 163  
      * and the same column is selected to be sorted again, then the results will be 
 164  
      * reversed.  After the search method is called, it is difficult to determine the sort
 165  
      * order of the result table, so no column is considered sorted.  So, after a search, we were
 166  
      * to click sort on an already sorted column, it would appear to have no effect.  Subsequent clicks
 167  
      * would tell you  
 168  
      * 
 169  
      * @param mapping
 170  
      * @param form must be an instance of MultipleValueLookupForm
 171  
      * @param request
 172  
      * @param response
 173  
      * @return
 174  
      * @throws Exception
 175  
      */
 176  
     @Override
 177  
         public ActionForward sort(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 178  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 179  0
         List<ResultRow> resultTable = sort(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
 180  0
         request.setAttribute("reqSearchResults", resultTable);
 181  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 182  
     }
 183  
     
 184  
     /**
 185  
      * This method does the processing necessary to return selected results and sends a redirect back to the lookup caller
 186  
      * 
 187  
      * @param mapping
 188  
      * @param form must be an instance of MultipleValueLookupForm
 189  
      * @param request
 190  
      * @param response
 191  
      * @return
 192  
      * @throws Exception
 193  
      */
 194  
     public ActionForward prepareToReturnSelectedResults(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 195  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 196  0
         if (StringUtils.isBlank(multipleValueLookupForm.getLookupResultsSequenceNumber())) {
 197  
             // no search was executed
 198  0
             return prepareToReturnNone(mapping, form, request, response);
 199  
         }
 200  
         
 201  0
         prepareToReturnSelectedResultBOs(multipleValueLookupForm);
 202  
         
 203  
         // build the parameters for the refresh url
 204  0
         Properties parameters = new Properties();
 205  0
         parameters.put(KRADConstants.LOOKUP_RESULTS_BO_CLASS_NAME, multipleValueLookupForm.getBusinessObjectClassName());
 206  0
         parameters.put(KRADConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER, multipleValueLookupForm.getLookupResultsSequenceNumber());
 207  0
         parameters.put(KRADConstants.DOC_FORM_KEY, multipleValueLookupForm.getFormKey());
 208  0
         parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.RETURN_METHOD_TO_CALL);
 209  0
         parameters.put(KRADConstants.REFRESH_CALLER, KRADConstants.MULTIPLE_VALUE);
 210  0
         parameters.put(KRADConstants.ANCHOR, multipleValueLookupForm.getLookupAnchor());
 211  0
         parameters.put(KRADConstants.LOOKED_UP_COLLECTION_NAME, multipleValueLookupForm.getLookedUpCollectionName());
 212  0
         if(multipleValueLookupForm.getDocNum() != null){
 213  0
                 parameters.put(KRADConstants.DOC_NUM, multipleValueLookupForm.getDocNum());
 214  
         }
 215  
 
 216  
 
 217  0
         String backUrl = UrlFactory.parameterizeUrl(multipleValueLookupForm.getBackLocation(), parameters);
 218  0
         return new ActionForward(backUrl, true);
 219  
     }
 220  
     
 221  
     /**
 222  
      * This method selects all results across all pages
 223  
      * @param mapping
 224  
      * @param form must be an instance of MultipleValueLookupForm
 225  
      * @param request
 226  
      * @param response
 227  
      * @return
 228  
      * @throws Exception
 229  
      */
 230  
     public ActionForward selectAll(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 231  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 232  0
         List<ResultRow> resultTable = selectAll(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
 233  0
         request.setAttribute("reqSearchResults", resultTable);
 234  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 235  
     }
 236  
     
 237  
     /**
 238  
      * This method unselects all results across all pages
 239  
      * 
 240  
      * @param mapping
 241  
      * @param form must be an instance of MultipleValueLookupForm
 242  
      * @param request
 243  
      * @param response
 244  
      * @return
 245  
      * @throws Exception
 246  
      */
 247  
     public ActionForward unselectAll(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 248  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 249  0
         List<ResultRow> resultTable = unselectAll(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
 250  0
         request.setAttribute("reqSearchResults", resultTable);
 251  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 252  
     }
 253  
     
 254  
     /**
 255  
      * This method overrides the super class cancel method because it is basically equivalent to clicking prepare to return none 
 256  
      * 
 257  
      * @see org.kuali.rice.krad.web.struts.action.KualiLookupAction#cancel(org.apache.struts.action.ActionMapping, org.apache.struts.action.ActionForm, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
 258  
      */
 259  
     @Override
 260  
     public ActionForward cancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 261  0
         return prepareToReturnNone(mapping, form, request, response);
 262  
     }
 263  
     
 264  
 
 265  
     /**
 266  
      * This method returns none of the selected results and redirects back to the lookup caller.
 267  
      * @param mapping
 268  
      * @param form must be an instance of MultipleValueLookupForm
 269  
      * @param request
 270  
      * @param response
 271  
      * @return
 272  
      * @throws Exception
 273  
      */
 274  
     public ActionForward prepareToReturnNone(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 275  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 276  0
         prepareToReturnNone(multipleValueLookupForm);
 277  
         
 278  
         // build the parameters for the refresh url
 279  0
         Properties parameters = new Properties();
 280  0
         parameters.put(KRADConstants.DOC_FORM_KEY, multipleValueLookupForm.getFormKey());
 281  0
         parameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.RETURN_METHOD_TO_CALL);
 282  0
         parameters.put(KRADConstants.REFRESH_CALLER, KRADConstants.MULTIPLE_VALUE);
 283  0
         parameters.put(KRADConstants.ANCHOR, multipleValueLookupForm.getLookupAnchor());
 284  0
         if(multipleValueLookupForm.getDocNum() != null){
 285  0
                 parameters.put(KRADConstants.DOC_NUM, multipleValueLookupForm.getDocNum());
 286  
         }
 287  0
         String backUrl = UrlFactory.parameterizeUrl(multipleValueLookupForm.getBackLocation(), parameters);
 288  0
         return new ActionForward(backUrl, true);
 289  
     }
 290  
     
 291  
     /**
 292  
      * This method prepares to export results.  Note: this method will not look for any rows selected since the last page view, so it is best
 293  
      * that exporting opens in a new browser window.
 294  
      * 
 295  
      * @param mapping
 296  
      * @param form must be an instance of MultipleValueLookupForm
 297  
      * @param request
 298  
      * @param response
 299  
      * @return
 300  
      * @throws Exception
 301  
      */
 302  
     public ActionForward export(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
 303  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 304  0
         List<ResultRow> resultTable = prepareToExport(multipleValueLookupForm);
 305  0
         request.setAttribute("reqSearchResults", resultTable);
 306  0
         return mapping.findForward(RiceConstants.MAPPING_BASIC);
 307  
     }
 308  
     
 309  
     /**
 310  
      * This method performs the lookup and returns a collection of lookup items.  Also initializes values in the form
 311  
      * that will allow the multiple value lookup page to render
 312  
      * 
 313  
      * @param multipleValueLookupForm
 314  
      * @param resultTable a list of result rows (used to generate what's shown in the UI).  This list will be modified by this method
 315  
      * @param maxRowsPerPage
 316  
      * @param bounded whether the results will be bounded
 317  
      * @return the list of result BOs, possibly bounded by size
 318  
      */
 319  
     protected Collection performMultipleValueLookup(MultipleValueLookupForm multipleValueLookupForm, List<ResultRow> resultTable, int maxRowsPerPage, boolean bounded) {
 320  0
         Lookupable lookupable = multipleValueLookupForm.getLookupable();
 321  0
         Collection displayList = lookupable.performLookup(multipleValueLookupForm, resultTable, bounded);
 322  
         
 323  0
         List defaultSortColumns = lookupable.getDefaultSortColumns();
 324  0
         if (defaultSortColumns != null && !defaultSortColumns.isEmpty() && resultTable != null && !resultTable.isEmpty()) {
 325  
             // there's a default sort order, just find the first sort column, and we can't go wrong
 326  0
             String firstSortColumn = (String) defaultSortColumns.get(0);
 327  
             
 328  
             // go thru the first result row to find the index of the column (more efficient than calling lookupable.getColumns since we don't have to recreate column list)
 329  0
             int firstSortColumnIdx = -1;
 330  0
             List<Column> columnsForFirstResultRow = resultTable.get(0).getColumns();
 331  0
             for (int i = 0; i < columnsForFirstResultRow.size(); i++) {
 332  0
                 if (StringUtils.equals(firstSortColumn, columnsForFirstResultRow.get(i).getPropertyName())) {
 333  0
                     firstSortColumnIdx = i;
 334  0
                     break;
 335  
                 }
 336  
             }
 337  0
             multipleValueLookupForm.setColumnToSortIndex(firstSortColumnIdx);
 338  0
         }
 339  
         else {
 340  
             // don't know how results were sorted, so we just say -1
 341  0
             multipleValueLookupForm.setColumnToSortIndex(-1);
 342  
         }
 343  
         
 344  
         // we just performed the lookup, so we're on the first page (indexed from 0)
 345  0
         multipleValueLookupForm.jumpToFirstPage(resultTable.size(), maxRowsPerPage);
 346  
         
 347  0
         SequenceAccessorService sas = KRADServiceLocator.getSequenceAccessorService();
 348  0
         Long nextSeq = sas.getNextAvailableSequenceNumber(KRADConstants.LOOKUP_RESULTS_SEQUENCE);
 349  0
         String lookupResultsSequenceNumber = nextSeq.toString();
 350  0
         multipleValueLookupForm.setLookupResultsSequenceNumber(lookupResultsSequenceNumber);
 351  
         try {
 352  0
             LookupResultsService lookupResultsService = KRADServiceLocatorWeb.getLookupResultsService();
 353  0
             lookupResultsService.persistResultsTable(lookupResultsSequenceNumber, resultTable,
 354  
                     GlobalVariables.getUserSession().getPerson().getPrincipalId());
 355  
         }
 356  0
         catch (Exception e) {
 357  0
             LOG.error("error occured trying to persist multiple lookup results", e);
 358  0
             throw new RuntimeException("error occured trying to persist multiple lookup results");
 359  0
         }
 360  
         
 361  
         // since new search, nothing's checked
 362  0
         multipleValueLookupForm.setCompositeObjectIdMap(new HashMap<String, String>());
 363  
         
 364  0
         return displayList;
 365  
     }
 366  
     
 367  
     /**
 368  
      * This method performs the operations necessary for a multiple value lookup to switch to another page of results and rerender the page
 369  
      * @param multipleValueLookupForm
 370  
      * @param maxRowsPerPage
 371  
      * @return a list of result rows, used by the UI to render the page
 372  
      */
 373  
     protected List<ResultRow> switchToPage(MultipleValueLookupForm multipleValueLookupForm, int maxRowsPerPage) {
 374  0
         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
 375  
         
 376  0
         List<ResultRow> resultTable = null;
 377  
         try {
 378  0
             resultTable = KRADServiceLocatorWeb.getLookupResultsService().retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
 379  
         }
 380  0
         catch (Exception e) {
 381  0
             LOG.error("error occured trying to retrieve multiple lookup results", e);
 382  0
             throw new RuntimeException("error occured trying to retrieve multiple lookup results");
 383  0
         }
 384  
         
 385  0
         multipleValueLookupForm.jumpToPage(multipleValueLookupForm.getSwitchToPageNumber(), resultTable.size(), maxRowsPerPage);
 386  
         
 387  0
         multipleValueLookupForm.setColumnToSortIndex(Integer.parseInt(multipleValueLookupForm.getPreviouslySortedColumnIndex()));
 388  0
         multipleValueLookupForm.setCompositeObjectIdMap(LookupUtils.generateCompositeSelectedObjectIds(multipleValueLookupForm.getPreviouslySelectedObjectIdSet(),
 389  
                 multipleValueLookupForm.getDisplayedObjectIdSet(), multipleValueLookupForm.getSelectedObjectIdSet()));
 390  0
         return resultTable;
 391  
     }
 392  
     
 393  
     /**
 394  
      * This method performs the operations necessary for a multiple value lookup to sort results and rerender the page
 395  
      * 
 396  
      * @param multipleValueLookupForm
 397  
      * @param maxRowsPerPage
 398  
      * @return a list of result rows, used by the UI to render the page
 399  
      */
 400  
     protected List<ResultRow> sort(MultipleValueLookupForm multipleValueLookupForm, int maxRowsPerPage) {
 401  0
         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
 402  
         
 403  0
         LookupResultsService lookupResultsService = KRADServiceLocatorWeb.getLookupResultsService();
 404  
         
 405  0
         List<ResultRow> resultTable = null;
 406  
         try {
 407  0
             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
 408  
         }
 409  0
         catch (Exception e) {
 410  0
             LOG.error("error occured trying to retrieve multiple lookup results", e);
 411  0
             throw new RuntimeException("error occured trying to retrieve multiple lookup results");
 412  0
         }
 413  
         
 414  0
         int columnToSortOn = multipleValueLookupForm.getColumnToSortIndex();
 415  0
         int columnCurrentlySortedOn = Integer.parseInt(multipleValueLookupForm.getPreviouslySortedColumnIndex());
 416  
         
 417  
         // if columnCurrentlySortedOn is -1, that means that we don't know which column we were originally sorting on
 418  
         // after a search, it's hard to tell which of the columns we're sorted on,
 419  
         
 420  0
         if (columnToSortOn == columnCurrentlySortedOn) {
 421  
             // we're already sorted on the same column that the user clicked on, so we reverse the list
 422  0
             Collections.reverse(resultTable);
 423  
         }
 424  
         else {
 425  
             // sorting on a different column, so we have to sort
 426  
             
 427  
             // HACK ALERT for findBestValueComparatorForColumn, since there's no central place to know
 428  
             // which comparator we should use to compare values in a column
 429  0
             Collections.sort(resultTable, new BeanComparator("columns[" + columnToSortOn + "].propertyValue", LookupUtils.findBestValueComparatorForColumn(resultTable, columnToSortOn)));
 430  
         }
 431  
         
 432  
         // repersist the list
 433  
         try {
 434  0
             lookupResultsService.persistResultsTable(lookupResultsSequenceNumber, resultTable, 
 435  
                     GlobalVariables.getUserSession().getPerson().getPrincipalId());
 436  
         }
 437  0
         catch (Exception e) {
 438  0
             LOG.error("error occured trying to persist multiple lookup results", e);
 439  0
             throw new RuntimeException("error occured trying to persist multiple lookup results");
 440  0
         }
 441  
         
 442  
         // we just performed the sort, so go back to first page
 443  0
         multipleValueLookupForm.jumpToFirstPage(resultTable.size(), maxRowsPerPage);
 444  
     
 445  0
         multipleValueLookupForm.setCompositeObjectIdMap(LookupUtils.generateCompositeSelectedObjectIds(multipleValueLookupForm.getPreviouslySelectedObjectIdSet(),
 446  
                 multipleValueLookupForm.getDisplayedObjectIdSet(), multipleValueLookupForm.getSelectedObjectIdSet()));
 447  0
         return resultTable;
 448  
     }
 449  
     
 450  
     /**
 451  
      * This method performs the operations necessary for a multiple value lookup keep track of which results have been selected to be returned
 452  
      * to the calling document.  Note, this method does not actually requery for the results.
 453  
      * 
 454  
      * @param multipleValueLookupForm
 455  
      */
 456  
     protected void prepareToReturnSelectedResultBOs(MultipleValueLookupForm multipleValueLookupForm) {
 457  0
         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
 458  0
         if (StringUtils.isBlank(lookupResultsSequenceNumber)) {
 459  
             // pressed return before searching
 460  0
             return;
 461  
         }
 462  0
         Map<String, String> compositeObjectIdMap = LookupUtils.generateCompositeSelectedObjectIds(multipleValueLookupForm.getPreviouslySelectedObjectIdSet(),
 463  
                 multipleValueLookupForm.getDisplayedObjectIdSet(), multipleValueLookupForm.getSelectedObjectIdSet());
 464  0
         Set<String> compositeObjectIds = compositeObjectIdMap.keySet();
 465  
         try {
 466  0
             LookupResultsService lookupResultsService = KRADServiceLocatorWeb.getLookupResultsService();
 467  0
             lookupResultsService.persistSelectedObjectIds(lookupResultsSequenceNumber, compositeObjectIds,
 468  
                     GlobalVariables.getUserSession().getPerson().getPrincipalId());
 469  
         }
 470  0
         catch (Exception e) {
 471  0
             LOG.error("error occured trying to retrieve selected multiple lookup results", e);
 472  0
             throw new RuntimeException("error occured trying to retrieve selected multiple lookup results");
 473  0
         }
 474  0
     }
 475  
     
 476  
     /**
 477  
      * This method performs the operations necessary for a multiple value lookup to return no results to the calling page
 478  
      * 
 479  
      * @param multipleValueLookupForm
 480  
      */
 481  
     protected void prepareToReturnNone(MultipleValueLookupForm multipleValueLookupForm) {
 482  0
         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
 483  
         try {
 484  0
             if (StringUtils.isNotBlank(lookupResultsSequenceNumber)) {
 485  
                 // we're returning nothing, so we try to get rid of stuff
 486  0
                 LookupResultsService lookupResultsService = KRADServiceLocatorWeb.getLookupResultsService();
 487  0
                 lookupResultsService.clearPersistedLookupResults(lookupResultsSequenceNumber);
 488  0
                 multipleValueLookupForm.setLookupResultsSequenceNumber(null);
 489  
             }
 490  
         }
 491  0
         catch (Exception e) {
 492  
             // not a big deal, continue on and purge w/ a batch job
 493  0
             LOG.error("error occured trying to clear lookup results seq nbr " + lookupResultsSequenceNumber, e);
 494  0
         }
 495  0
     }
 496  
     
 497  
     /**
 498  
      * This method performs the operations necessary for a multiple value lookup to export the rows via display tag
 499  
      * 
 500  
      * Note: this method assumes that the export will be opened in a new browser window, therefore, persisting the selected
 501  
      * checkboxes will not be needed.
 502  
      * 
 503  
      * @param multipleValueLookupForm
 504  
      * @return a list of result rows, to be used by display tag to render the results
 505  
      */
 506  
     protected List<ResultRow> prepareToExport(MultipleValueLookupForm multipleValueLookupForm) {
 507  0
         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
 508  
         
 509  0
         List<ResultRow> resultTable = null;
 510  
         try {
 511  0
             LookupResultsService lookupResultsService = KRADServiceLocatorWeb.getLookupResultsService();
 512  0
             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
 513  
         }
 514  0
         catch (Exception e) {
 515  0
             LOG.error("error occured trying to export multiple lookup results", e);
 516  0
             throw new RuntimeException("error occured trying to export multiple lookup results");
 517  0
         }
 518  0
         return resultTable;
 519  
     }
 520  
     
 521  
     
 522  
     /**
 523  
      * This method performs the operations necessary for a multiple value lookup to select all of the results and rerender the page
 524  
      * @param multipleValueLookupForm
 525  
      * @param maxRowsPerPage
 526  
      * @return a list of result rows, used by the UI to render the page
 527  
      */
 528  
     protected List<ResultRow> selectAll(MultipleValueLookupForm multipleValueLookupForm, int maxRowsPerPage) {
 529  0
         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
 530  
         
 531  0
         List<ResultRow> resultTable = null;
 532  
         try {
 533  0
             LookupResultsService lookupResultsService = KRADServiceLocatorWeb.getLookupResultsService();
 534  0
             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
 535  
         }
 536  0
         catch (Exception e) {
 537  0
             LOG.error("error occured trying to export multiple lookup results", e);
 538  0
             throw new RuntimeException("error occured trying to export multiple lookup results");
 539  0
         }
 540  
         
 541  0
         Map<String, String> selectedObjectIds = new HashMap<String, String>();
 542  0
         for (ResultRow row : resultTable) {
 543  0
             String objId = row.getObjectId();
 544  0
             InputHtmlData returnUrl = (InputHtmlData) row.getReturnUrlHtmlData();
 545  0
             returnUrl.setChecked(InputHtmlData.CHECKBOX_CHECKED_VALUE);
 546  0
             row.setReturnUrl(returnUrl.constructCompleteHtmlTag());
 547  0
             if(objId != null){
 548  0
                     selectedObjectIds.put(objId, objId);
 549  
             }
 550  0
         }
 551  
         
 552  0
         multipleValueLookupForm.jumpToPage(multipleValueLookupForm.getViewedPageNumber(), resultTable.size(), maxRowsPerPage);
 553  0
         multipleValueLookupForm.setColumnToSortIndex(Integer.parseInt(multipleValueLookupForm.getPreviouslySortedColumnIndex()));
 554  0
         multipleValueLookupForm.setCompositeObjectIdMap(selectedObjectIds);
 555  
         
 556  0
         return resultTable;
 557  
     }
 558  
     
 559  
     @Override
 560  
     public ActionForward clearValues(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
 561  0
         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
 562  
         
 563  
         // call the following methods to clear the persisted results
 564  0
         prepareToReturnNone(multipleValueLookupForm);
 565  
         
 566  0
         return super.clearValues(mapping, form, request, response);
 567  
     }
 568  
 
 569  
     /**
 570  
      * This method performs the operations necessary for a multiple value lookup to unselect all of the results and rerender the page
 571  
      * @param multipleValueLookupForm
 572  
      * @param maxRowsPerPage
 573  
      * @return a list of result rows, used by the UI to render the page
 574  
      */
 575  
     protected List<ResultRow> unselectAll(MultipleValueLookupForm multipleValueLookupForm, int maxRowsPerPage) {
 576  0
         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
 577  
         
 578  0
         List<ResultRow> resultTable = null;
 579  
         try {
 580  0
             LookupResultsService lookupResultsService = KRADServiceLocatorWeb.getLookupResultsService();
 581  0
             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
 582  
         }
 583  0
         catch (Exception e) {
 584  0
             LOG.error("error occured trying to export multiple lookup results", e);
 585  0
             throw new RuntimeException("error occured trying to export multiple lookup results");
 586  0
         }
 587  
         
 588  0
         Map<String, String> selectedObjectIds = new HashMap<String, String>();
 589  
         // keep map empty since we're not selecting anything
 590  
         
 591  0
         multipleValueLookupForm.jumpToPage(multipleValueLookupForm.getViewedPageNumber(), resultTable.size(), maxRowsPerPage);
 592  0
         multipleValueLookupForm.setColumnToSortIndex(Integer.parseInt(multipleValueLookupForm.getPreviouslySortedColumnIndex()));
 593  0
         multipleValueLookupForm.setCompositeObjectIdMap(selectedObjectIds);
 594  
         
 595  0
         return resultTable;
 596  
     }
 597  
 
 598  
     /**
 599  
      * This method computes the max number of rows that should be rendered per page for a multiple value lookup.
 600  
      * 
 601  
      * This method first looks for an application parameter in FS_PARM_T, group SYSTEM, multipleValueLookupResultsPerPage
 602  
      * 
 603  
      * if someone wants to implement something where a user can decide how many results to display per page, 
 604  
      * this method is the place to do it.  Make this method read form values to determine the max rows per page based on the user inputs
 605  
      * 
 606  
      * @see org.kuali.rice.krad.util.KRADConstants.SystemGroupParameterNames#MULTIPLE_VALUE_LOOKUP_RESULTS_PER_PAGE
 607  
      * @see #DEFAULT_MAX_ROWS_PER_PAGE
 608  
      * @param multipleValueLookupForm the form
 609  
      * @return
 610  
      */
 611  
     protected int getMaxRowsPerPage(MultipleValueLookupForm multipleValueLookupForm) {
 612  0
         Integer appMaxRowsPerPage = LookupUtils.getApplicationMaximumSearchResulsPerPageForMultipleValueLookups();
 613  0
         if (appMaxRowsPerPage == null) {
 614  0
             LOG.warn("Couldn't find application results per page for MV lookups.  Using default of " + DEFAULT_MAX_ROWS_PER_PAGE);
 615  0
             appMaxRowsPerPage = new Integer(DEFAULT_MAX_ROWS_PER_PAGE);
 616  
         }
 617  0
         return appMaxRowsPerPage;
 618  
     }
 619  
 }
 620