001/**
002 * Copyright 2005-2015 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.kuali.rice.kns.web.struts.action;
017
018import org.apache.commons.beanutils.BeanComparator;
019import org.apache.commons.lang.StringUtils;
020import org.apache.struts.action.ActionForm;
021import org.apache.struts.action.ActionForward;
022import org.apache.struts.action.ActionMapping;
023import org.kuali.rice.core.api.util.RiceConstants;
024import org.kuali.rice.kns.lookup.HtmlData;
025import org.kuali.rice.kns.lookup.LookupResultsService;
026import org.kuali.rice.kns.lookup.LookupUtils;
027import org.kuali.rice.kns.lookup.Lookupable;
028import org.kuali.rice.kns.service.KNSServiceLocator;
029import org.kuali.rice.kns.web.struts.form.MultipleValueLookupForm;
030import org.kuali.rice.kns.web.ui.Column;
031import org.kuali.rice.kns.web.ui.ResultRow;
032import org.kuali.rice.krad.lookup.CollectionIncomplete;
033import org.kuali.rice.krad.service.KRADServiceLocator;
034import org.kuali.rice.krad.service.SequenceAccessorService;
035import org.kuali.rice.krad.util.GlobalVariables;
036import org.kuali.rice.krad.util.KRADConstants;
037import org.kuali.rice.krad.util.UrlFactory;
038
039import javax.servlet.ServletException;
040import javax.servlet.http.HttpServletRequest;
041import javax.servlet.http.HttpServletResponse;
042import java.io.IOException;
043import java.util.ArrayList;
044import java.util.Collection;
045import java.util.Collections;
046import java.util.HashMap;
047import java.util.List;
048import java.util.Map;
049import java.util.Properties;
050import java.util.Set;
051
052/**
053 * This class serves as the struts action for implementing multiple value lookups
054 *
055 * @deprecated KNS Struts deprecated, use KRAD and the Spring MVC framework.
056 */
057@Deprecated
058public class KualiMultipleValueLookupAction extends KualiLookupAction implements KualiTableRenderAction {
059    private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiMultipleValueLookupAction.class);
060
061    /**
062     * If there is no app param defined for the # rows/page, then this value
063     * will be used for the default
064     * 
065     * @see KualiMultipleValueLookupAction#getMaxRowsPerPage(MultipleValueLookupForm)
066     */
067    public static final int DEFAULT_MAX_ROWS_PER_PAGE = 50;
068
069
070    /**
071     * This method performs the search, and will be responsible for persisting the results via the LookupResultsService.
072     * This overrides the superclass's search action method b/c of the differences in how the results are generated and it populates
073     * certain attributes that are specific to MultipleValueLookupForm
074     * 
075     * @param mapping
076     * @param form must be an instance of MultipleValueLookupForm
077     * @param request
078     * @param response 
079     */
080    @Override
081    public ActionForward search(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
082        MultipleValueLookupForm multipleValueLookupForm = (MultipleValueLookupForm) form;
083
084        // If this is a new search, clear out the old search results.
085        String methodToCall = findMethodToCall(form, request);
086        if (methodToCall.equalsIgnoreCase("search")) {
087            GlobalVariables.getUserSession().removeObjectsByPrefix(KRADConstants.SEARCH_METHOD);
088        }
089
090        Lookupable kualiLookupable = multipleValueLookupForm.getLookupable();
091        if (kualiLookupable == null) {
092            LOG.error("Lookupable is null.");
093            throw new RuntimeException("Lookupable is null.");
094        }
095
096        Collection displayList = new ArrayList();
097        ArrayList<ResultRow> resultTable = new ArrayList<ResultRow>();
098
099        // 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