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