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.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
21  import org.kuali.rice.krad.uif.UifParameters;
22  import org.kuali.rice.krad.util.GlobalVariables;
23  import org.kuali.rice.krad.util.KRADConstants;
24  import org.kuali.rice.krad.util.UrlFactory;
25  import org.kuali.rice.krad.web.controller.UifControllerBase;
26  import org.kuali.rice.krad.web.form.UifFormBase;
27  import org.kuali.student.r2.common.util.constants.AcademicCalendarServiceConstants;
28  import org.kuali.student.enrollment.acal.dto.AcademicCalendarInfo;
29  import org.kuali.student.enrollment.acal.dto.TermInfo;
30  import org.kuali.student.enrollment.acal.service.AcademicCalendarService;
31  import org.kuali.student.enrollment.class2.acal.dto.*;
32  import org.kuali.student.enrollment.class2.acal.form.AcademicCalendarForm;
33  import org.kuali.student.enrollment.class2.acal.util.CalendarConstants;
34  import org.kuali.student.r2.core.constants.AtpServiceConstants;
35  import org.springframework.stereotype.Controller;
36  import org.springframework.validation.BindingResult;
37  import org.springframework.web.bind.annotation.ModelAttribute;
38  import org.springframework.web.bind.annotation.RequestMapping;
39  import org.springframework.web.bind.annotation.RequestMethod;
40  import org.springframework.web.servlet.ModelAndView;
41  
42  import javax.servlet.http.HttpServletRequest;
43  import javax.servlet.http.HttpServletResponse;
44  import javax.xml.namespace.QName;
45  import java.util.*;
46  import org.apache.log4j.Logger;
47  
48  /**
49   * This controller handles all the request from Academic calendar UI.
50   *
51   * @author Kuali Student Team
52   */
53  
54  @Controller
55  @RequestMapping(value = "/academicCalendar")
56  public class AcademicCalendarController extends UifControllerBase {
57  
58      private static final Logger LOG = org.apache.log4j.Logger.getLogger(AcademicCalendarController.class);
59  
60      private AcademicCalendarService acalService;
61  
62      @Override
63      protected UifFormBase createInitialForm(HttpServletRequest request) {
64          return new AcademicCalendarForm();
65      }
66  
67      /**
68       * This GET method loads an academic calendar based on the parameters passed into the request.
69       *
70       * These are the supported request parameters
71       * 1. id - Academic Calendar Id to load in to UI
72       * 2. readOnlyView - If true, sets the view as read only
73       * 3. selectTab - can be 'info' or 'term'
74       *
75       */
76      @Override
77      @RequestMapping(method = RequestMethod.GET, params = "methodToCall=start")
78      public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
79                                HttpServletRequest request, HttpServletResponse response) {
80          AcademicCalendarForm acalForm = (AcademicCalendarForm) form;
81  
82          String acalId = request.getParameter(CalendarConstants.CALENDAR_ID);
83  
84          if (StringUtils.isNotBlank(acalId)){
85              try {
86                  loadAcademicCalendar(acalId, acalForm);
87              } catch (Exception ex) {
88                  throw new RuntimeException(ex);
89              }
90          }
91  
92          String readOnlyView = request.getParameter(CalendarConstants.READ_ONLY_VIEW);
93          acalForm.getView().setReadOnly(BooleanUtils.toBoolean(readOnlyView));
94  
95          if (StringUtils.isNotBlank(request.getParameter(CalendarConstants.SELECT_TAB))) {
96              acalForm.setDefaultTabToShow(request.getParameter(CalendarConstants.SELECT_TAB));
97          }
98  
99          return super.start(form, result, request, response);
100     }
101 
102     /**
103      * This method creates a blank academic calendar.
104      */
105     @RequestMapping(params = "methodToCall=createBlankCalendar")
106     public ModelAndView createBlankCalendar(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
107                                             HttpServletRequest request, HttpServletResponse response){
108 
109         acalForm.setAcademicCalendarInfo(new AcademicCalendarInfo());
110         acalForm.setEvents(new ArrayList<AcalEventWrapper>());
111         acalForm.setHolidayCalendarList(new ArrayList<HolidayCalendarWrapper>());
112         acalForm.setTermWrapperList(new ArrayList<AcademicTermWrapper>());
113 
114         return getUIFModelAndView(acalForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
115     }
116 
117     /**
118      * This GET method is called before the Create New Academic Calendar page is displayed
119      *
120      * It fills in the original Acal for the form with the latest calendar found, by default
121      */
122     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=startNew")
123     public ModelAndView startNew( @ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
124                                   HttpServletRequest request, HttpServletResponse response) {
125 
126         try {
127             AcademicCalendarInfo acalInfo = acalForm.getViewHelperService().getLatestAcademicCalendar();
128             acalForm.setOrgAcalInfo(acalInfo);
129         }
130         catch (Exception x) {
131             throw new RuntimeException(x);
132         }
133 
134 
135         return getUIFModelAndView(acalForm);
136     }
137 
138     @RequestMapping(params = "methodToCall=toEdit")
139     public ModelAndView toEdit(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
140                                               HttpServletRequest request, HttpServletResponse response){
141         AcademicCalendarInfo acalInfo = acalForm.getAcademicCalendarInfo();
142         AcademicCalendarInfo orgAcalInfo = acalForm.getOrgAcalInfo();
143 
144         if (StringUtils.isBlank(acalInfo.getId()) && StringUtils.isNotBlank(orgAcalInfo.getId())){
145             try{
146                 loadAcademicCalendar(orgAcalInfo.getId(), acalForm);
147              } catch (Exception ex) {
148                  throw new RuntimeException("unable to getAcademicCalendar");
149             }
150             acalForm.setOrgAcalInfo(new AcademicCalendarInfo());
151         }
152 
153         acalForm.getView().setReadOnly(false);
154 
155         return getUIFModelAndView(acalForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
156     }
157 
158     @RequestMapping(method = RequestMethod.GET, params = "methodToCall=copyForNew")
159     public ModelAndView copyForNew( @ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
160                                   HttpServletRequest request, HttpServletResponse response) {
161 
162         AcademicCalendarInfo acalInfo = null;
163 
164         String acalId = request.getParameter(CalendarConstants.CALENDAR_ID);
165         if (acalId != null && !acalId.trim().isEmpty()) {
166             String pageId = request.getParameter(CalendarConstants.PAGE_ID);
167             if (CalendarConstants.ACADEMIC_CALENDAR_COPY_PAGE.equals(pageId)) {
168 
169                 try {
170                     acalInfo= getAcalService().getAcademicCalendar(acalId, acalForm.getContextInfo());
171                     acalForm.setOrgAcalInfo(acalInfo);
172 
173                 } catch (Exception ex) {
174                     throw new RuntimeException(ex);
175                 }
176             }
177         }
178         else {
179             // try to get the AC from the form (in case of copy from the Acal view page) and set it as the Original Acal
180             try {
181                 acalInfo = acalForm.getAcademicCalendarInfo();
182                 acalForm.reset();
183                 acalForm.setNewCalendar(true);
184                 acalForm.setOrgAcalInfo(acalInfo);
185             }
186             catch (Exception x) {
187                 throw new RuntimeException(x);
188             }
189 
190         }
191         return copy(acalForm, result, request, response);
192     }
193 
194     /**
195      * Passes on request from Acal view to copy the Acal to the copyForNew method.  Needed a forwarder here because the
196      * call is a GET rather than a POST
197      *
198      * @param acalForm
199      * @param result
200      * @param request
201      * @param response
202      * @return
203      */
204     @RequestMapping(params = "methodToCall=toCopy")
205     public ModelAndView toCopy(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
206                                               HttpServletRequest request, HttpServletResponse response){
207 
208         return copyForNew(acalForm, result, request, response);
209     }
210 
211     //copy over from the existing AcalInfo to create a new
212     @RequestMapping(method = RequestMethod.POST, params="methodToCall=copy")
213     public ModelAndView copy( @ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
214                               HttpServletRequest request, HttpServletResponse response) {
215         try {
216            acalForm.getViewHelperService().copyToCreateAcademicCalendar(acalForm);
217         }catch (Exception ex) {
218             throw new RuntimeException(ex);
219         }
220 
221         return getUIFModelAndView(acalForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
222 
223     }
224 
225     //Editing Hcal is implemented fully and it's working.. but we're having some issues with KRAD form management
226     //This will be implemented in future milestones
227     @RequestMapping(method = RequestMethod.POST, params="methodToCall=editHolidayCalendar")
228     public ModelAndView editHolidayCalendar( @ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
229                                             HttpServletRequest request, HttpServletResponse response) {
230 
231         String selectedCollectionPath = acalForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
232         if (StringUtils.isBlank(selectedCollectionPath)) {
233             throw new RuntimeException("unable to determine the selected collection path");
234         }
235 
236         int selectedLineIndex = -1;
237         String selectedLine = acalForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
238         if (StringUtils.isNotBlank(selectedLine)) {
239             selectedLineIndex = Integer.parseInt(selectedLine);
240         }
241 
242         if (selectedLineIndex == -1) {
243             throw new RuntimeException("unable to determine the selected line index");
244         }
245 
246         Properties hcalURLParam = new Properties();
247         hcalURLParam.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, CalendarConstants.HC_EDIT_METHOD);
248         hcalURLParam.put(CalendarConstants.CALENDAR_ID, acalForm.getHolidayCalendarList().get(selectedLineIndex).getId());
249         hcalURLParam.put(UifParameters.VIEW_ID, CalendarConstants.HOLIDAYCALENDAR_FLOWVIEW);
250         hcalURLParam.put(UifParameters.PAGE_ID, CalendarConstants.HOLIDAYCALENDAR_EDITPAGE);
251         hcalURLParam.put(UifParameters.RETURN_FORM_KEY, acalForm.getFormKey());
252 
253         Properties acalReturnURLParams = new Properties();
254         acalReturnURLParams.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, CalendarConstants.AC_EDIT_METHOD);
255         acalReturnURLParams.put(UifParameters.VIEW_ID, CalendarConstants.ACAL_VIEW);
256         acalReturnURLParams.put(UifParameters.PAGE_ID, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
257         String returnUrl = UrlFactory.parameterizeUrl(CalendarConstants.ACAL_CONTROLLER_PATH, acalReturnURLParams);
258         hcalURLParam.put(UifParameters.RETURN_LOCATION, returnUrl);
259 
260         return super.performRedirect(acalForm,CalendarConstants.HCAL_CONTROLLER_PATH, hcalURLParam);
261 
262     }
263 
264 
265     /**
266      * redirect to search Calendar page
267      */
268     @RequestMapping(params = "methodToCall=search")
269     public ModelAndView search(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
270                              HttpServletRequest request, HttpServletResponse response) throws Exception {
271 
272         String controllerPath = CalendarConstants.CALENDAR_SEARCH_CONTROLLER_PATH;
273         Properties urlParameters = new Properties();
274         urlParameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.START_METHOD);
275         urlParameters.put(UifParameters.VIEW_ID, CalendarConstants.CALENDAR_SEARCH_VIEW);
276         return super.performRedirect(acalForm,controllerPath, urlParameters);
277     }
278 
279 
280     /**
281      * Method used to save AcademicCalendar
282      */
283     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=save")
284     public ModelAndView save(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
285                              HttpServletRequest request, HttpServletResponse response) {
286         return saveAcademicCalendar(academicCalendarForm, CalendarConstants.MSG_INFO_ACADEMIC_CALENDAR_SAVED, false);
287     }
288 
289     /**
290      * Method used to delete AcademicCalendar
291      */
292     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=delete")
293     public ModelAndView delete(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm, BindingResult result,
294                                    HttpServletRequest request, HttpServletResponse response) throws Exception {
295 
296         acalForm.getViewHelperService().deleteAcademicCalendar(acalForm.getAcademicCalendarInfo().getId());
297 
298         GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MSG_INFO_SEARCH_DELETE_SUCCESS, acalForm.getAcademicCalendarInfo().getName());
299 
300         Properties urlParameters = new  Properties();
301         urlParameters.put("viewId", CalendarConstants.ENROLLMENT_HOME_VIEW);
302         urlParameters.put("methodToCall", KRADConstants.START_METHOD);
303         return performRedirect(acalForm, request.getRequestURL().toString(), urlParameters);
304     }
305 
306     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=cancelTerm")
307     public ModelAndView cancelTerm(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
308                                         HttpServletRequest request, HttpServletResponse response) {
309 
310         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
311         if (StringUtils.isBlank(selectedCollectionPath)) {
312             throw new RuntimeException("unable to determine the selected collection path");
313         }
314 
315         int selectedLineIndex = -1;
316         String selectedLine = academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
317         if (StringUtils.isNotBlank(selectedLine)) {
318             selectedLineIndex = Integer.parseInt(selectedLine);
319         }
320 
321         if (selectedLineIndex == -1) {
322             throw new RuntimeException("unable to determine the selected line index");
323         }
324 
325         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
326 
327         if (termWrapper.isNew()){
328            academicCalendarForm.getTermWrapperList().remove(selectedLineIndex);
329         }else{
330             try {
331                 TermInfo termInfo = getAcalService().getTerm(termWrapper.getTermInfo().getId(), academicCalendarForm.getContextInfo());
332                 AcademicTermWrapper termWrapperFromDB = academicCalendarForm.getViewHelperService().populateTermWrapper(termInfo, false);
333                 academicCalendarForm.getTermWrapperList().set(selectedLineIndex,termWrapperFromDB);
334 
335                try{
336                     academicCalendarForm.getViewHelperService().populateInstructionalDays(termWrapperFromDB);
337                 }catch(Exception e){
338                     //TODO: FIXME: Have to handle the error.. but for now, as it's causing issue, just skipping calculation when there are errors
339                     e.printStackTrace();
340                 }
341             } catch (Exception e) {
342                 throw new RuntimeException(e);
343             }
344         }
345 
346         return getUIFModelAndView(academicCalendarForm);
347     }
348 
349     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=makeTermOfficial")
350     public ModelAndView makeTermOfficial(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
351                                         HttpServletRequest request, HttpServletResponse response) {
352 
353         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
354         if (StringUtils.isBlank(selectedCollectionPath)) {
355             throw new RuntimeException("unable to determine the selected collection path");
356         }
357 
358         int selectedLineIndex = -1;
359         String selectedLine = academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
360         if (StringUtils.isNotBlank(selectedLine)) {
361             selectedLineIndex = Integer.parseInt(selectedLine);
362         }
363 
364         if (selectedLineIndex == -1) {
365             throw new RuntimeException("unable to determine the selected line index");
366         }
367 
368         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
369 
370         academicCalendarForm.getViewHelperService().validateTerm(academicCalendarForm.getTermWrapperList(),selectedLineIndex,academicCalendarForm.getAcademicCalendarInfo());
371 
372         if (GlobalVariables.getMessageMap().getErrorCount() > 0){
373            return getUIFModelAndView(academicCalendarForm);
374         }
375 
376         try{
377             boolean alreadyOfficial = StringUtils.equals(AtpServiceConstants.ATP_OFFICIAL_STATE_KEY,academicCalendarForm.getAcademicCalendarInfo().getStateKey());
378             String messageText = alreadyOfficial ? "info.enroll.term.saved" : "info.enroll.term.official";
379             academicCalendarForm.getViewHelperService().saveTerm(termWrapper, academicCalendarForm.getAcademicCalendarInfo().getId(),true);
380             GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_ERRORS, messageText, termWrapper.getTermNameForUI());
381             // GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_ERRORS,"info.enroll.term.official",termWrapper.getTermNameForUI());
382         }catch (Exception e){
383            throw new RuntimeException(e);
384         }
385 
386        try{
387             academicCalendarForm.getViewHelperService().populateInstructionalDays(termWrapper);
388         }catch(Exception e){
389             //TODO: FIXME: Have to handle the error.. but for now, as it's causing issue, just skipping calculation when there are errors
390             e.printStackTrace();
391         }
392 
393         return getUIFModelAndView(academicCalendarForm);
394     }
395 
396     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=cancelAddingTerm")
397     public ModelAndView cancelAddingTerm(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
398                                         HttpServletRequest request, HttpServletResponse response) {
399 
400         ((AcademicTermWrapper)academicCalendarForm.getNewCollectionLines().get("termWrapperList")).clear();
401 
402         return getUIFModelAndView(academicCalendarForm);
403     }
404 
405     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=cancelAddingHoliday")
406     public ModelAndView cancelAddingHoliday(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
407                                         HttpServletRequest request, HttpServletResponse response) {
408 
409         ((HolidayCalendarWrapper)academicCalendarForm.getNewCollectionLines().get("holidayCalendarList")).setId(StringUtils.EMPTY);
410 
411         return getUIFModelAndView(academicCalendarForm);
412     }
413 
414     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteTerm")
415     public ModelAndView deleteTerm(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
416                                         HttpServletRequest request, HttpServletResponse response) {
417 
418         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
419         if (StringUtils.isBlank(selectedCollectionPath)) {
420             throw new RuntimeException("unable to determine the selected collection path");
421         }
422 
423         int selectedLineIndex = -1;
424         String selectedLine = academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
425         if (StringUtils.isNotBlank(selectedLine)) {
426             selectedLineIndex = Integer.parseInt(selectedLine);
427         }
428 
429         if (selectedLineIndex == -1) {
430             throw new RuntimeException("unable to determine the selected line index");
431         }
432 
433         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(selectedLineIndex);
434 
435         if (!termWrapper.isNew()){
436             academicCalendarForm.getTermsToDeleteOnSave().add(termWrapper);
437         }
438 
439         academicCalendarForm.getTermWrapperList().remove(selectedLineIndex);
440 
441         return getUIFModelAndView(academicCalendarForm);
442 
443     }
444 
445     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteKeyDate")
446     public ModelAndView deleteKeyDate(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
447                                         HttpServletRequest request, HttpServletResponse response) {
448 
449         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
450         if (StringUtils.isBlank(selectedCollectionPath)) {
451             throw new RuntimeException("unable to determine the selected collection path");
452         }
453 
454         int selectedLineIndex = -1;
455         String selectedLine = academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
456         if (StringUtils.isNotBlank(selectedLine)) {
457             selectedLineIndex = Integer.parseInt(selectedLine);
458         }
459 
460         if (selectedLineIndex == -1) {
461             throw new RuntimeException("unable to determine the selected line index");
462         }
463 
464         String selectedTermIndex = StringUtils.substringBetween(selectedCollectionPath,"termWrapperList[","]");
465         String selectedKeyDateGroup = StringUtils.substringBetween(selectedCollectionPath,"keyDatesGroupWrappers[","]");
466 
467         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(Integer.parseInt(selectedTermIndex));
468         KeyDatesGroupWrapper keydateGroup = termWrapper.getKeyDatesGroupWrappers().get(Integer.parseInt(selectedKeyDateGroup));
469         KeyDateWrapper keyDateWrapper = keydateGroup.getKeydates().get(selectedLineIndex);
470 
471         if (StringUtils.isNotBlank(keyDateWrapper.getKeyDateInfo().getId())){
472             termWrapper.getKeyDatesToDeleteOnSave().add(keyDateWrapper);
473         }
474 
475         keydateGroup.getKeydates().remove(selectedLineIndex);
476 
477         return getUIFModelAndView(academicCalendarForm);
478 
479     }
480 
481     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteKeyDateGroup")
482     public ModelAndView deleteKeyDateGroup(@ModelAttribute("KualiForm") AcademicCalendarForm academicCalendarForm, BindingResult result,
483                                            HttpServletRequest request, HttpServletResponse response) {
484 
485         String selectedCollectionPath = academicCalendarForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
486         if (StringUtils.isBlank(selectedCollectionPath)) {
487             throw new RuntimeException("unable to determine the selected collection path");
488         }
489 
490         int selectedLineIndex = -1;
491         String selectedLine = academicCalendarForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
492         if (StringUtils.isNotBlank(selectedLine)) {
493             selectedLineIndex = Integer.parseInt(selectedLine);
494         }
495 
496         if (selectedLineIndex == -1) {
497             throw new RuntimeException("unable to determine the selected line index");
498         }
499 
500         String selectedTermIndex = StringUtils.substringBetween(selectedCollectionPath,"termWrapperList[","]");
501 
502         AcademicTermWrapper termWrapper = academicCalendarForm.getTermWrapperList().get(Integer.parseInt(selectedTermIndex));
503         KeyDatesGroupWrapper keydateGroup = termWrapper.getKeyDatesGroupWrappers().get(selectedLineIndex);
504         for (KeyDateWrapper keyDateWrapper : keydateGroup.getKeydates()) {
505             if (StringUtils.isNotBlank(keyDateWrapper.getKeyDateInfo().getId())){
506                 termWrapper.getKeyDatesToDeleteOnSave().add(keyDateWrapper);
507             }
508         }
509 
510         termWrapper.getKeyDatesGroupWrappers().remove(keydateGroup);
511 
512         return getUIFModelAndView(academicCalendarForm);
513 
514     }
515 
516     /**
517      * Method used to set Acal as official
518      */
519     @RequestMapping(method = RequestMethod.POST, params = "methodToCall=makeAcalOfficial")
520     public ModelAndView makeAcalOfficial(@ModelAttribute("KualiForm") AcademicCalendarForm acalForm) throws Exception {
521         return saveAcademicCalendar(acalForm, CalendarConstants.MSG_INFO_ACADEMIC_CALENDAR_OFFICIAL, true);
522     }
523 
524     private void loadAcademicCalendar(String acalId, AcademicCalendarForm acalForm) throws Exception {
525 
526         AcademicCalendarInfo acalInfo = getAcalService().getAcademicCalendar(acalId,acalForm.getContextInfo());
527 
528         acalForm.setAcademicCalendarInfo(acalInfo);
529         acalForm.setAdminOrgName(getAdminOrgNameById(acalInfo.getAdminOrgId()));
530         acalForm.setNewCalendar(false);
531         acalForm.setOfficialCalendar(StringUtils.equals(acalInfo.getStateKey(),AtpServiceConstants.ATP_OFFICIAL_STATE_KEY));
532 
533         List<AcalEventWrapper> events = acalForm.getViewHelperService().populateEventWrappers(acalForm);
534         acalForm.setEvents(events);
535 
536         List<AcademicTermWrapper> termWrappers = acalForm.getViewHelperService().populateTermWrappers(acalId, false);
537         acalForm.setTermWrapperList(termWrappers);
538         
539         List<HolidayCalendarWrapper> holidayCalendarWrapperList = acalForm.getViewHelperService().loadHolidayCalendars(acalInfo);
540         acalForm.setHolidayCalendarList(holidayCalendarWrapperList);
541 
542         //Calculate instructional days (if HC exists)
543         if (acalForm.getHolidayCalendarList() != null && !acalForm.getHolidayCalendarList().isEmpty()) {
544             acalForm.getViewHelperService().populateInstructionalDays(acalForm.getTermWrapperList());
545         }
546 
547     }
548 
549     private AcademicCalendarInfo processHolidayCalendars(AcademicCalendarForm academicCalendarForm)    {
550         AcademicCalendarInfo acalInfo = academicCalendarForm.getAcademicCalendarInfo();
551         List<HolidayCalendarWrapper> holidayCalendarList = academicCalendarForm.getHolidayCalendarList();
552         List<String> holidayCalendarIds = new ArrayList<String>();
553         if (holidayCalendarList != null && !holidayCalendarList.isEmpty()) {
554             for (HolidayCalendarWrapper hcWrapper : holidayCalendarList){
555                 holidayCalendarIds.add(hcWrapper.getHolidayCalendarInfo().getId());
556             }
557         }
558 
559         // if the list from the form is empty, then all holiday calendars have been removed (or none have been assigned)
560         // so an empty list will be assigned to the AcademicCalendarInfo
561         acalInfo.setHolidayCalendarIds(holidayCalendarIds);
562         academicCalendarForm.setAcademicCalendarInfo(acalInfo);
563 
564         return acalInfo;
565     }
566 
567     private ModelAndView saveAcademicCalendar(AcademicCalendarForm academicCalendarForm, String keyToDisplayOnSave, boolean isOfficial) {
568 
569         AcademicCalendarInfo academicCalendarInfo = academicCalendarForm.getAcademicCalendarInfo();
570 
571         // Populate default times
572         academicCalendarForm.getViewHelperService().populateAcademicCalendarDefaults(academicCalendarForm);
573 
574         // Validate Acal
575         academicCalendarForm.getViewHelperService().validateAcademicCalendar(academicCalendarForm);
576         if (GlobalVariables.getMessageMap().getErrorCount() > 0){
577             return getUIFModelAndView(academicCalendarForm);
578         }
579 
580         // If validation succeeds, continue save
581         try {
582             if (StringUtils.isNotBlank(academicCalendarInfo.getId())) {
583                 // 1. update acal and AC-HC relationships
584                 academicCalendarInfo = processHolidayCalendars(academicCalendarForm);
585                 if (isOfficial) {
586                     academicCalendarInfo.setStateKey(AcademicCalendarServiceConstants.ACADEMIC_CALENDAR_OFFICIAL_STATE_KEY);
587                 }
588                 AcademicCalendarInfo acalInfo = getAcalService().updateAcademicCalendar(academicCalendarInfo.getId(), academicCalendarInfo, academicCalendarForm.getContextInfo());
589                 academicCalendarForm.setAcademicCalendarInfo(getAcalService().getAcademicCalendar(acalInfo.getId(), academicCalendarForm.getContextInfo()));
590 
591                 // 2. update acalEvents if any
592                 List<AcalEventWrapper> events = academicCalendarForm.getEvents();
593                 processEvents(academicCalendarForm, events, acalInfo.getId());
594             } else {
595                 AcademicCalendarInfo acalInfo = null;
596                 // 1. create  a new acalInfo with a list of HC Ids
597                 processHolidayCalendars(academicCalendarForm);
598                 acalInfo = academicCalendarForm.getViewHelperService().createAcademicCalendar(academicCalendarForm);
599                 academicCalendarForm.setAcademicCalendarInfo(getAcalService().getAcademicCalendar(acalInfo.getId(), academicCalendarForm.getContextInfo()));
600                 // 2. create new events if any
601                 createEvents(acalInfo.getId(), academicCalendarForm);
602             }
603         } catch(Exception e) {
604             LOG.error("Add or update of Academic Calendar failed.", e);
605             GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MSG_ERROR_ACAL_SAVE_FAILED);
606             return getUIFModelAndView(academicCalendarForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
607         }
608 
609         // Delete terms which are deleted by the user in the ui
610         for (AcademicTermWrapper termWrapper : academicCalendarForm.getTermsToDeleteOnSave()){
611             String termId = termWrapper.getTermInfo().getId();
612             try {
613                 getAcalService().deleteTerm(termId, academicCalendarForm.getContextInfo());
614             } catch(Exception e) {
615                 LOG.error(String.format("Unable to delete term [%s].", termId), e);
616                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MSG_ERROR_ACAL_SAVE_FAILED);
617                 return getUIFModelAndView(academicCalendarForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
618             }
619         }
620 
621         academicCalendarForm.getTermsToDeleteOnSave().clear();
622 
623         // Save Term and keydates
624         for (AcademicTermWrapper termWrapper : academicCalendarForm.getTermWrapperList()){
625             try {
626                 academicCalendarForm.getViewHelperService().saveTerm(termWrapper, academicCalendarForm.getAcademicCalendarInfo().getId(), false);
627             } catch(Exception e) {
628                 LOG.error(String.format("Unable to save term [%s].", termWrapper.getName()), e);
629                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_MESSAGES, CalendarConstants.MSG_ERROR_ACAL_SAVE_TERM_SAVE_FAILED,
630                         termWrapper.getName(), e.getLocalizedMessage());
631                 return getUIFModelAndView(academicCalendarForm, CalendarConstants.ACADEMIC_CALENDAR_EDIT_PAGE);
632             }
633         }
634 
635         // Calculate instructional days (if HC exists)
636         try {
637             academicCalendarForm.getViewHelperService().populateInstructionalDays(academicCalendarForm.getTermWrapperList());
638         } catch(Exception e) {
639             //FIXME: Have to handle the error.. but for now, as it's causing issue, just skipping calculation when there are errors
640             e.printStackTrace();
641         }
642 
643         academicCalendarForm.setNewCalendar(false);
644 
645         if (isOfficial) {
646             academicCalendarForm.setOfficialCalendar(true);
647             academicCalendarForm.getView().setReadOnly(true);
648         }
649 
650         GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_MESSAGES, keyToDisplayOnSave, academicCalendarForm.getAcademicCalendarInfo().getName());
651 
652         return getUIFModelAndView(academicCalendarForm);
653     }
654 
655     private String getAdminOrgNameById(String id){
656         //TODO: hard-coded for now, going to call OrgService
657         String adminOrgName = null;
658         Map<String, String> allAcalOrgs = new HashMap<String, String>();
659         allAcalOrgs.put("102", "Registrar's Office");
660         allAcalOrgs.put("34", "Medical School");
661 
662         if(allAcalOrgs.containsKey(id)){
663             adminOrgName = allAcalOrgs.get(id);
664         }
665 
666         return adminOrgName;
667     }
668 
669     private void createEvents(String acalId, AcademicCalendarForm acalForm) throws Exception {
670         List<AcalEventWrapper> events = acalForm.getEvents();
671 
672         if(events != null && !events.isEmpty()){
673             List<AcalEventWrapper> createdEvents = new ArrayList<AcalEventWrapper>();
674             for (AcalEventWrapper event : events){
675                 createdEvents.add(acalForm.getViewHelperService().createEvent(acalId, event));
676             }
677             acalForm.setEvents(createdEvents);
678         }
679 
680     }
681 
682     /**
683      * Update existing events, create new events, and delete events that do not exist any more when a user modifies and saves an Academic Calendar
684      */
685     private void processEvents(AcademicCalendarForm acalForm, List<AcalEventWrapper> events, String acalId)throws Exception{
686         List<AcalEventWrapper> updatedEvents = new ArrayList<AcalEventWrapper>();
687         List<String> currentEventIds = getExistingEventIds(acalForm);
688         if(events != null && !events.isEmpty()){
689             for(AcalEventWrapper event : events){
690                 if(currentEventIds.contains(event.getAcalEventInfo().getId())){
691                     //update event
692                     AcalEventWrapper updatedEvent = acalForm.getViewHelperService().updateEvent(event.getAcalEventInfo().getId(), event);
693                     updatedEvents.add(updatedEvent);
694                     currentEventIds.remove(event.getAcalEventInfo().getId());
695                 }
696                 else {
697                     //create a new event
698                     AcalEventWrapper createdEvent = acalForm.getViewHelperService().createEvent(acalId, event);
699                     updatedEvents.add(createdEvent);
700                 }
701             }
702         }
703         acalForm.setEvents(updatedEvents);
704 
705         //delete events that have been removed by the user
706         if (currentEventIds != null && currentEventIds.size() > 0){
707             for(String eventId: currentEventIds){
708                 //TODO: delete completely from db, when "deleted" state is available, update the event with state ="deleted"
709                 acalForm.getViewHelperService().deleteEvent(eventId);
710             }
711         }
712 
713     }
714 
715     private List<String> getExistingEventIds(AcademicCalendarForm acalForm) throws Exception{
716         List<AcalEventWrapper> events = acalForm.getViewHelperService().populateEventWrappers(acalForm);
717         List<String> eventIds = new ArrayList<String>();
718 
719         if(events != null && !events.isEmpty()){
720             for(AcalEventWrapper event : events){
721                 eventIds.add(event.getAcalEventInfo().getId());
722             }
723         }
724         return eventIds;
725     }
726 
727 
728     public AcademicCalendarService getAcalService() {
729         if(acalService == null) {
730             acalService = (AcademicCalendarService) GlobalResourceLoader.getService(new QName(AcademicCalendarServiceConstants.NAMESPACE, AcademicCalendarServiceConstants.SERVICE_NAME_LOCAL_PART));
731         }
732         return this.acalService;
733     }
734 
735 
736 }