View Javadoc

1   /*
2    * Copyright 2011 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 1.0 (the
5    * "License"); 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/ecl1.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, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations under
14   * the License.
15   */
16  package org.kuali.student.enrollment.class2.acal.controller;
17  
18  import org.apache.commons.lang.BooleanUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.apache.log4j.Logger;
21  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
22  import org.kuali.rice.core.api.util.RiceKeyConstants;
23  import org.kuali.rice.krad.uif.UifConstants;
24  import org.kuali.rice.krad.uif.UifParameters;
25  import org.kuali.rice.krad.uif.view.DialogManager;
26  import org.kuali.rice.krad.util.GlobalVariables;
27  import org.kuali.rice.krad.util.KRADConstants;
28  import org.kuali.rice.krad.web.controller.UifControllerBase;
29  import org.kuali.rice.krad.web.form.UifFormBase;
30  import org.kuali.student.common.uif.util.KSControllerHelper;
31  import org.kuali.student.enrollment.class2.acal.dto.AcademicTermWrapper;
32  import org.kuali.student.enrollment.class2.acal.dto.AcalEventWrapper;
33  import org.kuali.student.enrollment.class2.acal.dto.HolidayCalendarWrapper;
34  import org.kuali.student.enrollment.class2.acal.dto.KeyDateWrapper;
35  import org.kuali.student.enrollment.class2.acal.dto.KeyDatesGroupWrapper;
36  import org.kuali.student.enrollment.class2.acal.form.AcademicCalendarForm;
37  import org.kuali.student.enrollment.class2.acal.service.AcademicCalendarViewHelperService;
38  import org.kuali.student.enrollment.class2.acal.util.CalendarConstants;
39  import org.kuali.student.enrollment.class2.acal.util.CommonUtils;
40  import org.kuali.student.enrollment.common.util.EnrollConstants;
41  import org.kuali.student.r2.common.dto.RichTextInfo;
42  import org.kuali.student.r2.common.dto.StatusInfo;
43  import org.kuali.student.r2.common.exceptions.VersionMismatchException;
44  import org.kuali.student.r2.core.acal.dto.AcademicCalendarInfo;
45  import org.kuali.student.r2.core.acal.dto.AcalEventInfo;
46  import org.kuali.student.r2.core.acal.dto.KeyDateInfo;
47  import org.kuali.student.r2.core.acal.dto.TermInfo;
48  import org.kuali.student.r2.core.acal.service.AcademicCalendarService;
49  import org.kuali.student.r2.core.acal.service.facade.AcademicCalendarServiceFacade;
50  import org.kuali.student.r2.core.constants.AcademicCalendarServiceConstants;
51  import org.kuali.student.r2.core.constants.AtpServiceConstants;
52  import org.springframework.stereotype.Controller;
53  import org.springframework.validation.BindingResult;
54  import org.springframework.web.bind.annotation.ModelAttribute;
55  import org.springframework.web.bind.annotation.RequestMapping;
56  import org.springframework.web.bind.annotation.RequestMethod;
57  import org.springframework.web.servlet.ModelAndView;
58  
59  import javax.servlet.http.HttpServletRequest;
60  import javax.servlet.http.HttpServletResponse;
61  import javax.xml.namespace.QName;
62  import java.lang.reflect.InvocationTargetException;
63  import java.lang.reflect.Method;
64  import java.util.ArrayList;
65  import java.util.Date;
66  import java.util.List;
67  import java.util.Properties;
68  
69  /**
70   * This controller handles all the request from Academic calendar UI.
71   *
72   * These are the related xmls from where requests come to this controller
73   * 1. AcademicCalendarView.xml
74   * 2. AcademicCalendarEditPage.xml
75   * 3. AcademicCalendarCopyPage.xml
76   * 4. AcademicTermPage.xml
77   *
78   * @author Kuali Student Team
79   */
80  
81  @Controller
82  @RequestMapping(value = "/academicCalendar")
83  public class AcademicCalendarController extends UifControllerBase {
84  
85      private static final Logger LOG = Logger.getLogger(AcademicCalendarController.class);
86  
87      private AcademicCalendarService acalService;
88      private AcademicCalendarServiceFacade academicCalendarServiceFacade;
89  
90      @Override
91      protected UifFormBase createInitialForm(HttpServletRequest request) {
92          return new AcademicCalendarForm();
93      }
94  
95      /**
96       * This method loads an academic calendar based on the parameters passed into the request.
97       *
98       * These are the supported request parameters (specific to Acal)
99       * 1. id - Academic Calendar Id to load in to UI
100      * 2. readOnlyView - If true, sets the view as read only
101      * 3. selectTab - can be 'info' or 'term'
102      *
103      */
104     @Override
105     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=start")
106     public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
107                               HttpServletRequest request, HttpServletResponse response) {
108         AcademicCalendarForm acalForm = (AcademicCalendarForm) form;
109 
110         String acalId = request.getParameter(CalendarConstants.CALENDAR_ID);
111 
112         if (StringUtils.isNotBlank(acalId)){
113             getAcalViewHelperService(acalForm).populateAcademicCalendar(acalId, acalForm);
114         }
115 
116         String readOnlyView = request.getParameter(CalendarConstants.READ_ONLY_VIEW);
117         acalForm.getView().setReadOnly(BooleanUtils.toBoolean(readOnlyView));
118 
119         if (StringUtils.isNotBlank(request.getParameter(CalendarConstants.SELECT_TAB))) {
120             acalForm.setDefaultTabToShow(request.getParameter(CalendarConstants.SELECT_TAB));
121         }
122 
123         return getUIFModelAndView(form);
124     }
125 
126     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=reload")
127     public ModelAndView reload(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
128                                HttpServletRequest request, HttpServletResponse response) {
129         String acalId = acalForm.getAcademicCalendarInfo().getId();
130         getAcalViewHelperService(acalForm).populateAcademicCalendar(acalId, acalForm);
131         acalForm.setReload(false);
132         return getUIFModelAndView(acalForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
133     }
134 
135     /**
136      * This method creates a blank academic calendar.
137      */
138     @RequestMapping(params = "methodToCall=createBlankCalendar")
139     public ModelAndView createBlankCalendar(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
140                                             HttpServletRequest request, HttpServletResponse response){
141 
142         acalForm.setAcademicCalendarInfo(new AcademicCalendarInfo());
143         acalForm.setEvents(new ArrayList<AcalEventWrapper>());
144         acalForm.setHolidayCalendarList(new ArrayList<HolidayCalendarWrapper>());
145         acalForm.setTermWrapperList(new ArrayList<AcademicTermWrapper>());
146 
147         return getUIFModelAndView(acalForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
148     }
149 
150     /**
151      * This method is called before the Create New Academic Calendar page is displayed
152      *
153      * It fills in the original Acal for the form with the latest calendar found, by default
154      */
155     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=startNew")
156     public ModelAndView startNew( @ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
157                                   HttpServletRequest request, HttpServletResponse response) {
158 
159         try {
160             AcademicCalendarInfo acalInfo = getAcalViewHelperService(acalForm).getLatestAcademicCalendar();
161             acalForm.setCopyFromAcal(acalInfo);
162             acalForm.setMeta(acalInfo.getMeta());
163         } catch (Exception e) {
164             throw getAcalViewHelperService(acalForm).convertServiceExceptionsToUI(e);
165         }
166 
167         return super.start(acalForm, result, request, response);
168     }
169 
170     /**
171      * This method will be called when user clicks on the edit link at the header portion of acal.
172      *
173      * @param acalForm
174      * @param result
175      * @param request
176      * @param response
177      * @return
178      */
179     @RequestMapping(params = "methodToCall=toEdit")
180     public ModelAndView toEdit(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
181                                HttpServletRequest request, HttpServletResponse response){
182         AcademicCalendarInfo acalInfo = acalForm.getAcademicCalendarInfo();
183         AcademicCalendarInfo orgAcalInfo = acalForm.getCopyFromAcal();
184 
185         if (StringUtils.isBlank(acalInfo.getId()) && StringUtils.isNotBlank(orgAcalInfo.getId())){
186             getAcalViewHelperService(acalForm).populateAcademicCalendar(orgAcalInfo.getId(), acalForm);
187             acalForm.setCopyFromAcal(new AcademicCalendarInfo());
188         }
189 
190         acalForm.getView().setReadOnly(false);
191 
192         return getUIFModelAndView(acalForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
193     }
194 
195     /**
196      * Passes on request from Acal view to copy the Acal to the copyForNew method.  Needed a forwarder here because the
197      * call is a GET rather than a POST
198      *
199      * @param acalForm
200      * @param result
201      * @param request
202      * @param response
203      * @return
204      */
205     @RequestMapping(params = "methodToCall=toCopy")
206     public ModelAndView toCopy(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
207                                HttpServletRequest request, HttpServletResponse response){
208 
209         AcademicCalendarInfo acalInfo = null;
210 
211         String acalId = request.getParameter(CalendarConstants.CALENDAR_ID);
212         if (acalId != null && !acalId.trim().isEmpty()) {
213             String pageId = request.getParameter(CalendarConstants.PAGE_ID);
214             if (CalendarConstants.ACADEMIC_CALENDAR_COPY_PAGE.equals(pageId)) {
215 
216                 try {
217                     acalInfo= getAcalService().getAcademicCalendar(acalId, getAcalViewHelperService(acalForm).createContextInfo());
218                     acalForm.setCopyFromAcal(acalInfo);
219                 } catch (Exception ex) {
220                     throw getAcalViewHelperService(acalForm).convertServiceExceptionsToUI(ex);
221                 }
222             }
223         }
224         else {
225             // try to get the AC from the form (in case of copy from the Acal view page) and set it as the Original Acal
226             try {
227                 acalInfo = acalForm.getAcademicCalendarInfo();
228                 acalForm.reset();
229                 acalForm.setNewCalendar(true);
230                 acalForm.setCopyFromAcal(acalInfo);
231             }
232             catch (Exception e) {
233                 throw getAcalViewHelperService(acalForm).convertServiceExceptionsToUI(e);
234             }
235 
236         }
237 
238         // Anything that extends KSUIFForm.java will have meta information
239         if(acalInfo != null){
240             acalForm.setMeta(acalInfo.getMeta());
241         }
242 
243         return copy(acalForm, result, request, response);
244     }
245 
246     /**
247      * Copy over from the existing AcalInfo to create a new.
248      *
249      * @param acalForm
250      * @param result
251      * @param request
252      * @param response
253      * @return
254      */
255     @RequestMapping(method = RequestMethod.POST, params="methodToCall=copy")
256     public ModelAndView copy( @ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
257                               HttpServletRequest request, HttpServletResponse response) {
258 
259         getAcalViewHelperService(acalForm).copyToCreateAcademicCalendar(acalForm);
260 
261         return getUIFModelAndView(acalForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
262 
263     }
264 
265     //Editing Hcal is implemented fully and it's working.. but we're having some issues with KRAD form management
266     //This will be implemented in future milestones
267     /*@RequestMapping(method = RequestMethod.POST, params="methodToCall=editHolidayCalendar")
268     public ModelAndView editHolidayCalendar( @ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
269                                             HttpServletRequest request, HttpServletResponse response) {
270 
271         String selectedCollectionPath = acalForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
272         if (StringUtils.isBlank(selectedCollectionPath)) {
273             throw new RuntimeException("unable to determine the selected collection path");
274         }
275 
276         int selectedLineIndex = -1;
277         String selectedLine = acalForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
278         if (StringUtils.isNotBlank(selectedLine)) {
279             selectedLineIndex = Integer.parseInt(selectedLine);
280         }
281 
282         if (selectedLineIndex == -1) {
283             throw new RuntimeException("unable to determine the selected line index");
284         }
285 
286         Properties hcalURLParam = new Properties();
287         hcalURLParam.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, CalendarConstants.HC_EDIT_METHOD);
288         hcalURLParam.put(CalendarConstants.CALENDAR_ID, acalForm.getHolidayCalendarList().get(selectedLineIndex).getId());
289         hcalURLParam.put(UifParameters.VIEW_ID, CalendarConstants.HOLIDAYCALENDAR_FLOWVIEW);
290         hcalURLParam.put(UifParameters.PAGE_ID, CalendarConstants.HOLIDAYCALENDAR_EDITPAGE);
291         hcalURLParam.put(UifParameters.RETURN_FORM_KEY, acalForm.getFormKey());
292 
293         Properties acalReturnURLParams = new Properties();
294         acalReturnURLParams.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, CalendarConstants.AC_EDIT_METHOD);
295         acalReturnURLParams.put(UifParameters.VIEW_ID, CalendarConstants.ACAL_VIEW);
296         acalReturnURLParams.put(UifParameters.PAGE_ID, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
297         String returnUrl = UrlFactory.parameterizeUrl(CalendarConstants.ACAL_CONTROLLER_PATH, acalReturnURLParams);
298         hcalURLParam.put(UifParameters.RETURN_LOCATION, returnUrl);
299 
300         return super.performRedirect(acalForm,CalendarConstants.HCAL_CONTROLLER_PATH, hcalURLParam);
301 
302     }*/
303 
304 
305     /**
306      * Redirects the user to the search Calendar page
307      *
308      * @param acalForm
309      * @param result
310      * @param request
311      * @param response
312      * @return
313      */
314     @RequestMapping(params = "methodToCall=search")
315     public ModelAndView search(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
316                                HttpServletRequest request, HttpServletResponse response) {
317 
318         String controllerPath = CalendarConstants.CALENDAR_SEARCH_CONTROLLER_PATH;
319         Properties urlParameters = new Properties();
320         urlParameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.START_METHOD);
321         urlParameters.put(UifParameters.VIEW_ID, CalendarConstants.CALENDAR_SEARCH_VIEW);
322         urlParameters.put(UifConstants.UrlParams.SHOW_HISTORY, BooleanUtils.toStringTrueFalse(false));
323         return super.performRedirect(acalForm,controllerPath, urlParameters);
324     }
325 
326     /**
327      * This will save the academic calendar and terms.  Uses dialog confirmations to verify changes from draft to
328      * offical state.
329      *
330      * @param academicCalendarForm
331      * @param result
332      * @param request
333      * @param response
334      * @return
335      */
336     @RequestMapping(params = "methodToCall=save")
337     public ModelAndView save(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
338                              HttpServletRequest request, HttpServletResponse response) {
339         AcademicCalendarForm acal = saveAcademicCalendarDirtyFields(academicCalendarForm);
340         return getUIFModelAndView(acal);
341     }
342 
343     /**
344      * Method used to delete AcademicCalendar
345      *
346      * @param acalForm
347      * @param result
348      * @param request
349      * @param response
350      * @return
351      */
352     @RequestMapping(params = "methodToCall=delete")
353     public ModelAndView delete(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
354                                HttpServletRequest request, HttpServletResponse response) {
355         String dialog = CalendarConstants.ACADEMIC_DELETE_CONFIRMATION_DIALOG;
356         if (!hasDialogBeenDisplayed(dialog, acalForm)) {
357 
358             //redirect back to client to display lightbox
359             return showDialog(dialog, acalForm, request, response);
360         }else{
361             if(hasDialogBeenAnswered(dialog,acalForm)){
362                 boolean confirmDelete = getBooleanDialogResponse(dialog, acalForm, request, response);
363                 acalForm.getDialogManager().resetDialogStatus(dialog);
364                 if(!confirmDelete){
365                     return getUIFModelAndView(acalForm);
366                 }
367             } else {
368 
369                 //redirect back to client to display lightbox
370                 return showDialog(dialog, acalForm, request, response);
371             }
372         }
373 
374         StatusInfo statusInfo;
375         try {
376             statusInfo = getAcademicCalendarServiceFacade().deleteCalendarCascaded(acalForm.getAcademicCalendarInfo().getId(), getAcalViewHelperService(acalForm).createContextInfo());
377         } catch (Exception e) {
378             throw getAcalViewHelperService(acalForm).convertServiceExceptionsToUI(e);
379         }
380 
381         if (statusInfo.getIsSuccess()){
382             // If delete successful, populate growl message parameters and redirect to the search page.
383             Properties urlParameters = new Properties();
384             urlParameters.put(EnrollConstants.GROWL_TITLE,"");
385             urlParameters.put(EnrollConstants.GROWL_MESSAGE, CalendarConstants.MessageKeys.INFO_ACADEMIC_CALENDAR_DELETED);
386             urlParameters.put(EnrollConstants.GROWL_MESSAGE_PARAMS,acalForm.getAcademicCalendarInfo().getName());
387             return redirectToSearch(acalForm,request,urlParameters);
388         } else {
389             GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_DELETING, acalForm.getAcademicCalendarInfo().getName(),statusInfo.getMessage());
390             return getUIFModelAndView(acalForm);
391         }
392 
393 
394     }
395 
396     /**
397      * Cancel editing a term. This will undo all the changes done by the users. Basically, it loads the term info
398      * from the DB.
399      *
400      * @param academicCalendarForm
401      * @param result
402      * @param request
403      * @param response
404      * @return
405      */
406     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=cancelTerm")
407     public ModelAndView cancelTerm(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
408                                    HttpServletRequest request, HttpServletResponse response) {
409         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
410         int selectedLineIndex = KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
411 
412         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
413 
414         AcademicCalendarViewHelperService viewHelperService = getAcalViewHelperService(academicCalendarForm);
415 
416         if (termWrapper.isNew()){
417             academicCalendarForm.getTermWrapperList().remove(selectedLineIndex);
418             if (termWrapper.isHasSubterm()){
419                 List<AcademicTermWrapper> subTerms = termWrapper.getSubterms();
420                 for(AcademicTermWrapper subTerm : subTerms){
421                     academicCalendarForm.getTermWrapperList().remove(subTerm);
422                 }
423             }
424         }else{  //this part will not be called since cancel Term link does not show up after a term is persisted in DB.
425             try {
426                 TermInfo termInfo = getAcalService().getTerm(termWrapper.getTermInfo().getId(), viewHelperService.createContextInfo());
427                 boolean calculateInstrDays = !academicCalendarForm.getHolidayCalendarList().isEmpty();
428                 AcademicTermWrapper termWrapperFromDB = viewHelperService.populateTermWrapper(termInfo, false,calculateInstrDays);
429                 academicCalendarForm.getTermWrapperList().set(selectedLineIndex,termWrapperFromDB);
430             } catch (Exception e) {
431                 throw getAcalViewHelperService(academicCalendarForm).convertServiceExceptionsToUI(e);
432             }
433         }
434 
435         return getUIFModelAndView(academicCalendarForm);
436     }
437 
438     /**
439      * This method makes a term official and persist to DB. User can selectively make a term official.
440      *
441      * @param academicCalendarForm
442      * @param result
443      * @param request
444      * @param response
445      * @return
446      */
447     @RequestMapping(params = "methodToCall=makeTermOfficial")
448     public ModelAndView makeTermOfficial(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
449                                          HttpServletRequest request, HttpServletResponse response) {
450         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
451 
452         int selectedLineIndex;
453 
454         AcademicTermWrapper termWrapper;
455 
456         String dialog=null;
457         if(academicCalendarForm.isOfficialCalendar()){
458             dialog = CalendarConstants.ACADEMIC_TERM_OFFICIAL_CONFIRMATION_DIALOG;
459         }else{
460             dialog = CalendarConstants.ACADEMIC_TERM_AND_CALENDAR_OFFICIAL_CONFIRMATION_DIALOG;
461         }
462 
463         // Dialog confirmation to make terms official
464         if (!hasDialogBeenDisplayed(dialog, academicCalendarForm)) {
465             selectedLineIndex= KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
466             termWrapper= academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
467             academicCalendarForm.setSelectedCollectionPath(academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH));
468             academicCalendarForm.setSelectedLineIndex(academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX));
469             academicCalendarForm.setMakeOfficialName(termWrapper.getName());
470             academicCalendarForm.setMakeOfficialIsSubterm(termWrapper.isSubTerm());
471             if(termWrapper.getParentTermInfo()!=null){
472                 academicCalendarForm.setMakeOfficialParentTermName(termWrapper.getParentTermInfo().getName());
473                 academicCalendarForm.setOfficialParentTerm(false);
474                 for(AcademicTermWrapper term : academicCalendarForm.getTermWrapperList()){
475                     if(term.getTermInfo().getId().equals(termWrapper.getParentTermInfo().getId())){
476                         academicCalendarForm.setOfficialParentTerm(term.isOfficial());
477                     }
478                 }
479             }
480 
481             //redirect back to client to display lightbox
482             return showDialog(dialog, academicCalendarForm, request, response);
483         }else{
484             if(hasDialogBeenAnswered(dialog,academicCalendarForm)){
485                 boolean confirm = getBooleanDialogResponse(dialog, academicCalendarForm, request, response);
486                 academicCalendarForm.getDialogManager().resetDialogStatus(dialog);
487                 if(!confirm){
488                     return getUIFModelAndView(academicCalendarForm);
489                 }
490             } else {
491                 selectedLineIndex= KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
492                 termWrapper= academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
493                 academicCalendarForm.setSelectedCollectionPath(academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH));
494                 academicCalendarForm.setSelectedLineIndex(academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX));
495                 academicCalendarForm.setMakeOfficialName(termWrapper.getName());
496                 academicCalendarForm.setMakeOfficialIsSubterm(termWrapper.isSubTerm());
497                 if(termWrapper.getParentTermInfo()!=null){
498                     academicCalendarForm.setMakeOfficialParentTermName(termWrapper.getParentTermInfo().getName());
499                     academicCalendarForm.setOfficialParentTerm(false);
500                     for(AcademicTermWrapper term : academicCalendarForm.getTermWrapperList()){
501                         if(term.getTermInfo().getId().equals(termWrapper.getParentTermInfo().getId())){
502                             academicCalendarForm.setOfficialParentTerm(term.isOfficial());
503                         }
504                     }
505                 }
506 
507 
508                 //redirect back to client to display lightbox
509                 return showDialog(dialog, academicCalendarForm, request, response);
510             }
511         }
512 
513         academicCalendarForm.getActionParameters().put(UifParameters.SELLECTED_COLLECTION_PATH, academicCalendarForm.getSelectedCollectionPath());
514         if (academicCalendarForm.getSelectedLineIndex() != null && academicCalendarForm.getSelectedLineIndex().indexOf(",") > -1) {
515             academicCalendarForm.getActionParameters().put(UifParameters.SELECTED_LINE_INDEX, academicCalendarForm.getSelectedLineIndex().substring(0,academicCalendarForm.getSelectedLineIndex().indexOf(",")));
516         } else {
517             academicCalendarForm.getActionParameters().put(UifParameters.SELECTED_LINE_INDEX, academicCalendarForm.getSelectedLineIndex());
518         }
519         selectedLineIndex= KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
520         termWrapper= academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
521 
522         boolean acalOfficial=true;
523 
524         if(!academicCalendarForm.isOfficialCalendar()){
525             acalOfficial = makeAcalOfficial(academicCalendarForm);
526         }
527 
528         if(acalOfficial){
529             makeTermOfficial(termWrapper,academicCalendarForm);
530         }
531 
532         academicCalendarForm.setDefaultTabToShow(CalendarConstants.ACAL_TERM_TAB);
533         return getUIFModelAndView(academicCalendarForm);
534     }
535 
536 
537     /**
538      *
539      * Improvement jira KSENROLL-3568  to clear all the fields at the client side instead of at server side.
540      * @param academicCalendarForm
541      * @param result
542      * @param request
543      * @param response
544      * @return
545      */
546     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=cancelAddingHoliday")
547     public ModelAndView cancelAddingHoliday(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
548                                             HttpServletRequest request, HttpServletResponse response) {
549         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
550         ((HolidayCalendarWrapper)academicCalendarForm.getNewCollectionLines().get("holidayCalendarList")).setId(StringUtils.EMPTY);
551 
552         return getUIFModelAndView(academicCalendarForm);
553     }
554 
555     private void setDeleteTermMessageWithContext(AcademicCalendarForm academicCalendarForm){
556         academicCalendarForm.setSelectedCollectionPath(academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH));
557         academicCalendarForm.setSelectedLineIndex(academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX));
558         academicCalendarForm.getActionParameters().put(UifParameters.SELLECTED_COLLECTION_PATH, academicCalendarForm.getSelectedCollectionPath());
559         if (academicCalendarForm.getSelectedLineIndex() != null && academicCalendarForm.getSelectedLineIndex().indexOf(",") > -1) {
560             academicCalendarForm.getActionParameters().put(UifParameters.SELECTED_LINE_INDEX, academicCalendarForm.getSelectedLineIndex().substring(0,academicCalendarForm.getSelectedLineIndex().indexOf(",")));
561         } else {
562             academicCalendarForm.getActionParameters().put(UifParameters.SELECTED_LINE_INDEX, academicCalendarForm.getSelectedLineIndex());
563         }
564 
565         int selectedLineIndex = KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
566 
567         AcademicTermWrapper selectedTermWrapper = academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
568         if(selectedTermWrapper.isSubTerm()){
569             academicCalendarForm.setMessageForDeleteTermOrSubterm(CalendarConstants.MESSAGE_CONFIRM_TO_DELETE_SUBTERM);
570         }else if(selectedTermWrapper.isHasSubterm()){
571             academicCalendarForm.setMessageForDeleteTermOrSubterm(CalendarConstants.MESSAGE_CONFIRM_TO_DELETE_TERM_WITH_SUBTERM);
572         }else{
573             academicCalendarForm.setMessageForDeleteTermOrSubterm(CalendarConstants.MESSAGE_CONFIRM_TO_DELETE_TERM_ONLY);
574         }
575     }
576 
577     /**
578      * This would mark a term for deletion if it's already there in the DB. If it's a newly added term, it just deletes
579      * that.
580      *
581      * @param academicCalendarForm
582      * @param result
583      * @param request
584      * @param response
585      * @return
586      */
587     @RequestMapping(params = "methodToCall=deleteTerm")
588     public ModelAndView deleteTerm(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
589                                    HttpServletRequest request, HttpServletResponse response) {
590         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
591 
592         String dialog = CalendarConstants.TERM_DELETE_CONFIRMATION_DIALOG;
593         if (!hasDialogBeenDisplayed(dialog, academicCalendarForm)) {
594             setDeleteTermMessageWithContext(academicCalendarForm);
595             //redirect back to client to display lightbox
596             return showDialog(dialog, academicCalendarForm, request, response);
597         }else{
598             if(hasDialogBeenAnswered(dialog,academicCalendarForm)){
599                 boolean confirmDelete = getBooleanDialogResponse(dialog, academicCalendarForm, request, response);
600                 academicCalendarForm.getDialogManager().resetDialogStatus(dialog);
601                 if(!confirmDelete){
602                     return getUIFModelAndView(academicCalendarForm);
603                 }
604             } else {
605                 setDeleteTermMessageWithContext(academicCalendarForm);
606                 //redirect back to client to display lightbox
607                 return showDialog(dialog, academicCalendarForm, request, response);
608             }
609         }
610 
611         academicCalendarForm.getActionParameters().put(UifParameters.SELLECTED_COLLECTION_PATH, academicCalendarForm.getSelectedCollectionPath());
612         if (academicCalendarForm.getSelectedLineIndex() != null && academicCalendarForm.getSelectedLineIndex().indexOf(",") > -1) {
613             academicCalendarForm.getActionParameters().put(UifParameters.SELECTED_LINE_INDEX, academicCalendarForm.getSelectedLineIndex().substring(0,academicCalendarForm.getSelectedLineIndex().indexOf(",")));
614         } else {
615             academicCalendarForm.getActionParameters().put(UifParameters.SELECTED_LINE_INDEX, academicCalendarForm.getSelectedLineIndex());
616         }
617 
618         int selectedLineIndex = KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
619 
620         AcademicTermWrapper theTermWrapper = academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
621 
622         if (!theTermWrapper.isNew()){
623             academicCalendarForm.getTermsToDeleteOnSave().add(theTermWrapper);
624         }
625         academicCalendarForm.getTermWrapperList().remove(selectedLineIndex);
626 
627         if(theTermWrapper.isHasSubterm())  { //get all subterms and remove them as well
628             List<AcademicTermWrapper> subTerms = theTermWrapper.getSubterms();
629             for(AcademicTermWrapper subTerm : subTerms){
630                 academicCalendarForm.getTermWrapperList().remove(subTerm);
631             }
632         }
633         return getUIFModelAndView(academicCalendarForm);
634     }
635 
636     /**
637      * Like term, this would mark a key date for deletion. If it's newly added, just deletes it.
638      *
639      * @param academicCalendarForm
640      * @param result
641      * @param request
642      * @param response
643      * @return
644      */
645     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteKeyDate")
646     public ModelAndView deleteKeyDate(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
647                                       HttpServletRequest request, HttpServletResponse response) {
648         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
649         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
650         if (StringUtils.isBlank(selectedCollectionPath)) {
651             throw new RuntimeException("unable to determine the selected collection path");
652         }
653 
654         int selectedLineIndex = KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
655 
656         String selectedTermIndex = StringUtils.substringBetween(selectedCollectionPath,"termWrapperList[","]");
657         String selectedKeyDateGroup = StringUtils.substringBetween(selectedCollectionPath,"keyDatesGroupWrappers[","]");
658 
659         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(Integer.parseInt(selectedTermIndex));
660         KeyDatesGroupWrapper keydateGroup = termWrapper.getKeyDatesGroupWrappers().get(Integer.parseInt(selectedKeyDateGroup));
661         KeyDateWrapper keyDateWrapper = keydateGroup.getKeydates().get(selectedLineIndex);
662 
663         if (StringUtils.isNotBlank(keyDateWrapper.getKeyDateInfo().getId())){
664             termWrapper.getKeyDatesToDeleteOnSave().add(keyDateWrapper);
665         }
666 
667         keydateGroup.getKeydates().remove(selectedLineIndex);
668 
669         return getUIFModelAndView(academicCalendarForm);
670 
671     }
672 
673     @RequestMapping(params = "methodToCall=deleteKeyDateGroup")
674     public ModelAndView deleteKeyDateGroup(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
675                                            HttpServletRequest request, HttpServletResponse response) {
676         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
677         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
678         if (StringUtils.isBlank(selectedCollectionPath)) {
679             throw new RuntimeException("unable to determine the selected collection path");
680         }
681 
682         int selectedLineIndex = KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
683 
684         String selectedTermIndex = StringUtils.substringBetween(selectedCollectionPath, "termWrapperList[", "]");
685 
686         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(Integer.parseInt(selectedTermIndex));
687         KeyDatesGroupWrapper keydateGroup = termWrapper.getKeyDatesGroupWrappers().get(selectedLineIndex);
688         for (KeyDateWrapper keyDateWrapper : keydateGroup.getKeydates()) {
689             if (StringUtils.isNotBlank(keyDateWrapper.getKeyDateInfo().getId())){
690                 termWrapper.getKeyDatesToDeleteOnSave().add(keyDateWrapper);
691             }
692         }
693 
694         termWrapper.getKeyDatesGroupWrappers().remove(keydateGroup);
695 
696         return getUIFModelAndView(academicCalendarForm);
697 
698     }
699 
700     /**
701      * Removes the the selected holiday for delete from the list of holidays.
702      * No changes are made to database until save.
703      *
704      * @param academicCalendarForm
705      * @param result
706      * @param request
707      * @param response
708      * @return
709      */
710     @RequestMapping(params = "methodToCall=deleteHolidayCalendar")
711     public ModelAndView deleteHolidayCalendar(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
712                                               HttpServletRequest request, HttpServletResponse response) {
713         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
714         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
715         if (StringUtils.isBlank(selectedCollectionPath)) {
716             throw new RuntimeException("unable to determine the selected collection path");
717         }
718 
719         int selectedLineIndex = KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
720 
721         academicCalendarForm.getHolidayCalendarList().remove(selectedLineIndex);
722 
723         return getUIFModelAndView(academicCalendarForm);
724 
725     }
726 
727     /**
728      * Removes the the selected event for delete from the list of events.
729      * Event is added to the list of events to be deleted during save if it is in the database.
730      * No changes are made to database until save.
731      *
732      * @param academicCalendarForm
733      * @param result
734      * @param request
735      * @param response
736      * @return
737      */
738     @RequestMapping(params = "methodToCall=deleteAcalEvent")
739     public ModelAndView deleteAcalEvent(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
740                                         HttpServletRequest request, HttpServletResponse response) {
741         academicCalendarForm.setFieldsToSave(processDirtyFields(academicCalendarForm));
742         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
743         if (StringUtils.isBlank(selectedCollectionPath)) {
744             throw new RuntimeException("unable to determine the selected collection path");
745         }
746 
747         int selectedLineIndex = KSControllerHelper.getSelectedCollectionLineIndex(academicCalendarForm);
748         AcalEventWrapper deletedEvent = academicCalendarForm.getEvents().get(selectedLineIndex);
749         if(deletedEvent.getAcalEventInfo().getId()!=null){
750             academicCalendarForm.getEventsToDeleteOnSave().add(deletedEvent);
751         }
752 
753         academicCalendarForm.getEvents().remove(selectedLineIndex);
754 
755         return getUIFModelAndView(academicCalendarForm);
756 
757     }
758 
759     /**
760      * Method used to set Acal as official
761      */
762     @RequestMapping(params = "methodToCall=makeAcalOfficial")
763     public ModelAndView makeAcalOfficial(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
764                                          HttpServletRequest request, HttpServletResponse response) {
765         // Dialog confirmation to make the calendar official
766         String dialog = CalendarConstants.ACADEMIC_CALENDAR_OFFICIAL_CONFIRMATION_DIALOG;
767         if (!hasDialogBeenDisplayed(dialog, acalForm)) {
768             acalForm.setMakeOfficialName(acalForm.getAcademicCalendarInfo().getName());
769             //redirect back to client to display lightbox
770             return showDialog(dialog, acalForm, request, response);
771         }else{
772             if(hasDialogBeenAnswered(dialog,acalForm)){
773                 boolean confirm = getBooleanDialogResponse(dialog, acalForm, request, response);
774                 acalForm.getDialogManager().resetDialogStatus(dialog);
775                 if(!confirm){
776                     return getUIFModelAndView(acalForm);
777                 }
778             } else {
779 
780                 //redirect back to client to display lightbox
781                 return showDialog(dialog, acalForm, request, response);
782             }
783         }
784 
785         makeAcalOfficial(acalForm);
786 
787         return getUIFModelAndView(acalForm);
788     }
789 
790     public AcademicCalendarService getAcalService() {
791         if(acalService == null) {
792             acalService = (AcademicCalendarService) GlobalResourceLoader.getService(new QName(AcademicCalendarServiceConstants.NAMESPACE, AcademicCalendarServiceConstants.SERVICE_NAME_LOCAL_PART));
793         }
794         return this.acalService;
795     }
796 
797     public AcademicCalendarServiceFacade getAcademicCalendarServiceFacade() {
798         if(academicCalendarServiceFacade == null) {
799             academicCalendarServiceFacade = (AcademicCalendarServiceFacade) GlobalResourceLoader.getService(new QName(AcademicCalendarServiceConstants.FACADE_NAMESPACE, AcademicCalendarServiceConstants.FACADE_SERVICE_NAME_LOCAL_PART));
800         }
801         return this.academicCalendarServiceFacade;
802     }
803 
804     protected AcademicCalendarViewHelperService getAcalViewHelperService(AcademicCalendarForm acalForm){
805         AcademicCalendarViewHelperService viewHelperService = (AcademicCalendarViewHelperService) KSControllerHelper.getViewHelperService(acalForm);
806         return viewHelperService;
807     }
808 
809     /**
810      * Redirects from an academic calendar page to the calendar search page
811      *
812      * @param academicCalendarForm - Calendar form backing the page
813      * @param request - Http requests parameters
814      * @param urlParameters - Additional parameters to pass when redirecting
815      * @return The Calendar search page.
816      */
817     private ModelAndView redirectToSearch(AcademicCalendarForm academicCalendarForm,HttpServletRequest request, Properties urlParameters){
818         urlParameters.put("viewId", CalendarConstants.CALENDAR_SEARCH_VIEW);
819         urlParameters.put("methodToCall", KRADConstants.START_METHOD);
820         urlParameters.put(UifConstants.UrlParams.SHOW_HISTORY, BooleanUtils.toStringTrueFalse(false));
821         String uri = request.getRequestURL().toString().replace("academicCalendar","calendarSearch");
822         return performRedirect(academicCalendarForm, uri, urlParameters);
823     }
824 
825     /**
826      * Changes the state of the term from draft to official
827      *
828      * @param term - The Term to make official
829      * @param acalForm - Tee page form
830      * @return true if the term was made official successfully, false otherwise.
831      */
832     private boolean makeTermOfficial(AcademicTermWrapper term, AcademicCalendarForm acalForm){
833         AcademicCalendarViewHelperService viewHelperService = getAcalViewHelperService(acalForm);
834         StatusInfo statusInfo;
835         try {
836             if (term.isSubTerm()) {
837                 statusInfo = getAcademicCalendarServiceFacade().makeTermOfficialCascaded(term.getTermInfo().getId(), viewHelperService.createContextInfo());
838             } else {
839                 statusInfo = getAcalService().changeTermState(term.getTermInfo().getId(), AtpServiceConstants.ATP_OFFICIAL_STATE_KEY, viewHelperService.createContextInfo());
840             }
841             if (!statusInfo.getIsSuccess()) {
842                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, RiceKeyConstants.ERROR_CUSTOM, statusInfo.getMessage());
843                 return false;
844             }
845             term.setTermInfo(getAcalService().getTerm(term.getTermInfo().getId(),viewHelperService.createContextInfo()));
846             if(term.isSubTerm()){ // update the parent term so the view displays the proper states (draft vs official)
847                 for(AcademicTermWrapper termWrapper : acalForm.getTermWrapperList()){
848                     if(termWrapper.getTermInfo().getId().equals(term.getParentTermInfo().getId())){
849                         TermInfo updatedParentTerm = getAcalService().getTerm(term.getParentTermInfo().getId(),viewHelperService.createContextInfo());
850                         // Make sure the parent term is updated in both the term and the termWrapperList.
851                         term.setParentTermInfo(updatedParentTerm);
852                         termWrapper.setTermInfo(updatedParentTerm); // the screen looks at this variable
853                     }
854                 }
855             }
856             for (KeyDatesGroupWrapper groupWrapper : term.getKeyDatesGroupWrappers()){
857                 for (KeyDateWrapper keyDateWrapper : groupWrapper.getKeydates()) {
858                     keyDateWrapper.setKeyDateInfo(getAcalService().getKeyDate(keyDateWrapper.getKeyDateInfo().getId(),viewHelperService.createContextInfo()));
859                 }
860             }
861         } catch (Exception e) {
862             LOG.error("Make Official Failed for Term",e);
863             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_ACAL_SAVE_TERM_OFFICIAL_FAILED + " - " + e.getMessage());
864             return false;
865         }
866         return true;
867     }
868 
869     /**
870      * Attempts to make the academic calendar official.
871      *
872      * @param acalForm - Tee page form
873      * @return True if calendar state is successfully changed
874      */
875     private boolean makeAcalOfficial(AcademicCalendarForm acalForm){
876         AcademicCalendarViewHelperService viewHelperService = getAcalViewHelperService(acalForm);
877         try {
878             StatusInfo statusInfo = null;
879             statusInfo = getAcalService().changeAcademicCalendarState(acalForm.getAcademicCalendarInfo().getId(), AcademicCalendarServiceConstants.ACADEMIC_CALENDAR_OFFICIAL_STATE_KEY,viewHelperService.createContextInfo());
880             if (!statusInfo.getIsSuccess()){
881                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, RiceKeyConstants.ERROR_CUSTOM, statusInfo.getMessage());
882                 return false;
883             } else{
884                 // Refresh form information
885                 acalForm.setAcademicCalendarInfo(getAcalService().getAcademicCalendar(acalForm.getAcademicCalendarInfo().getId(), viewHelperService.createContextInfo()));
886                 acalForm.setOfficialCalendar(true);
887                 for (AcalEventWrapper eventWrapper : acalForm.getEvents()) {
888                     eventWrapper.setAcalEventInfo(getAcalService().getAcalEvent(eventWrapper.getAcalEventInfo().getId(),viewHelperService.createContextInfo()));
889                 }
890             }
891         } catch (Exception e) {
892             LOG.error("Make Official Failed for Acal",e);
893             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_ACAL_OFFICIAL_FAILED + " - " + e.getMessage());
894             return false;
895         }
896         return true;
897     }
898 
899     /**
900      * Saves changes made to an academic calendar.
901      *
902      * @param academicCalendarForm - Form containing the data from the page.
903      * @return The updated calendar after save.
904      */
905     private AcademicCalendarForm saveAcademicCalendarDirtyFields(AcademicCalendarForm academicCalendarForm){
906         AcademicCalendarViewHelperService viewHelperService = getAcalViewHelperService(academicCalendarForm);
907 
908         // Convert Raw UI data and prepare it for save.
909         viewHelperService.populateAcademicCalendarDefaults(academicCalendarForm);
910         // Validate Acal
911         viewHelperService.validateAcademicCalendar(academicCalendarForm);
912 
913         if (GlobalVariables.getMessageMap().getErrorCount() > 0){
914             // If there are errors in the validation return current calendar without saving
915             return academicCalendarForm;
916         }
917 
918         // Create list of dirty fields by seperating string from page (See enroll.js:saveAcalPreProcess())
919         List<String> dirtyFields = processDirtyFields(academicCalendarForm);
920 
921         // Save the base Academic calendar info and refresh it in the form
922         AcademicCalendarInfo newAcal = saveAcal(academicCalendarForm.getAcademicCalendarInfo(), academicCalendarForm, viewHelperService);
923         academicCalendarForm.setAcademicCalendarInfo(newAcal);
924 
925         // Save the dirty field information
926         academicCalendarForm = saveDirtyFieldChanges(academicCalendarForm, dirtyFields,viewHelperService);
927 
928         // Check for new Acal Events and save them
929         academicCalendarForm = saveAcalEvents(academicCalendarForm,viewHelperService);
930 
931         // Check for deleted Acal Events and delete them from database
932         deleteAcalEvents(academicCalendarForm,viewHelperService);
933 
934         // Check for new terms and save them
935         academicCalendarForm = saveTerms(academicCalendarForm,viewHelperService);
936 
937         // Check for deleted terms and delete them from database
938         deleteTerms(academicCalendarForm, viewHelperService);
939 
940         // Check keydates in terms
941         for(int i = 0; i < academicCalendarForm.getTermWrapperList().size();i++){
942             // Check for new key dates and save them
943             academicCalendarForm = saveKeyDates(academicCalendarForm,i,viewHelperService);
944 
945             // Check for deleted key dates and delete them from database
946             AcademicTermWrapper term = academicCalendarForm.getTermWrapperList().get(i);
947             deleteKeyDates(term, viewHelperService);
948 
949             // update instructionalDays
950             try{
951                 term.setInstructionalDays(getAcalService().getInstructionalDaysForTerm(term.getTermInfo().getId(), viewHelperService.createContextInfo()));
952             }catch (Exception ex){
953                 // If the lookup fails message user
954                 LOG.error("Unable to load instructional days",ex);
955                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_CALCULATING_INSTRUCTIONAL_DAYS, term.getStartDate().toString(), term.getEndDate().toString());
956             }
957         }
958 
959         // Reset values
960         academicCalendarForm.getEventsToDeleteOnSave().clear();
961         academicCalendarForm.getFieldsToSave().clear();
962         academicCalendarForm.setDirtyFields("");
963         academicCalendarForm.getTermsToDeleteOnSave().clear();
964         academicCalendarForm.setNewCalendar(false);
965 
966         // Successful save message
967         if(!(GlobalVariables.getMessageMap().getErrorCount()>0)){
968             GlobalVariables.getMessageMap().addGrowlMessage("", CalendarConstants.MessageKeys.INFO_ACADEMIC_CALENDAR_SAVED, academicCalendarForm.getAcademicCalendarInfo().getName());
969         }
970 
971         academicCalendarForm.setMeta(academicCalendarForm.getAcademicCalendarInfo().getMeta());
972 
973         // Reseting added collection items since they were saved
974         academicCalendarForm.setAddedCollectionItems(new ArrayList<Object>());
975 
976         //sort term wrappers by start date
977         viewHelperService.sortTermWrappers(academicCalendarForm.getTermWrapperList());
978 
979         // Return new form
980         return academicCalendarForm;
981     }
982 
983     /**
984      * Cycles through the list of dirty fields, determines what property they correspond to and updates them.
985      *
986      * @param form - View form containing the Calendar information
987      * @param dirtyFields - List of properties that have unsaved information
988      * @param helperService - View Helper service
989      * @return The updated form
990      */
991     private AcademicCalendarForm saveDirtyFieldChanges(AcademicCalendarForm form, List<String>dirtyFields, AcademicCalendarViewHelperService helperService){
992         List<String> updatedFields = new ArrayList<String>();
993 
994         // Cycle through the dirty field list and save the individual properties.
995         for(String field : dirtyFields){
996             if(field.isEmpty()) continue;
997 
998             // Remove sub properties from the one to save
999             field = field.substring(0,field.lastIndexOf("."));
1000 
1001             // Check if the property has already been saved.
1002             boolean alreadyUpdated = false;
1003             for(int j=0;j<updatedFields.size();j++){
1004                 if(field.compareTo(updatedFields.get(j))==0){
1005                     alreadyUpdated=true;
1006                     break;
1007                 }
1008             }
1009             if(alreadyUpdated) continue;
1010 
1011             // Add field to list of saved fields
1012             updatedFields.add(field);
1013 
1014             // Search for the save process for the field
1015             if(field.contains("newCollectionLines")){
1016                 // Catch known dirty field that are not handled by save
1017                 continue;
1018             }else if(field.contains("academicCalendarInfo")){
1019                 // Academic calendar info is always saved
1020                 continue;
1021             } else if(field.contains("events")){
1022 
1023                 // Save an individual event and refresh it in the form
1024                 int index = processFieldIndex(field);
1025                 AcalEventWrapper event = form.getEvents().get(index);
1026                 AcalEventWrapper newEvent = saveAcalEvent(event,form, helperService);
1027                 form.getEvents().set(index, newEvent);
1028 
1029             } else if(field.contains("keydates")){
1030 
1031                 // Save an individual key date change and refresh it in the form
1032                 int termIndex = processFieldIndex(field.substring(0, field.indexOf(".")));
1033                 int keyDateGroupIndex = processFieldIndex(field.substring(field.indexOf("."), field.lastIndexOf(".")));
1034                 int keyDateIndex = processFieldIndex( field.substring(field.lastIndexOf(".")));
1035                 KeyDateWrapper  keyDateWrapper = form.getTermWrapperList().get(termIndex).getKeyDatesGroupWrappers().get(keyDateGroupIndex).getKeydates().get(keyDateIndex);
1036                 KeyDateWrapper newKeyDateWrapper = saveKeyDate(keyDateWrapper, form.getTermWrapperList().get(termIndex), helperService);
1037                 form.getTermWrapperList().get(termIndex).getKeyDatesGroupWrappers().get(keyDateGroupIndex).getKeydates().set(keyDateIndex,newKeyDateWrapper);
1038 
1039             } else if(field.contains("termWrapperList")){
1040 
1041                 // Save and individual even and refresh it in the form
1042                 int index = processFieldIndex(field);
1043                 AcademicTermWrapper term = form.getTermWrapperList().get(index);
1044                 AcademicTermWrapper newTerm = saveTerm(term, form, helperService);
1045                 form.getTermWrapperList().set(index,newTerm);
1046 
1047             } else {
1048                 // Signal that there is an unknown field found.
1049                 LOG.warn("Unknown field encounter during save: "+field);
1050             }
1051         }
1052         return form;
1053     }
1054 
1055     /**
1056      * Save changes to a calendar or create it if it has not already been saved
1057      *
1058      * @param acal - Calendar to be saved
1059      * @param form - View form containing the Calendar information
1060      * @param helperService - View Helper service
1061      * @return The updated calendar with information filled in from the save/create
1062      */
1063     private AcademicCalendarInfo saveAcal(AcademicCalendarInfo acal, AcademicCalendarForm form, AcademicCalendarViewHelperService helperService){
1064         // Process holiday calendar info and get calendar info base
1065         AcademicCalendarInfo acalInfo = processHolidayCalendars(form);
1066 
1067         // Save term to database
1068         try {
1069             if (StringUtils.isBlank(acal.getId())) {
1070                 // Fill in calendar information starting values
1071                 acalInfo.setStateKey(AcademicCalendarServiceConstants.ACADEMIC_CALENDAR_DRAFT_STATE_KEY);
1072                 acalInfo.setTypeKey(AcademicCalendarServiceConstants.ACADEMIC_CALENDAR_TYPE_KEY);
1073                 RichTextInfo rti = new RichTextInfo();
1074                 rti.setPlain(acalInfo.getName());
1075                 acalInfo.setDescr(rti);
1076 
1077                 // Save the key date to the database and return created information
1078                 AcademicCalendarInfo newAcal = getAcalService().createAcademicCalendar(AcademicCalendarServiceConstants.ACADEMIC_CALENDAR_TYPE_KEY, acalInfo, helperService.createContextInfo());
1079                 return newAcal;
1080             } else {
1081 
1082                 // Update the key date in the datebase and return updated information.
1083                 AcademicCalendarInfo updatedAcal = getAcalService().updateAcademicCalendar(acal.getId(), acal, helperService.createContextInfo());
1084                 return updatedAcal;
1085 
1086             }
1087         } catch (VersionMismatchException e){
1088 
1089             // If the calendar being worked on is out of date set up reload and message user
1090             form.setReload(true);
1091             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, RiceKeyConstants.ERROR_CUSTOM,"You are saving an older version of this calendar. Please click on the reload button to get the newer version.");
1092             return acal;
1093 
1094         } catch(Exception e) {
1095 
1096             // If the save fails message user
1097             LOG.error("Add/update Academic calendar failed", e);
1098             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_ACAL_SAVE_FAILED);
1099             return acal;
1100         }
1101     }
1102 
1103     /**
1104      * Cycles through the list of terms and saves any new terms detected.
1105      *
1106      * @param form - View form containing the Calendar information
1107      * @param helperService - View Helper service
1108      * @return The updated form.
1109      */
1110     private AcademicCalendarForm saveTerms(AcademicCalendarForm form, AcademicCalendarViewHelperService helperService){
1111         // Check for new terms and save them
1112         List<AcademicTermWrapper> subTermsToSave = new ArrayList<AcademicTermWrapper>();
1113         for(int i=0;i<form.getTermWrapperList().size();i++){
1114             AcademicTermWrapper term = form.getTermWrapperList().get(i);
1115             if(term.getTermInfo().getId()==null){
1116                 if(term.isSubTerm()){
1117                     // Subterms require the parent term to exist so wait and save all other terms are saved
1118                     subTermsToSave.add(term);
1119                 } else{
1120                     // Save the new term and refresh it in the form
1121                     AcademicTermWrapper newTerm = saveTerm(term,form,helperService);
1122                     form.getTermWrapperList().set(i,newTerm);
1123                 }
1124             }
1125         }
1126         // Save subterms from before
1127         for(AcademicTermWrapper subterm : subTermsToSave){
1128             int index = form.getTermWrapperList().indexOf(subterm);
1129             // Save the new term and refresh it in the form
1130             AcademicTermWrapper newTerm = saveTerm(subterm,form,helperService);
1131             form.getTermWrapperList().set(index,newTerm);
1132         }
1133 
1134         return form;
1135     }
1136 
1137     /**
1138      * Save changes to a term or create it if it has not already been saved
1139      *
1140      * @param termWrapper - The term to be saved
1141      * @param form - View form containing the Calendar information
1142      * @param helperService - View Helper service
1143      * @return The updated term with information filled in from the save/create
1144      */
1145     private AcademicTermWrapper saveTerm(AcademicTermWrapper termWrapper, AcademicCalendarForm form, AcademicCalendarViewHelperService helperService){
1146         // Create term info base
1147         TermInfo term = termWrapper.getTermInfo();
1148 
1149         // Fill in key date info from the wrapper
1150         term.setEndDate(termWrapper.getEndDate());
1151         term.setStartDate(termWrapper.getStartDate());
1152         term.setName(termWrapper.getName());
1153         term.setTypeKey(termWrapper.getTermType());
1154 
1155         // Save term to database
1156         try{
1157             if (termWrapper.isNew() && !termWrapper.isSubTerm()){
1158                 // If term is new and not a sub term.
1159                 // Save the term to the database and update wrapper information.
1160                 TermInfo newTerm = getAcalService().createTerm(termWrapper.getTermType(),term,helperService.createContextInfo());
1161                 termWrapper.setTermInfo(newTerm);
1162                 // Add term to the calendar
1163                 getAcalService().addTermToAcademicCalendar(form.getAcademicCalendarInfo().getId(),termWrapper.getTermInfo().getId(),helperService.createContextInfo());
1164             }else if(termWrapper.isNew() && termWrapper.isSubTerm()){
1165                 // If term is new and is a sub term.
1166 
1167                 //Find parent term
1168                 String parentTermTypeKey = termWrapper.getParentTerm();
1169                 TermInfo parentTermInfo = getParentTerm(form.getAcademicCalendarInfo().getId(), parentTermTypeKey,helperService);
1170 
1171                 // Check if Parent term exists
1172                 if(parentTermInfo == null){
1173                     // If not throw exception
1174                     throw new Exception("Parent Term does not exist. Therefor unable to save subterm.");
1175                 }else{
1176                     // If parent exist fill in parent information in term.
1177                     termWrapper.setParentTermInfo(parentTermInfo);
1178                     // Save the term to the database and update wrapper information.
1179                     TermInfo newTerm = getAcalService().createTerm(termWrapper.getTermType(),term,helperService.createContextInfo());
1180                     termWrapper.setTermInfo(newTerm);
1181                     // Add link to parent term
1182                     getAcalService().addTermToTerm(termWrapper.getParentTermInfo().getId(), termWrapper.getTermInfo().getId(), helperService.createContextInfo());
1183 
1184                     // Add link to calendar
1185                     getAcalService().addTermToAcademicCalendar(form.getAcademicCalendarInfo().getId(),termWrapper.getTermInfo().getId(),helperService.createContextInfo());
1186                 }
1187             }else {
1188                 //If term already exists
1189                 // Update the term in the datebase adn update wrapper information.
1190                 TermInfo updatedTerm = getAcalService().updateTerm(term.getId(),term,helperService.createContextInfo());
1191                 termWrapper.setTermInfo(updatedTerm);
1192             }
1193         }catch(Exception e){
1194             LOG.error("Save term has failed", e);
1195             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_ACAL_SAVE_TERM_SAVE_FAILED,
1196                     termWrapper.getName(), e.getLocalizedMessage());
1197         }
1198 
1199         return termWrapper;
1200     }
1201 
1202     /**
1203      * Determines terms that have been deleted in the UI and deletes them from the database
1204      *
1205      * @param form - View form containing the Calendar information
1206      * @param helperService - View Helper service
1207      */
1208     private void deleteTerms(AcademicCalendarForm form, AcademicCalendarViewHelperService helperService){
1209         for (AcademicTermWrapper term : form.getTermsToDeleteOnSave()){
1210             try{
1211                 getAcademicCalendarServiceFacade().deleteTermCascaded(term.getTermInfo().getId(),helperService.createContextInfo());
1212             }catch(Exception e){
1213                 LOG.error("Delete term has failed",e);
1214                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_DELETING,"Term",term.getName());
1215 
1216             }
1217         }
1218     }
1219 
1220     /**
1221      * Cycles through the key date groups and their list of key dates and saves any new keydates detected
1222      *
1223      * @param form - View form containing the Calendar information
1224      * @param termIndex - The index of the term.
1225      * @param helperService - View Helper service
1226      * @return The updated form.
1227      */
1228     private AcademicCalendarForm saveKeyDates(AcademicCalendarForm form, int termIndex, AcademicCalendarViewHelperService helperService){
1229         AcademicTermWrapper term = form.getTermWrapperList().get(termIndex);
1230         for( int j = 0; j<term.getKeyDatesGroupWrappers().size();j++){
1231             KeyDatesGroupWrapper keyDateGroup = term.getKeyDatesGroupWrappers().get(j);
1232             for(int k = 0; k<keyDateGroup.getKeydates().size();k++){
1233                 KeyDateWrapper keyDate = keyDateGroup.getKeydates().get(k);
1234                 if(keyDate.getKeyDateInfo().getId() ==  null){
1235                     KeyDateWrapper newKeyDate= saveKeyDate(keyDate,term,helperService);
1236                     form.getTermWrapperList().get(termIndex).getKeyDatesGroupWrappers().get(j).getKeydates().set(k,newKeyDate);
1237                 }
1238             }
1239         }
1240         return form;
1241     }
1242 
1243     /**
1244      * Save changes to a keydate or create it if it has not already been saved
1245      *
1246      * @param keyDateWrapper - KeyDate to be saved
1247      * @param term - Term containing the key date
1248      * @param helperService - View helper service
1249      * @return The updated keydate with information filled in from the save/create
1250      */
1251     private KeyDateWrapper saveKeyDate(KeyDateWrapper keyDateWrapper, AcademicTermWrapper term, AcademicCalendarViewHelperService helperService){
1252         // Create key date info base
1253         KeyDateInfo keyDate = keyDateWrapper.getKeyDateInfo();
1254 
1255         // Fill in key date info from the wrapper
1256         keyDate.setTypeKey(keyDateWrapper.getKeyDateType());
1257         keyDate.setName(keyDateWrapper.getKeyDateNameUI());
1258         keyDate.setIsAllDay(keyDateWrapper.isAllDay());
1259         keyDate.setIsDateRange(keyDateWrapper.isDateRange());
1260         keyDate.setStartDate(getDateInfoForKeyDate(keyDateWrapper.isAllDay(),keyDateWrapper.getStartDate(),keyDateWrapper.getStartTime(),keyDateWrapper.getStartTimeAmPm()));
1261         if (keyDateWrapper.isDateRange()){
1262             keyDate.setEndDate(getDateInfoForKeyDate(keyDateWrapper.isAllDay(),keyDateWrapper.getEndDate(),keyDateWrapper.getEndTime(),keyDateWrapper.getEndTimeAmPm()));
1263         } else{
1264             keyDate.setEndDate(null);
1265         }
1266 
1267         // Save Key date to database
1268         try{
1269             if (keyDateWrapper.isNew()){
1270                 // Save the key date to the database and update wrapper information.
1271                 keyDate.setStateKey(AtpServiceConstants.MILESTONE_DRAFT_STATE_KEY);
1272                 KeyDateInfo createdKeyDate = getAcalService().createKeyDate(term.getTermInfo().getId(),keyDate.getTypeKey(),keyDate,helperService.createContextInfo());
1273                 keyDateWrapper.setKeyDateInfo(createdKeyDate);
1274             } else {
1275                 // Update the key date in the datebase adn update wrapper information.
1276                 KeyDateInfo updatedKeyDate = getAcalService().updateKeyDate(keyDate.getId(), keyDate, helperService.createContextInfo());
1277                 keyDateWrapper.setKeyDateInfo(updatedKeyDate);
1278             }
1279         }catch(Exception e){
1280             LOG.error("Save keydate has failed",e);
1281             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_ACAL_SAVE_TERM_KEYDATE_FAILED,keyDateWrapper.getKeyDateNameUI(),term.getName());
1282 
1283         }
1284 
1285         return keyDateWrapper;
1286     }
1287 
1288     /**
1289      * Determines kay dates that have been deleted in the UI and deletes them from the database
1290      *
1291      * @param term - term wrapper from form
1292      * @param helperService - View Helper service
1293      */
1294     private void deleteKeyDates(AcademicTermWrapper term, AcademicCalendarViewHelperService helperService){
1295         for(KeyDateWrapper keyDate : term.getKeyDatesToDeleteOnSave()){
1296             try{
1297                 getAcalService().deleteKeyDate(keyDate.getKeyDateInfo().getId(),helperService.createContextInfo());
1298             }catch(Exception e){
1299                 LOG.error("Delete key date has failed",e);
1300                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_DELETING,term.getName(),keyDate.getKeyDateNameUI());
1301             }
1302         }
1303         term.getKeyDatesToDeleteOnSave().clear();
1304     }
1305 
1306     /**
1307      * Cycles through the list of events and saves any new events detected
1308      *
1309      * @param form - View form containing the Calendar information
1310      * @param helperService - View Helper service
1311      * @return The updated form.
1312      */
1313     private AcademicCalendarForm saveAcalEvents(AcademicCalendarForm form, AcademicCalendarViewHelperService helperService){
1314         for(int i=0;i<form.getEvents().size();i++){
1315             AcalEventWrapper event = form.getEvents().get(i);
1316             if(event.getAcalEventInfo().getId()==null){
1317                 AcalEventWrapper newEvent = saveAcalEvent(event,form,helperService);
1318                 form.getEvents().set(i,newEvent);
1319             }
1320         }
1321         return form;
1322     }
1323 
1324     /**
1325      * Save changes to an event or create it if it has not already been saved
1326      *
1327      * @param event - The event to be created
1328      * @param form - View form containing the Calendar information
1329      * @param helperService - The view helper service
1330      * @return The updated event with the saved information from its creation.
1331      */
1332     private AcalEventWrapper saveAcalEvent(AcalEventWrapper event, AcademicCalendarForm form, AcademicCalendarViewHelperService helperService){
1333         // Create event info base
1334         AcalEventInfo eventInfo = event.getAcalEventInfo();
1335 
1336         // Fill in event info from the wrapper
1337         RichTextInfo rti = new RichTextInfo();
1338         rti.setPlain(event.getEventTypeKey());
1339         eventInfo.setDescr(rti);
1340         eventInfo.setTypeKey(event.getEventTypeKey());
1341         eventInfo.setIsAllDay(event.isAllDay());
1342         eventInfo.setIsDateRange(event.isDateRange());
1343         eventInfo.setStartDate(getDateInfoForKeyDate(event.isAllDay(),event.getStartDate(),event.getStartTime(),event.getStartTimeAmPm()));
1344         if(event.isDateRange()){
1345             eventInfo.setEndDate(getDateInfoForKeyDate(event.isAllDay(),event.getEndDate(),event.getEndTime(),event.getEndTimeAmPm()));
1346         } else{
1347             eventInfo.setEndDate(null);
1348         }
1349         // If calendar is official event is too
1350         if (!form.isOfficialCalendar()){
1351             eventInfo.setStateKey(AtpServiceConstants.MILESTONE_DRAFT_STATE_KEY);
1352         } else {
1353             eventInfo.setStateKey(AtpServiceConstants.MILESTONE_OFFICIAL_STATE_KEY);
1354         }
1355 
1356         // Save Event to database
1357         try{
1358             if(eventInfo.getId()==null){
1359                 // Save the event to the database and update wrapper information.
1360                 AcalEventInfo createdEventInfo = getAcalService().createAcalEvent(form.getAcademicCalendarInfo().getId(), eventInfo.getTypeKey(), eventInfo, helperService.createContextInfo());
1361                 event.setAcalEventInfo(createdEventInfo);
1362             }else{
1363                 // Update the event already in the database and update wrapper information.
1364                 AcalEventInfo updatedEventInfo = getAcalService().updateAcalEvent(eventInfo.getId(), eventInfo, helperService.createContextInfo());
1365                 event.setAcalEventInfo(updatedEventInfo);
1366             }
1367         }catch(Exception e){
1368             LOG.error("Save calendar event has failed" , e);
1369             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_ACAL_SAVE_EVENT_FAILED,event.getEventTypeName());
1370 
1371         }
1372 
1373         return event;
1374     }
1375 
1376     /**
1377      * Determines events that have been deleted in the UI and deletes them from the database
1378      *
1379      * @param form - View form containing the Calendar information
1380      * @param helperService - View Helper service
1381      */
1382     private void deleteAcalEvents(AcademicCalendarForm form, AcademicCalendarViewHelperService helperService){
1383         for(AcalEventWrapper event : form.getEventsToDeleteOnSave()){
1384             try{
1385                 getAcalService().deleteAcalEvent(event.getAcalEventInfo().getId(),helperService.createContextInfo());
1386             }catch(Exception e){
1387                 LOG.error("Delete calendar event has failed" , e);
1388                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MessageKeys.ERROR_DELETING,"Calendar event",event.getEventTypeName());
1389             }
1390         }
1391     }
1392 
1393     /**
1394      * Finds and returns an array index of a property from its field name
1395      *
1396      * @param field - The property field string in the form propertyName[#]
1397      * @return The index of the array slot referenced in the property.
1398      */
1399     private int processFieldIndex(String field){
1400         String indexChar = field.substring(field.indexOf("[")+1, field.lastIndexOf("]"));
1401         return Integer.parseInt(indexChar);
1402     }
1403 
1404     /**
1405      * Finds and returns the parent term of a subterm
1406      *
1407      * @param acalId - Id of the calendar containing the subterm
1408      * @param parentTermTypeKey - The type key of the parent term
1409      * @param helperService - the view helper service
1410      * @return The term info for the parent term
1411      * @throws Exception - Exception thrown by the call to the academic calendar service
1412      */
1413     private TermInfo getParentTerm(String acalId, String parentTermTypeKey, AcademicCalendarViewHelperService helperService) throws Exception{
1414 
1415         List<TermInfo> termInfoList =  getAcalService().getTermsForAcademicCalendar(acalId, helperService.createContextInfo());
1416         for(TermInfo termInfo : termInfoList){
1417             if (parentTermTypeKey.equals(termInfo.getTypeKey())) {
1418                 return termInfo;
1419             }
1420         }
1421         return null;
1422     }
1423 
1424     /**
1425      * Creates a Date object with just date or date and time based on if the event is all day or not
1426      *
1427      * @param isAllDay - Whether event is all day or not
1428      * @param date - The MM/dd/yyyy date
1429      * @param time - A string of the time
1430      * @param ampm - A string of whether the time is am or pm
1431      * @return A completed date object based on isAllDay
1432      */
1433     private Date getDateInfoForKeyDate(boolean isAllDay, Date date, String time, String ampm){
1434         if(!isAllDay){
1435             return CommonUtils.getDateWithTime(date, time, ampm);
1436         }
1437         return date;
1438     }
1439 
1440     /**
1441      * Compiles the list of Holiday ids saved in the form to a new list and adds it to the academicCalendarInfo.
1442      *
1443      * @param academicCalendarForm - View form containing the Calendar information
1444      * @return An updated academic calendar info with list of hcals
1445      */
1446     private AcademicCalendarInfo processHolidayCalendars(AcademicCalendarForm academicCalendarForm)    {
1447         AcademicCalendarInfo acalInfo = academicCalendarForm.getAcademicCalendarInfo();
1448         List<HolidayCalendarWrapper> holidayCalendarList = academicCalendarForm.getHolidayCalendarList();
1449         List<String> holidayCalendarIds = new ArrayList<String>();
1450         if (holidayCalendarList != null && !holidayCalendarList.isEmpty()) {
1451             for (HolidayCalendarWrapper hcWrapper : holidayCalendarList){
1452                 holidayCalendarIds.add(hcWrapper.getHolidayCalendarInfo().getId());
1453             }
1454         }
1455 
1456         // if the list from the form is empty, then all holiday calendars have been removed (or none have been assigned)
1457         acalInfo.setHolidayCalendarIds(holidayCalendarIds);
1458         academicCalendarForm.setAcademicCalendarInfo(acalInfo);
1459 
1460         return acalInfo;
1461     }
1462 
1463     /**
1464      * Processes the the string of dirty fields on the form and stores
1465      * (Mainly to prevent loss during redirects during dialogs)
1466      *
1467      * @param academicCalendarForm - View form containing the Calendar information
1468      * @return List of diry fields passed from the screen.
1469      */
1470     private List<String> processDirtyFields(AcademicCalendarForm academicCalendarForm){
1471         String[] tempFields = academicCalendarForm.getDirtyFields().split(",");
1472         List<String> dirtyFields = academicCalendarForm.getFieldsToSave();
1473         StringBuilder completeDirtyFields = new StringBuilder("");
1474         for(String field : tempFields){
1475             boolean alreadySeen = false;
1476             for(String field2 : dirtyFields){
1477                 if(field2.compareTo(field)==0){
1478                     alreadySeen=true;
1479                     break;
1480                 }
1481             }
1482             if(!alreadySeen){
1483                 dirtyFields.add(field);
1484 
1485             }
1486         }
1487         for(String field : dirtyFields){
1488             completeDirtyFields.append(field);
1489             completeDirtyFields.append(",");
1490         }
1491         academicCalendarForm.setDirtyFields(completeDirtyFields.toString());
1492         return dirtyFields;
1493 
1494     }
1495 
1496     /**
1497      * Override of the Krad lightbox return function to allow for returning to the controller without a redirect.
1498      * Redirect causes a page refresh.
1499      */
1500     @Override
1501     @RequestMapping(params = "methodToCall=returnFromLightbox")
1502     public ModelAndView returnFromLightbox(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
1503                                            HttpServletRequest request, HttpServletResponse response) {
1504 
1505         String newMethodToCall;
1506 
1507         // Save user responses from dialog
1508         DialogManager dm = form.getDialogManager();
1509         String dialogId = dm.getCurrentDialogId();
1510         if (dialogId == null) {
1511             newMethodToCall = "start";
1512         } else {
1513             dm.setDialogAnswer(dialogId, form.getDialogResponse());
1514             dm.setDialogExplanation(dialogId, form.getDialogExplanation());
1515             newMethodToCall = dm.getDialogReturnMethod(dialogId);
1516             dm.setCurrentDialogId(null);
1517         }
1518 
1519         // KSENROLL Code Start
1520         form.setMethodToCall(newMethodToCall);
1521 
1522         // Attempt to return to the controller method directly using reflection (look for the matching methodToCall)
1523         for (Method m : this.getClass().getMethods()) {
1524             RequestMapping a = m.getAnnotation(RequestMapping.class);
1525             if (a != null) {
1526                 String[] annotationsParams = a.params();
1527                 for (String param : annotationsParams) {
1528                     if (param.contains("methodToCall=" + newMethodToCall)) {
1529                         try {
1530                             return (ModelAndView) m.invoke(this, form, result, request, response);
1531                         } catch (IllegalAccessException iae) {
1532                             LOG.error("Reflection Invocation failed", iae);
1533                             throw new RuntimeException("Error using reflection in returnFromLightbox", iae);
1534                         } catch (InvocationTargetException ite) {
1535                             LOG.error("Reflection Invocation failed", ite);
1536                             throw new RuntimeException("Error using reflection in returnFromLightbox", ite);
1537                         } catch (IllegalArgumentException iae) {
1538                             LOG.error("Reflection Invocation failed", iae);
1539                             throw new RuntimeException("Error using reflection in returnFromLightbox", iae);
1540                         }
1541                     }
1542                 }
1543 
1544             }
1545         }
1546         // KSENROLL Code End
1547 
1548         // call intended controller method
1549         Properties props = new Properties();
1550         props.put(UifParameters.METHOD_TO_CALL, newMethodToCall);
1551         props.put(UifParameters.VIEW_ID, form.getViewId());
1552         props.put(UifParameters.FORM_KEY, form.getFormKey());
1553         props.put(UifParameters.AJAX_REQUEST, "false");
1554 
1555         return performRedirect(form, form.getFormPostUrl(), props);
1556     }
1557 
1558     /**
1559      * Override to process and save dirty fields when adding values.
1560      */
1561     @Override
1562     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=addLine")
1563     public ModelAndView addLine(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
1564                                 HttpServletRequest request, HttpServletResponse response) {
1565         ((AcademicCalendarForm)uifForm).setFieldsToSave(processDirtyFields((AcademicCalendarForm)uifForm));
1566         return super.addLine(uifForm,result,request,response);
1567     }
1568 
1569 }