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