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