001/*
002 * Copyright 2008 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.ole.pdp.web.struts;
017
018import java.text.MessageFormat;
019import java.util.List;
020import java.util.Properties;
021
022import javax.servlet.http.HttpServletRequest;
023import javax.servlet.http.HttpServletResponse;
024
025import org.apache.commons.lang.StringUtils;
026import org.apache.struts.action.ActionForm;
027import org.apache.struts.action.ActionForward;
028import org.apache.struts.action.ActionMapping;
029import org.kuali.ole.pdp.PdpKeyConstants;
030import org.kuali.ole.pdp.PdpParameterConstants;
031import org.kuali.ole.pdp.PdpPropertyConstants;
032import org.kuali.ole.pdp.businessobject.Batch;
033import org.kuali.ole.pdp.service.BatchMaintenanceService;
034import org.kuali.ole.pdp.util.PdpBatchQuestionCallback;
035import org.kuali.ole.sys.OLEConstants;
036import org.kuali.ole.sys.context.SpringContext;
037import org.kuali.rice.core.api.config.property.ConfigurationService;
038import org.kuali.rice.kim.api.identity.Person;
039import org.kuali.rice.kns.question.ConfirmationQuestion;
040import org.kuali.rice.kns.web.struts.action.KualiAction;
041import org.kuali.rice.krad.util.ErrorMessage;
042import org.kuali.rice.krad.util.GlobalVariables;
043import org.kuali.rice.krad.util.KRADConstants;
044import org.kuali.rice.krad.util.MessageMap;
045import org.kuali.rice.krad.util.UrlFactory;
046
047/**
048 * This class defines actions for Batch (cancel, hold, remove hold).
049 */
050public class BatchAction extends KualiAction {
051
052    private BatchMaintenanceService batchMaintenanceService;
053
054    /**
055     * Constructs a BatchAction.java.
056     */
057    public BatchAction() {
058        setBatchMaintenanceService(SpringContext.getBean(BatchMaintenanceService.class));
059    }
060
061
062    /**
063     * This method confirms and performs batch cancel.
064     * 
065     * @param mapping
066     * @param form
067     * @param request
068     * @param response
069     * @return
070     * @throws Exception
071     */
072    public ActionForward confirmAndCancel(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
073
074        PdpBatchQuestionCallback callback = new PdpBatchQuestionCallback() {
075            public boolean doPostQuestion(String batchIdString, String cancelNote, Person user) {
076                return performCancel(batchIdString, cancelNote, user);
077            }
078        };
079        return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.BatchConstants.Confirmation.CANCEL_BATCH_QUESTION, PdpKeyConstants.BatchConstants.Confirmation.CANCEL_BATCH_MESSAGE, PdpKeyConstants.BatchConstants.Messages.BATCH_SUCCESSFULLY_CANCELED, "confirmAndCancel", callback);
080
081    }
082
083    /**
084     * This method cancels a batch.
085     * 
086     * @param batchIdString a string representing the batch id
087     * @param cancelNote the cancelation note entered by the user
088     * @param user the current user
089     */
090    private boolean performCancel(String batchIdString, String cancelNote, Person user) {
091        try {
092            Integer batchId = Integer.parseInt(batchIdString);
093            return batchMaintenanceService.cancelPendingBatch(batchId, cancelNote, user);
094        }
095        catch (NumberFormatException e) {
096            GlobalVariables.getMessageMap().putError(PdpPropertyConstants.BatchConstants.BATCH_ID, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_BATCH_ID_IS_NOT_NUMERIC);
097            return false;
098        }
099
100    }
101
102    /**
103     * This method confirms and performs batch hold.
104     * 
105     * @param mapping
106     * @param form
107     * @param request
108     * @param response
109     * @return
110     * @throws Exception
111     */
112    public ActionForward confirmAndHold(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
113
114        PdpBatchQuestionCallback callback = new PdpBatchQuestionCallback() {
115            public boolean doPostQuestion(String batchIdString, String note, Person user) {
116                return performHold(batchIdString, note, user);
117            }
118        };
119        return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.BatchConstants.Confirmation.HOLD_BATCH_QUESTION, PdpKeyConstants.BatchConstants.Confirmation.HOLD_BATCH_MESSAGE, PdpKeyConstants.BatchConstants.Messages.BATCH_SUCCESSFULLY_HOLD, "confirmAndHold", callback);
120    }
121
122    /**
123     * This method holds a batch
124     * 
125     * @param batchIdString
126     * @param holdNote
127     * @param user
128     * @throws PdpException
129     */
130    private boolean performHold(String batchIdString, String holdNote, Person user) {
131        try {
132            Integer batchId = Integer.parseInt(batchIdString);
133            return batchMaintenanceService.holdPendingBatch(batchId, holdNote, user);
134        }
135        catch (NumberFormatException e) {
136            GlobalVariables.getMessageMap().putError(PdpPropertyConstants.BatchConstants.BATCH_ID, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_BATCH_ID_IS_NOT_NUMERIC);
137            return false;
138        }
139
140    }
141
142    /**
143     * This method confirms and peforms remove hold on batch action.
144     * 
145     * @param mapping
146     * @param form
147     * @param request
148     * @param response
149     * @return
150     * @throws Exception
151     */
152    public ActionForward confirmAndRemoveHold(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
153        PdpBatchQuestionCallback callback = new PdpBatchQuestionCallback() {
154            public boolean doPostQuestion(String batchIdString, String note, Person user) {
155                return performRemoveHold(batchIdString, note, user);
156            }
157        };
158        return askQuestionWithInput(mapping, form, request, response, PdpKeyConstants.BatchConstants.Confirmation.REMOVE_HOLD_BATCH_QUESTION, PdpKeyConstants.BatchConstants.Confirmation.REMOVE_HOLD_BATCH_MESSAGE, PdpKeyConstants.BatchConstants.Messages.HOLD_SUCCESSFULLY_REMOVED_ON_BATCH, "confirmAndRemoveHold", callback);
159    }
160
161    /**
162     * This method removes a batch hold.
163     * 
164     * @param batchIdString
165     * @param changeText
166     * @param user
167     * @throws PdpException
168     */
169    private boolean performRemoveHold(String batchIdString, String changeText, Person user) {
170        try {
171            Integer batchId = Integer.parseInt(batchIdString);
172            return batchMaintenanceService.removeBatchHold(batchId, changeText, user);
173        }
174        catch (NumberFormatException e) {
175            GlobalVariables.getMessageMap().putError(PdpPropertyConstants.BatchConstants.BATCH_ID, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_BATCH_ID_IS_NOT_NUMERIC);
176            return false;
177        }
178
179    }
180
181    /**
182     * This method prompts for a reason to perfomr an action on a batch (cancel, hold, remove hold).
183     * 
184     * @param mapping
185     * @param form
186     * @param request
187     * @param response
188     * @param confirmationQuestion
189     * @param confirmationText
190     * @param caller
191     * @param callback
192     * @return
193     * @throws Exception
194     */
195    private ActionForward askQuestionWithInput(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response, String confirmationQuestion, String confirmationText, String successMessage, String caller, PdpBatchQuestionCallback callback) throws Exception {
196        Object question = request.getParameter(KRADConstants.QUESTION_INST_ATTRIBUTE_NAME);
197        String reason = request.getParameter(KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME);
198        String noteText = OLEConstants.EMPTY_STRING;
199        Person person = GlobalVariables.getUserSession().getPerson();
200        boolean actionStatus;
201        String message = OLEConstants.EMPTY_STRING;
202
203        String batchId = request.getParameter(PdpParameterConstants.BatchConstants.BATCH_ID_PARAM);
204        if (batchId == null) {
205            batchId = request.getParameter(KRADConstants.QUESTION_CONTEXT);
206        }
207
208        ConfigurationService kualiConfiguration = SpringContext.getBean(ConfigurationService.class);
209        confirmationText = kualiConfiguration.getPropertyValueAsString(confirmationText);
210        confirmationText = MessageFormat.format(confirmationText, batchId);
211
212        if (question == null) {
213            // ask question if not already asked
214            return this.performQuestionWithInput(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, caller, batchId);
215        }
216        else {
217            Object buttonClicked = request.getParameter(KRADConstants.QUESTION_CLICKED_BUTTON);
218            if ((confirmationQuestion.equals(question)) && ConfirmationQuestion.NO.equals(buttonClicked)) {
219                actionStatus = false;
220            }
221            else {
222                noteText = reason;
223                int noteTextLength = (reason == null) ? 0 : noteText.length();
224                int noteTextMaxLength = PdpKeyConstants.BatchConstants.Confirmation.NOTE_TEXT_MAX_LENGTH;
225
226                if (StringUtils.isBlank(reason)) {
227
228                    if (reason == null) {
229                        // prevent a NPE by setting the reason to a blank string
230                        reason = OLEConstants.EMPTY_STRING;
231                    }
232                    return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, OLEConstants.MAPPING_BASIC, batchId, reason, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_NOTE_EMPTY, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, "");
233                }
234                else if (noteTextLength > noteTextMaxLength) {
235                    return this.performQuestionWithInputAgainBecauseOfErrors(mapping, form, request, response, confirmationQuestion, confirmationText, KRADConstants.CONFIRMATION_QUESTION, OLEConstants.MAPPING_BASIC, batchId, reason, PdpKeyConstants.BatchConstants.ErrorMessages.ERROR_NOTE_TOO_LONG, KRADConstants.QUESTION_REASON_ATTRIBUTE_NAME, "");
236                }
237
238                actionStatus = callback.doPostQuestion(batchId, noteText, person);
239                if (actionStatus) {
240                    message = successMessage;
241                }
242
243            }
244        }
245
246        String returnUrl = buildUrl(batchId, actionStatus, message, buildErrorMesageKeyList());
247        return new ActionForward(returnUrl, true);
248    }
249
250    /**
251     * This method builds the forward url.
252     * 
253     * @param batchId the batch id
254     * @param success action status: true if success, false otherwise
255     * @param message the message for the user
256     * @return the build url
257     */
258    private String buildUrl(String batchId, boolean success, String message, String errorList) {
259        String basePath = SpringContext.getBean(ConfigurationService.class).getPropertyValueAsString(OLEConstants.APPLICATION_URL_KEY);
260
261        Properties parameters = new Properties();
262        parameters.put(OLEConstants.DISPATCH_REQUEST_PARAMETER, OLEConstants.SEARCH_METHOD);
263        parameters.put(OLEConstants.BACK_LOCATION, basePath + "/" + OLEConstants.MAPPING_PORTAL + ".do");
264        parameters.put(KRADConstants.DOC_FORM_KEY, "88888888");
265        parameters.put(OLEConstants.BUSINESS_OBJECT_CLASS_ATTRIBUTE, Batch.class.getName());
266        parameters.put(OLEConstants.HIDE_LOOKUP_RETURN_LINK, "true");
267        parameters.put(OLEConstants.SUPPRESS_ACTIONS, "false");
268        parameters.put(PdpPropertyConstants.BatchConstants.BATCH_ID, batchId);
269        parameters.put(PdpParameterConstants.ACTION_SUCCESSFUL_PARAM, String.valueOf(success));
270        if (message != null && !message.equalsIgnoreCase(OLEConstants.EMPTY_STRING)) {
271            parameters.put(PdpParameterConstants.MESSAGE_PARAM, message);
272        }
273
274        if (StringUtils.isNotEmpty(errorList)) {
275            parameters.put(PdpParameterConstants.ERROR_KEY_LIST_PARAM, errorList);
276        }
277
278        String lookupUrl = UrlFactory.parameterizeUrl(basePath + "/" + OLEConstants.LOOKUP_ACTION, parameters);
279
280        return lookupUrl;
281    }
282
283    /**
284     * This method build a string list of error message keys out of the error map in GlobalVariables
285     * 
286     * @return a String representing the list of error message keys
287     */
288    private String buildErrorMesageKeyList() {
289        MessageMap errorMap = GlobalVariables.getMessageMap();
290        StringBuffer errorList = new StringBuffer();
291
292        for (String errorKey : (List<String>) errorMap.getPropertiesWithErrors()) {
293            for (ErrorMessage errorMessage : (List<ErrorMessage>) errorMap.getMessages(errorKey)) {
294
295                errorList.append(errorMessage.getErrorKey());
296                errorList.append(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR);
297            }
298        }
299        if (errorList.length() > 0) {
300            errorList.replace(errorList.lastIndexOf(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR), errorList.lastIndexOf(PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR) + PdpParameterConstants.ERROR_KEY_LIST_SEPARATOR.length(), "");
301        }
302
303        return errorList.toString();
304    }
305
306    /**
307     * This method gets the batch maintenance service.
308     * 
309     * @return the BatchMaintenanceService
310     */
311    public BatchMaintenanceService getBatchMaintenanceService() {
312        return batchMaintenanceService;
313    }
314
315    /**
316     * This method sets the batch maintenance service.
317     * 
318     * @param batchMaintenanceService
319     */
320    public void setBatchMaintenanceService(BatchMaintenanceService batchMaintenanceService) {
321        this.batchMaintenanceService = batchMaintenanceService;
322    }
323
324}
325