View Javadoc

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  public class KualiMultipleValueLookupAction extends KualiLookupAction implements KualiTableRenderAction {
56      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          MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
80          
81          // If this is a new search, clear out the old search results.
82      	String methodToCall = findMethodToCall(form, request);
83  		if (methodToCall.equalsIgnoreCase("search")) {
84  			GlobalVariables.getUserSession().removeObjectsByPrefix(KNSConstants.SEARCH_METHOD);
85  		}
86  		
87          Lookupable kualiLookupable = multipleValueLookupForm.getLookupable();
88          if (kualiLookupable == null) {
89              LOG.error("Lookupable is null.");
90              throw new RuntimeException("Lookupable is null.");
91          }
92          
93          Collection displayList = new ArrayList();
94          List<ResultRow> resultTable = new ArrayList<ResultRow>();
95  
96          // validate search parameters
97          kualiLookupable.validateSearchParameters(multipleValueLookupForm.getFields());
98  
99          boolean bounded = true;
100 
101         displayList = performMultipleValueLookup(multipleValueLookupForm, resultTable, getMaxRowsPerPage(multipleValueLookupForm), bounded);
102         if (kualiLookupable.isSearchUsingOnlyPrimaryKeyValues()) {
103             multipleValueLookupForm.setSearchUsingOnlyPrimaryKeyValues(true);
104             multipleValueLookupForm.setPrimaryKeyFieldLabels(kualiLookupable.getPrimaryKeyFieldLabels());
105         }
106         else {
107             multipleValueLookupForm.setSearchUsingOnlyPrimaryKeyValues(false);
108             multipleValueLookupForm.setPrimaryKeyFieldLabels(KNSConstants.EMPTY_STRING);
109         }
110         
111         //request.setAttribute("reqSearchResultsActualSize", ((CollectionIncomplete) displayList).getActualSizeIfTruncated());
112         
113         if ( displayList instanceof CollectionIncomplete ){
114             request.setAttribute("reqSearchResultsActualSize", ((CollectionIncomplete) displayList).getActualSizeIfTruncated());
115         } else {
116             request.setAttribute("reqSearchResultsActualSize", displayList.size() );
117         }
118         
119         request.setAttribute("reqSearchResults", resultTable);
120         
121         //multipleValueLookupForm.setResultsActualSize((int) ((CollectionIncomplete) displayList).getActualSizeIfTruncated().longValue());
122         
123         if ( displayList instanceof CollectionIncomplete ){
124         	multipleValueLookupForm.setResultsActualSize((int) ((CollectionIncomplete) displayList).getActualSizeIfTruncated().longValue());    
125         } else {
126         	multipleValueLookupForm.setResultsActualSize(displayList.size()); 
127         }
128         
129         
130         multipleValueLookupForm.setResultsLimitedSize(resultTable.size());
131 
132         if (request.getParameter(KNSConstants.SEARCH_LIST_REQUEST_KEY) != null) {
133             GlobalVariables.getUserSession().removeObject(request.getParameter(KNSConstants.SEARCH_LIST_REQUEST_KEY));
134         }
135         request.setAttribute(KNSConstants.SEARCH_LIST_REQUEST_KEY, GlobalVariables.getUserSession().addObject(resultTable, KNSConstants.SEARCH_LIST_KEY_PREFIX));
136 
137         String refreshCaller = request.getParameter(KNSConstants.REFRESH_CALLER);
138 
139         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         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
154         List<ResultRow> resultTable = switchToPage(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
155         request.setAttribute("reqSearchResults", resultTable);
156         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         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
176         List<ResultRow> resultTable = sort(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
177         request.setAttribute("reqSearchResults", resultTable);
178         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         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
193         if (StringUtils.isBlank(multipleValueLookupForm.getLookupResultsSequenceNumber())) {
194             // no search was executed
195             return prepareToReturnNone(mapping, form, request, response);
196         }
197         
198         prepareToReturnSelectedResultBOs(multipleValueLookupForm);
199         
200         // build the parameters for the refresh url
201         Properties parameters = new Properties();
202         parameters.put(KNSConstants.LOOKUP_RESULTS_BO_CLASS_NAME, multipleValueLookupForm.getBusinessObjectClassName());
203         parameters.put(KNSConstants.LOOKUP_RESULTS_SEQUENCE_NUMBER, multipleValueLookupForm.getLookupResultsSequenceNumber());
204         parameters.put(KNSConstants.DOC_FORM_KEY, multipleValueLookupForm.getFormKey());
205         parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, KNSConstants.RETURN_METHOD_TO_CALL);
206         parameters.put(KNSConstants.REFRESH_CALLER, KNSConstants.MULTIPLE_VALUE);
207         parameters.put(KNSConstants.ANCHOR, multipleValueLookupForm.getLookupAnchor());
208         parameters.put(KNSConstants.LOOKED_UP_COLLECTION_NAME, multipleValueLookupForm.getLookedUpCollectionName());
209         if(multipleValueLookupForm.getDocNum() != null){
210         	parameters.put(KNSConstants.DOC_NUM, multipleValueLookupForm.getDocNum());
211         }
212 
213 
214         String backUrl = UrlFactory.parameterizeUrl(multipleValueLookupForm.getBackLocation(), parameters);
215         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         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
229         List<ResultRow> resultTable = selectAll(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
230         request.setAttribute("reqSearchResults", resultTable);
231         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         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
246         List<ResultRow> resultTable = unselectAll(multipleValueLookupForm, getMaxRowsPerPage(multipleValueLookupForm));
247         request.setAttribute("reqSearchResults", resultTable);
248         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         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         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
273         prepareToReturnNone(multipleValueLookupForm);
274         
275         // build the parameters for the refresh url
276         Properties parameters = new Properties();
277         parameters.put(KNSConstants.DOC_FORM_KEY, multipleValueLookupForm.getFormKey());
278         parameters.put(KNSConstants.DISPATCH_REQUEST_PARAMETER, KNSConstants.RETURN_METHOD_TO_CALL);
279         parameters.put(KNSConstants.REFRESH_CALLER, KNSConstants.MULTIPLE_VALUE);
280         parameters.put(KNSConstants.ANCHOR, multipleValueLookupForm.getLookupAnchor());
281         if(multipleValueLookupForm.getDocNum() != null){
282         	parameters.put(KNSConstants.DOC_NUM, multipleValueLookupForm.getDocNum());
283         }
284         String backUrl = UrlFactory.parameterizeUrl(multipleValueLookupForm.getBackLocation(), parameters);
285         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         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
301         List<ResultRow> resultTable = prepareToExport(multipleValueLookupForm);
302         request.setAttribute("reqSearchResults", resultTable);
303         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         Lookupable lookupable = multipleValueLookupForm.getLookupable();
318         Collection displayList = lookupable.performLookup(multipleValueLookupForm, resultTable, bounded);
319         
320         List defaultSortColumns = lookupable.getDefaultSortColumns();
321         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             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             int firstSortColumnIdx = -1;
327             List<Column> columnsForFirstResultRow = resultTable.get(0).getColumns();
328             for (int i = 0; i < columnsForFirstResultRow.size(); i++) {
329                 if (StringUtils.equals(firstSortColumn, columnsForFirstResultRow.get(i).getPropertyName())) {
330                     firstSortColumnIdx = i;
331                     break;
332                 }
333             }
334             multipleValueLookupForm.setColumnToSortIndex(firstSortColumnIdx);
335         }
336         else {
337             // don't know how results were sorted, so we just say -1
338             multipleValueLookupForm.setColumnToSortIndex(-1);
339         }
340         
341         // we just performed the lookup, so we're on the first page (indexed from 0)
342         multipleValueLookupForm.jumpToFirstPage(resultTable.size(), maxRowsPerPage);
343         
344         SequenceAccessorService sas = KNSServiceLocator.getSequenceAccessorService();
345         Long nextSeq = sas.getNextAvailableSequenceNumber(KNSConstants.LOOKUP_RESULTS_SEQUENCE); 
346         String lookupResultsSequenceNumber = nextSeq.toString();
347         multipleValueLookupForm.setLookupResultsSequenceNumber(lookupResultsSequenceNumber);
348         try {
349             LookupResultsService lookupResultsService = KNSServiceLocator.getLookupResultsService();
350             lookupResultsService.persistResultsTable(lookupResultsSequenceNumber, resultTable,
351                     GlobalVariables.getUserSession().getPerson().getPrincipalId());
352         }
353         catch (Exception e) {
354             LOG.error("error occured trying to persist multiple lookup results", e);
355             throw new RuntimeException("error occured trying to persist multiple lookup results");
356         }
357         
358         // since new search, nothing's checked
359         multipleValueLookupForm.setCompositeObjectIdMap(new HashMap<String, String>());
360         
361         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         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
372         
373         List<ResultRow> resultTable = null;
374         try {
375             resultTable = KNSServiceLocator.getLookupResultsService().retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
376         }
377         catch (Exception e) {
378             LOG.error("error occured trying to retrieve multiple lookup results", e);
379             throw new RuntimeException("error occured trying to retrieve multiple lookup results");
380         }
381         
382         multipleValueLookupForm.jumpToPage(multipleValueLookupForm.getSwitchToPageNumber(), resultTable.size(), maxRowsPerPage);
383         
384         multipleValueLookupForm.setColumnToSortIndex(Integer.parseInt(multipleValueLookupForm.getPreviouslySortedColumnIndex()));
385         multipleValueLookupForm.setCompositeObjectIdMap(LookupUtils.generateCompositeSelectedObjectIds(multipleValueLookupForm.getPreviouslySelectedObjectIdSet(),
386                 multipleValueLookupForm.getDisplayedObjectIdSet(), multipleValueLookupForm.getSelectedObjectIdSet()));
387         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         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
399         
400         LookupResultsService lookupResultsService = KNSServiceLocator.getLookupResultsService();
401         
402         List<ResultRow> resultTable = null;
403         try {
404             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
405         }
406         catch (Exception e) {
407             LOG.error("error occured trying to retrieve multiple lookup results", e);
408             throw new RuntimeException("error occured trying to retrieve multiple lookup results");
409         }
410         
411         int columnToSortOn = multipleValueLookupForm.getColumnToSortIndex();
412         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         if (columnToSortOn == columnCurrentlySortedOn) {
418             // we're already sorted on the same column that the user clicked on, so we reverse the list
419             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             Collections.sort(resultTable, new BeanComparator("columns[" + columnToSortOn + "].propertyValue", LookupUtils.findBestValueComparatorForColumn(resultTable, columnToSortOn)));
427         }
428         
429         // repersist the list
430         try {
431             lookupResultsService.persistResultsTable(lookupResultsSequenceNumber, resultTable, 
432                     GlobalVariables.getUserSession().getPerson().getPrincipalId());
433         }
434         catch (Exception e) {
435             LOG.error("error occured trying to persist multiple lookup results", e);
436             throw new RuntimeException("error occured trying to persist multiple lookup results");
437         }
438         
439         // we just performed the sort, so go back to first page
440         multipleValueLookupForm.jumpToFirstPage(resultTable.size(), maxRowsPerPage);
441     
442         multipleValueLookupForm.setCompositeObjectIdMap(LookupUtils.generateCompositeSelectedObjectIds(multipleValueLookupForm.getPreviouslySelectedObjectIdSet(),
443                 multipleValueLookupForm.getDisplayedObjectIdSet(), multipleValueLookupForm.getSelectedObjectIdSet()));
444         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         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
455         if (StringUtils.isBlank(lookupResultsSequenceNumber)) {
456             // pressed return before searching
457             return;
458         }
459         Map<String, String> compositeObjectIdMap = LookupUtils.generateCompositeSelectedObjectIds(multipleValueLookupForm.getPreviouslySelectedObjectIdSet(),
460                 multipleValueLookupForm.getDisplayedObjectIdSet(), multipleValueLookupForm.getSelectedObjectIdSet());
461         Set<String> compositeObjectIds = compositeObjectIdMap.keySet();
462         try {
463             LookupResultsService lookupResultsService = KNSServiceLocator.getLookupResultsService();
464             lookupResultsService.persistSelectedObjectIds(lookupResultsSequenceNumber, compositeObjectIds,
465                     GlobalVariables.getUserSession().getPerson().getPrincipalId());
466         }
467         catch (Exception e) {
468             LOG.error("error occured trying to retrieve selected multiple lookup results", e);
469             throw new RuntimeException("error occured trying to retrieve selected multiple lookup results");
470         }
471     }
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         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
480         try {
481             if (StringUtils.isNotBlank(lookupResultsSequenceNumber)) {
482                 // we're returning nothing, so we try to get rid of stuff
483                 LookupResultsService lookupResultsService = KNSServiceLocator.getLookupResultsService();
484                 lookupResultsService.clearPersistedLookupResults(lookupResultsSequenceNumber);
485                 multipleValueLookupForm.setLookupResultsSequenceNumber(null);
486             }
487         }
488         catch (Exception e) {
489             // not a big deal, continue on and purge w/ a batch job
490             LOG.error("error occured trying to clear lookup results seq nbr " + lookupResultsSequenceNumber, e);
491         }
492     }
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         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
505         
506         List<ResultRow> resultTable = null;
507         try {
508             LookupResultsService lookupResultsService = KNSServiceLocator.getLookupResultsService();
509             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
510         }
511         catch (Exception e) {
512             LOG.error("error occured trying to export multiple lookup results", e);
513             throw new RuntimeException("error occured trying to export multiple lookup results");
514         }
515         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         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
527         
528         List<ResultRow> resultTable = null;
529         try {
530             LookupResultsService lookupResultsService = KNSServiceLocator.getLookupResultsService();
531             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
532         }
533         catch (Exception e) {
534             LOG.error("error occured trying to export multiple lookup results", e);
535             throw new RuntimeException("error occured trying to export multiple lookup results");
536         }
537         
538         Map<String, String> selectedObjectIds = new HashMap<String, String>();
539         for (ResultRow row : resultTable) {
540             String objId = row.getObjectId();
541             InputHtmlData returnUrl = (InputHtmlData) row.getReturnUrlHtmlData();
542             returnUrl.setChecked(InputHtmlData.CHECKBOX_CHECKED_VALUE);
543             row.setReturnUrl(returnUrl.constructCompleteHtmlTag());
544             if(objId != null){
545             	selectedObjectIds.put(objId, objId);
546             }
547         }
548         
549         multipleValueLookupForm.jumpToPage(multipleValueLookupForm.getViewedPageNumber(), resultTable.size(), maxRowsPerPage);
550         multipleValueLookupForm.setColumnToSortIndex(Integer.parseInt(multipleValueLookupForm.getPreviouslySortedColumnIndex()));
551         multipleValueLookupForm.setCompositeObjectIdMap(selectedObjectIds);
552         
553         return resultTable;
554     }
555     
556     @Override
557     public ActionForward clearValues(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
558         MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
559         
560         // call the following methods to clear the persisted results
561         prepareToReturnNone(multipleValueLookupForm);
562         
563         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         String lookupResultsSequenceNumber = multipleValueLookupForm.getLookupResultsSequenceNumber();
574         
575         List<ResultRow> resultTable = null;
576         try {
577             LookupResultsService lookupResultsService = KNSServiceLocator.getLookupResultsService();
578             resultTable = lookupResultsService.retrieveResultsTable(lookupResultsSequenceNumber, GlobalVariables.getUserSession().getPerson().getPrincipalId());
579         }
580         catch (Exception e) {
581             LOG.error("error occured trying to export multiple lookup results", e);
582             throw new RuntimeException("error occured trying to export multiple lookup results");
583         }
584         
585         Map<String, String> selectedObjectIds = new HashMap<String, String>();
586         // keep map empty since we're not selecting anything
587         
588         multipleValueLookupForm.jumpToPage(multipleValueLookupForm.getViewedPageNumber(), resultTable.size(), maxRowsPerPage);
589         multipleValueLookupForm.setColumnToSortIndex(Integer.parseInt(multipleValueLookupForm.getPreviouslySortedColumnIndex()));
590         multipleValueLookupForm.setCompositeObjectIdMap(selectedObjectIds);
591         
592         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         Integer appMaxRowsPerPage = LookupUtils.getApplicationMaximumSearchResulsPerPageForMultipleValueLookups();
610         if (appMaxRowsPerPage == null) {
611             LOG.warn("Couldn't find application results per page for MV lookups.  Using default of " + DEFAULT_MAX_ROWS_PER_PAGE);
612             appMaxRowsPerPage = new Integer(DEFAULT_MAX_ROWS_PER_PAGE);
613         }
614         return appMaxRowsPerPage;
615     }
616 }
617