View Javadoc

1   /**
2    * Copyright 2012 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   *
15   * Created by Charles on 5/7/12
16   */
17  package org.kuali.student.enrollment.class2.courseoffering.controller;
18  
19  import org.apache.commons.lang.UnhandledException;
20  import org.apache.log4j.Logger;
21  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
22  import org.kuali.rice.krad.util.GlobalVariables;
23  import org.kuali.rice.krad.web.controller.UifControllerBase;
24  import org.kuali.rice.krad.web.form.UifFormBase;
25  import org.kuali.student.enrollment.acal.dto.TermInfo;
26  import org.kuali.student.enrollment.class2.courseoffering.dto.SocRolloverResultItemWrapper;
27  import org.kuali.student.enrollment.class2.courseoffering.form.CourseOfferingRolloverManagementForm;
28  import org.kuali.student.enrollment.class2.courseoffering.service.CourseOfferingViewHelperService;
29  import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo;
30  import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService;
31  import org.kuali.student.enrollment.courseofferingset.dto.SocInfo;
32  import org.kuali.student.enrollment.courseofferingset.dto.SocRolloverResultInfo;
33  import org.kuali.student.enrollment.courseofferingset.dto.SocRolloverResultItemInfo;
34  import org.kuali.student.enrollment.courseofferingset.service.CourseOfferingSetService;
35  import org.kuali.student.r2.common.dto.ContextInfo;
36  import org.kuali.student.r2.common.exceptions.*;
37  import org.kuali.student.r2.common.util.ContextUtils;
38  import org.kuali.student.r2.common.util.constants.CourseOfferingServiceConstants;
39  import org.kuali.student.r2.common.util.constants.CourseOfferingSetServiceConstants;
40  import org.kuali.student.r2.core.constants.StateServiceConstants;
41  import org.kuali.student.r2.core.constants.TypeServiceConstants;
42  import org.kuali.student.r2.core.class1.state.dto.StateInfo;
43  import org.kuali.student.r2.core.class1.state.service.StateService;
44  import org.kuali.student.r2.core.class1.type.service.TypeService;
45  import org.springframework.stereotype.Controller;
46  import org.springframework.validation.BindingResult;
47  import org.springframework.web.bind.annotation.ModelAttribute;
48  import org.springframework.web.bind.annotation.RequestMapping;
49  import org.springframework.web.bind.annotation.RequestMethod;
50  import org.springframework.web.servlet.ModelAndView;
51  
52  import javax.servlet.http.HttpServletRequest;
53  import javax.servlet.http.HttpServletResponse;
54  import javax.xml.namespace.QName;
55  import java.text.SimpleDateFormat;
56  import java.util.Date;
57  import java.util.List;
58  import java.util.Map;
59  import java.util.concurrent.CopyOnWriteArrayList;
60  
61  /**
62   * The controller for Perform Rollover, Rollover Details, and Release to Depts page (all within the same view).
63   *
64   * @author Kuali Student Team
65   */
66  @Controller
67  @RequestMapping(value = "/courseOfferingRollover")
68  public class CourseOfferingRolloverController extends UifControllerBase {
69      private CourseOfferingViewHelperService viewHelperService;
70      private CourseOfferingSetService socService;
71      private CourseOfferingService coService;
72      private TypeService typeService;
73      private StateService stateService;
74  
75      final Logger LOGGER = Logger.getLogger(CourseOfferingRolloverController.class);
76      public static final String ROLLOVER_DETAILS_PAGEID = "selectTermForRolloverDetails";
77      public static final String ROLLOVER_CONFIRM_RELEASE = "releaseToDepts";
78  
79      @Override
80      protected UifFormBase createInitialForm(HttpServletRequest request) {
81          return new CourseOfferingRolloverManagementForm();
82      }
83  
84      @Override
85      @RequestMapping(method = RequestMethod.GET, params = "methodToCall=start")
86      public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
87                                HttpServletRequest request, HttpServletResponse response) {
88          CourseOfferingRolloverManagementForm theForm = (CourseOfferingRolloverManagementForm) form;
89          Map paramMap = request.getParameterMap();
90          if (paramMap.containsKey("pageId")) {
91              String pageId = ((String []) paramMap.get("pageId"))[0];
92              if (pageId.equals("selectTermsForRollover")) {
93                  return _startPerformRollover(form, result, request, response);
94              } else if (pageId.equals("releaseToDepts")) {
95                  return _startReleaseToDepts(theForm, result, request, response);
96              } else if (pageId.equals("selectTermForRolloverDetails")) {
97                  return _startRolloverDetails(form, result, request, response);
98              }
99          }
100         return getUIFModelAndView(theForm);
101         // return super.start(theForm, result, request, response);
102     }
103 
104     private ModelAndView _startPerformRollover(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
105                                              HttpServletRequest request, HttpServletResponse response) {
106         CourseOfferingRolloverManagementForm theForm = (CourseOfferingRolloverManagementForm) form;
107         LOGGER.info("startPerformRollover");
108         return getUIFModelAndView(theForm);
109         // return super.start(theForm, result, request, response);
110     }
111 
112     private ModelAndView _startRolloverDetails(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
113                                              HttpServletRequest request, HttpServletResponse response) {
114         CourseOfferingRolloverManagementForm theForm = (CourseOfferingRolloverManagementForm) form;
115         Map map = request.getParameterMap();
116         LOGGER.info("startRolloverDetails");
117         String rolloverTerm = theForm.getRolloverTargetTermCode();
118 
119         try {
120             if (rolloverTerm != null && !"".equals(rolloverTerm)) {
121                 return showRolloverResults(theForm, result, request, response);
122             }
123         } catch (Exception ex){
124             return getUIFModelAndView(theForm);
125         }
126 
127         return getUIFModelAndView(theForm);
128         // return super.start(theForm, result, request, response);
129     }
130 
131     private ModelAndView _startReleaseToDepts(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
132                                             HttpServletRequest request, HttpServletResponse response) {
133         LOGGER.info("startReleaseToDepts");
134         form.computeReleaseToDeptsDisabled();
135         return getUIFModelAndView(form);
136     }
137 
138     @RequestMapping(params = "methodToCall=goTargetTerm")
139     public ModelAndView goTargetTerm(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
140                                      HttpServletRequest request, HttpServletResponse response) throws Exception {
141         CourseOfferingViewHelperService helper = getViewHelperService(form);
142         List<TermInfo> termList = helper.findTermByTermCode(form.getTargetTermCode());
143         if (termList != null && termList.size() == 1) {
144             //validation to check if already rollover target term exists..
145             List<String> coIds = this._getCourseOfferingService().getCourseOfferingIdsByTerm(termList.get(0).getId(), true, new ContextInfo());
146             if (!coIds.isEmpty()) {
147                 // Print error message if there are course offerings in the target term
148                 GlobalVariables.getMessageMap().putError("targetTermCode", "error.courseoffering.rollover.targetTermExists");
149                 form.resetForm();
150                 return getUIFModelAndView(form);
151             }
152             // Get first term
153             TermInfo matchingTerm = termList.get(0);
154             String targetTermCode = matchingTerm.getCode();
155             form.setDisplayedTargetTermCode(targetTermCode);
156             // Set the start date
157             Date startDate = matchingTerm.getStartDate();
158             SimpleDateFormat format = new SimpleDateFormat("EEE, MMMMM d, yyyy");
159             String startDateStr = format.format(startDate);
160             form.setTargetTermStartDate(startDateStr);
161             // Set the end date
162             Date endDate = matchingTerm.getEndDate();
163             String endDateStr = format.format(endDate);
164             form.setTargetTermEndDate(endDateStr);
165             // TODO: Put in last rollover date (Kirk says this may be unnecessary in new wireframes 5/18/2012)
166             form.setTargetTerm(matchingTerm);
167             form.setIsGoSourceButtonDisabled(false); // Make go button for source enabled
168         } else {
169             form.setTargetTerm(null);
170             form.resetForm();
171             GlobalVariables.getMessageMap().putError("targetTermCode", "error.courseoffering.targetTerm.inValid");
172         }
173         return getUIFModelAndView(form);
174     }
175 
176     @RequestMapping(params = "methodToCall=goSourceTerm")
177     public ModelAndView goSourceTerm(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
178                                      HttpServletRequest request, HttpServletResponse response) throws Exception {
179         // validation to check for valid term.
180         if (form.getTargetTermCode() == null || form.getTargetTermCode().length() == 0) {
181             GlobalVariables.getMessageMap().putError("targetTermCode", "error.submit.sourceTerm");
182             return getUIFModelAndView(form);
183         }
184         if (form.getSourceTermCode() == null || form.getSourceTermCode().length() == 0) {
185             GlobalVariables.getMessageMap().putError("sourceTermCode", "error.courseoffering.sourceTerm.inValid");
186             return getUIFModelAndView(form);
187         }
188         CourseOfferingViewHelperService helper = getViewHelperService(form);
189         
190         // validation to check for like terms and target term year comes before source term year.
191         String targetTermCd = form.getTargetTermCode();
192         String sourceTermCd = form.getSourceTermCode();
193         TermInfo targetTerm = helper.findTermByTermCode(targetTermCd).get(0);
194         TermInfo sourceTerm = helper.findTermByTermCode(sourceTermCd).get(0);
195         boolean likeTerms = sourceTerm.getTypeKey().equals(targetTerm.getTypeKey());
196         boolean sourcePrecedesTarget = sourceTerm.getStartDate().before(targetTerm.getStartDate());
197         boolean sourceTermHasSoc = helper.termHasSoc(sourceTerm.getId(), form);
198         if (!likeTerms) {
199             GlobalVariables.getMessageMap().putError("sourceTermCode", "error.likeTerms.validation");
200             form.setIsRolloverButtonDisabled(true);
201             return getUIFModelAndView(form);
202         } else if (!sourcePrecedesTarget) {
203             GlobalVariables.getMessageMap().putError("sourceTermCode", "error.years.validation");
204             form.setIsRolloverButtonDisabled(true);
205             return getUIFModelAndView(form);
206         } else if (!sourceTermHasSoc) {
207             GlobalVariables.getMessageMap().putError("sourceTermCode", "error.rollover.sourceTerm.noSoc");
208             form.setIsRolloverButtonDisabled(true);
209             return getUIFModelAndView(form);
210         }
211 
212         List<TermInfo> termList = helper.findTermByTermCode(form.getSourceTermCode());
213         if (termList != null && termList.size() == 1) {
214             // Get first term
215             TermInfo matchingTerm = termList.get(0);
216             String sourceTermCode = matchingTerm.getCode();
217             form.setDisplayedSourceTermCode(sourceTermCode);
218             // Set the start date
219             Date startDate = matchingTerm.getStartDate();
220             SimpleDateFormat format = new SimpleDateFormat("EEE, MMMMM d, yyyy");
221             String startDateStr = format.format(startDate);
222             form.setSourceTermStartDate(startDateStr);
223             // Set the end date
224             Date endDate = matchingTerm.getEndDate();
225             String endDateStr = format.format(endDate);
226             form.setSourceTermEndDate(endDateStr);
227             form.setSourceTerm(matchingTerm);
228             form.setIsRolloverButtonDisabled(false); // Enable the button
229         } else {
230             form.setTargetTerm(null);
231             form.resetForm();
232             GlobalVariables.getMessageMap().putError("soucrceTermCode", "error.courseoffering.sourceTerm.inValid");
233         }
234         return getUIFModelAndView(form);
235     }
236 
237     @RequestMapping(params = "methodToCall=performRollover")
238     public ModelAndView performRollover(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
239                                         HttpServletRequest request, HttpServletResponse response) throws Exception {
240         CourseOfferingViewHelperService helper = getViewHelperService(form);
241 
242         if (form.getSourceTerm() == null || form.getTargetTerm() == null) {
243             form.setStatusField("(setUp) Source/target term objects appear to be missing");
244             return getUIFModelAndView(form);
245         }
246         form.setStatusField("");
247         String sourceTermId = form.getSourceTerm().getId();
248         String targetTermId = form.getTargetTerm().getId();
249 
250         boolean success = helper.performRollover(sourceTermId, targetTermId, form);
251         if (success) {
252             form.setRolloverTargetTermCode(form.getTargetTermCode());
253             showRolloverResults(form, result, request, response); // TODO: Factor out a common method?
254             // Switch to rollover details page
255             return start(form, result, request, response);
256             //return getUIFModelAndView(form, ROLLOVER_DETAILS_PAGEID);
257         } else{
258             // Had problems, stay in the same screen
259             return getUIFModelAndView(form);
260         }
261     }
262 
263     @RequestMapping(params = "methodToCall=setUpSourceTerm")
264     public ModelAndView setUpSourceTerm(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
265                                         HttpServletRequest request, HttpServletResponse response) throws Exception {
266         CourseOfferingViewHelperService helper = getViewHelperService(form);
267 
268         if (form.getSourceTerm() == null || form.getTargetTerm() == null) {
269             form.setStatusField("(setUp) Source/target term objects appear to be missing");
270             return getUIFModelAndView(form);
271         }
272         form.setStatusField("");
273         // Delete previous SOC and course offerings (allows for us to redefine SOC/course offering later on
274 
275         boolean success = helper.cleanSourceTerm(form.getSourceTerm().getId(), form);
276         if (success) {
277             helper.createSocCoFoAoForTerm(form.getSourceTerm().getId(), form);
278         }
279         return getUIFModelAndView(form);
280     }
281 
282     @RequestMapping(params = "methodToCall=performReverseRollover")
283     public ModelAndView performReverseRollover(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
284                                                HttpServletRequest request, HttpServletResponse response) throws Exception {
285         CourseOfferingViewHelperService helper = getViewHelperService(form);
286         if (form.getSourceTerm() == null || form.getTargetTerm() == null) {
287             form.setStatusField("(cleanUp) Source/target term objects appear to be missing");
288             return getUIFModelAndView(form);
289         }
290         form.setStatusField("");
291 
292         String sourceTermId = form.getSourceTerm().getId();
293         String targetTermId = form.getTargetTerm().getId();
294         SocRolloverResultInfo info = helper.performReverseRollover(sourceTermId, targetTermId, form);
295         if (info != null) {
296             form.setStatusField("Num items processed: " + info.getItemsProcessed());
297         }
298         return getUIFModelAndView(form);
299     }
300 
301     public CourseOfferingViewHelperService getViewHelperService(CourseOfferingRolloverManagementForm rolloverForm) {
302         if (viewHelperService == null) {
303             if (rolloverForm.getView().getViewHelperServiceClass() != null) {
304                 viewHelperService = (CourseOfferingViewHelperService) rolloverForm.getView().getViewHelperService();
305             } else {
306                 viewHelperService = (CourseOfferingViewHelperService) rolloverForm.getPostedView().getViewHelperService();
307             }
308         }
309         return viewHelperService;
310     }
311 
312     private void _disableReleaseToDeptsIfNeeded(CourseOfferingViewHelperService helper, String targetTermId,
313                                                 CourseOfferingRolloverManagementForm form) {
314         SocInfo socInfo = helper.getMainSoc(targetTermId);
315         if (socInfo == null) { 
316             // Disable if no term found
317             form.setReleaseToDeptsInvalidTerm(true);
318         } else {
319             String stateKey = socInfo.getStateKey();
320             if (!CourseOfferingSetServiceConstants.DRAFT_SOC_STATE_KEY.equals(stateKey)) {
321                 // Assume it's been released if no longer in draft state (TODO: may not be true--revisit)
322                 form.setSocReleasedToDepts(true);
323             } else { // In draft state
324                 form.setSocReleasedToDepts(false);
325             }
326         } 
327     }
328 
329     private String _computeRolloverDuration(Date dateInitiated, Date dateCompleted) {
330         long diffInMillis = dateCompleted.getTime() - dateInitiated.getTime();
331         long diffInSeconds = diffInMillis / 1000;
332         int minutes = (int)(diffInSeconds / 60);
333         int seconds = (int)(diffInSeconds % 60);
334         int hours = minutes / 60;
335         minutes = minutes % 60;
336         String result = seconds + "s";
337         if (minutes > 0 || hours > 0) {
338             result = minutes + "m " + result;
339         }
340         if (hours > 0) {
341             result = hours + "h " + result;
342         }
343         return result;
344     }
345 
346     private String _createPlural(int count) {
347         return count == 1 ? "" : "s";
348     }
349      
350     private String _createStatusString(SocRolloverResultInfo socRolloverResultInfo) {
351         String status = "";
352         String stateKey = socRolloverResultInfo.getStateKey();
353         if (CourseOfferingSetServiceConstants.SUBMITTED_RESULT_STATE_KEY.equals(stateKey) ||
354                 CourseOfferingSetServiceConstants.RUNNING_RESULT_STATE_KEY.equals(stateKey)) {
355             status = " (in progress)";
356         } else if (CourseOfferingSetServiceConstants.ABORTED_RESULT_STATE_KEY.equals(stateKey)) {
357             status = " (aborted)";
358         }
359         return status;
360     }
361     
362     private void _setStatus(String stateKey, CourseOfferingRolloverManagementForm form) {
363         if (CourseOfferingSetServiceConstants.FINISHED_RESULT_STATE_KEY.equals(stateKey)) {
364             form.setStatusField("Finished");
365             form.setRolloverCompleted(true);
366         } else if (CourseOfferingSetServiceConstants.RUNNING_RESULT_STATE_KEY.equals(stateKey) ||
367                 CourseOfferingSetServiceConstants.SUBMITTED_RESULT_STATE_KEY.equals(stateKey)) {
368             form.setStatusField("In Progress");
369             form.setRolloverCompleted(false);
370         } else if (CourseOfferingSetServiceConstants.ABORTED_RESULT_STATE_KEY.equals(stateKey)) {
371             form.setRolloverCompleted(true);
372         }
373     }
374 
375     private void _displayRolloverInfo(SocInfo socInfo, SocRolloverResultInfo socRolloverResultInfo,
376                                       CourseOfferingRolloverManagementForm form, CourseOfferingViewHelperService helper,
377                                       String stateKey, String targetTermId) {
378         if (socInfo != null) {
379             // Set some display fields that show friendly, human-readable term data
380             String friendlySourceTermDesc = helper.getTermDesc(socInfo.getTermId());
381             form.setRolloverSourceTermDesc(friendlySourceTermDesc);
382             String friendlyTargetTermDesc = helper.getTermDesc(targetTermId);
383             form.setRolloverTargetTermDesc(friendlyTargetTermDesc);
384         }
385         Date dateInitiated = socRolloverResultInfo.getDateInitiated();
386         String startDateStr = helper.formatDateAndTime(dateInitiated);
387         form.setDateInitiated(startDateStr);
388         // if items skipped is null, then below condition passes and items skipped is calculated
389         if (socRolloverResultInfo.getCourseOfferingsCreated() == null || socRolloverResultInfo.getCourseOfferingsCreated().toString().length() < 1) {
390             Integer temp = socRolloverResultInfo.getItemsExpected() - socRolloverResultInfo.getItemsProcessed();
391             String plural = _createPlural(temp);
392             form.setCourseOfferingsAllowed(socRolloverResultInfo.getItemsProcessed() + " transitioned with " + temp + " exception" + plural);
393         } else {
394             // This is the official way to compute this
395             String plural = _createPlural(socRolloverResultInfo.getCourseOfferingsSkipped());
396             form.setCourseOfferingsAllowed(socRolloverResultInfo.getCourseOfferingsCreated() + " transitioned with " +
397                     socRolloverResultInfo.getCourseOfferingsSkipped() + " exception" + plural);
398         }
399         String plural = _createPlural(socRolloverResultInfo.getActivityOfferingsSkipped());
400         form.setActivityOfferingsAllowed(socRolloverResultInfo.getActivityOfferingsCreated() + " transitioned with " +
401                 socRolloverResultInfo.getActivityOfferingsSkipped() + " exception" + plural);
402         Date dateCompleted = socRolloverResultInfo.getDateCompleted();
403         String updatedDateStr = helper.formatDateAndTime(dateCompleted);
404         // The status displays whether the time is in progress or aborted or nothing if it's completed.
405         String status = _createStatusString(socRolloverResultInfo);
406         if ((CourseOfferingSetServiceConstants.SUBMITTED_RESULT_STATE_KEY.equals(stateKey) ||
407                 CourseOfferingSetServiceConstants.RUNNING_RESULT_STATE_KEY.equals(stateKey)) ) {
408             form.setDateCompleted("Rollover in progress");  // DanS doesn't want a date completed if still in progress
409         } else {
410             form.setDateCompleted(updatedDateStr + status);
411         }
412         // Set value on how long rollover has been running
413         String rolloverDuration = _computeRolloverDuration(dateInitiated, dateCompleted);
414         form.setRolloverDuration(rolloverDuration + status);
415     }
416 
417     private void _displayRolloverItems(CourseOfferingRolloverManagementForm form,
418                                        List<SocRolloverResultItemInfo> socRolloverResultItemInfos,
419                                        List<SocRolloverResultItemInfo> socRolloverResultItemInfosCopy)
420             throws InvalidParameterException, MissingParameterException, DoesNotExistException, PermissionDeniedException,
421             OperationFailedException {
422         // Clear out the existing list of result items
423         form.getSocRolloverResultItems().clear();
424 
425         for (SocRolloverResultItemInfo socRolloverResultItemInfo : socRolloverResultItemInfosCopy) {
426             if (CourseOfferingSetServiceConstants.SUCCESSFUL_RESULT_ITEM_STATES.contains(socRolloverResultItemInfo.getStateKey())) {
427                 socRolloverResultItemInfos.remove(socRolloverResultItemInfo);
428             } else {
429                 String courseOfferingId = socRolloverResultItemInfo.getTargetCourseOfferingId();
430                 if (courseOfferingId == null || courseOfferingId.isEmpty()){
431                     courseOfferingId = socRolloverResultItemInfo.getSourceCourseOfferingId();
432                 }
433 
434                 CourseOfferingInfo courseOfferingInfo = _getCourseOfferingService().getCourseOffering(courseOfferingId, new ContextInfo());
435                 SocRolloverResultItemWrapper socRolloverResultItemWrapper = new SocRolloverResultItemWrapper();
436                 socRolloverResultItemWrapper.setCourse(courseOfferingInfo.getCourseOfferingCode());
437                 if (socRolloverResultItemInfo.getMessage() != null) {
438                     socRolloverResultItemWrapper.setMessage(socRolloverResultItemInfo.getMessage().getPlain());
439                 }
440                 socRolloverResultItemWrapper.setState(socRolloverResultItemInfo.getStateKey());
441 
442                 try {
443                     StateInfo stateInfo = this._getStateService().getState(socRolloverResultItemInfo.getStateKey(), ContextUtils.getContextInfo());
444                     if (stateInfo != null){
445                         socRolloverResultItemWrapper.setStateName((stateInfo.getName() != null) ? stateInfo.getName() : socRolloverResultItemInfo.getStateKey());
446                     }
447                 } catch (DoesNotExistException ex){
448                     socRolloverResultItemWrapper.setStateName(socRolloverResultItemInfo.getStateKey());
449                 }
450 
451 
452                 form.getSocRolloverResultItems().add(socRolloverResultItemWrapper);
453             }
454         }
455     }
456     // This method displays rollover result Infos for specific target term.
457     @RequestMapping(params = "methodToCall=showRolloverResults")
458     public ModelAndView showRolloverResults(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
459                                             HttpServletRequest request, HttpServletResponse response) throws Exception {
460         //helper class for courseOfferingSetService
461         CourseOfferingViewHelperService helper = getViewHelperService(form);
462         //To fetch Term by code which is desirable.
463         String targetTermCode = form.getRolloverTargetTermCode();
464         List<TermInfo> termList = helper.findTermByTermCode(targetTermCode);
465         if (termList.isEmpty()) {
466             GlobalVariables.getMessageMap().putError("rolloverTargetTermCode", "error.rollover.targetTerm.noResults", targetTermCode);
467             form.resetForm(); // TODO: Does this make sense?  I don't think so. cclin
468             return getUIFModelAndView(form);
469         } else {
470             TermInfo targetTerm = termList.get(0);
471             form.setTargetTerm(targetTerm);
472             form.setTargetTermCode(targetTermCode);
473             String targetTermId = targetTerm.getId();
474             // Get rollover result info for target term
475             List<SocRolloverResultInfo> socRolloverResultInfos = helper.findRolloverByTerm(targetTermId);
476             if (socRolloverResultInfos == null || socRolloverResultInfos.isEmpty()) {
477                 GlobalVariables.getMessageMap().putError("rolloverTargetTermCode", "error.rollover.targetTerm.noResults", targetTermCode);
478                 form.resetForm(); // TODO: Does this make sense?  I don't think so. cclin
479                 return getUIFModelAndView(form);
480             } else {
481                 if (socRolloverResultInfos.size() > 1) {
482                     LOGGER.warn("Multiple Soc Rollover Results Found");
483                 }
484                 _disableReleaseToDeptsIfNeeded(helper, targetTermId, form);
485                 SocRolloverResultInfo socRolloverResultInfo = socRolloverResultInfos.get(0);
486                 String stateKey = socRolloverResultInfo.getStateKey();
487                 _setStatus(stateKey, form);
488                 // SocInfo service to get Source Term Id
489                 SocInfo socInfo = _getSocService().getSoc(socRolloverResultInfo.getSourceSocId(), new ContextInfo());
490                 // Put info in the display fields on the left hand side
491                 _displayRolloverInfo(socInfo, socRolloverResultInfo, form, helper, stateKey, targetTermId);
492               
493                 // CourseOfferingSet service to get Soc Rollover ResultItems by socResultItemInfo id
494                 try {
495                     List<SocRolloverResultItemInfo> socRolloverResultItemInfos =
496                             _getSocService().getSocRolloverResultItemsByResultId(socRolloverResultInfo.getId(), new ContextInfo());
497                     List<SocRolloverResultItemInfo> socRolloverResultItemInfosCopy =
498                             new CopyOnWriteArrayList<SocRolloverResultItemInfo>(socRolloverResultItemInfos);
499 
500                     _displayRolloverItems(form, socRolloverResultItemInfos, socRolloverResultItemInfosCopy);
501                 } catch (UnhandledException ue) {
502                     throw new RuntimeException(ue);
503                 } catch (DoesNotExistException dne) {
504                     throw new RuntimeException(dne);
505                 }
506             } 
507         } 
508         return getUIFModelAndView(form, ROLLOVER_DETAILS_PAGEID);
509     }
510 
511     /**
512      * This is used in the release to depts page from
513      * CourseOfferingRolloverManagement-ReleaseToDeptsPage.xml
514      */
515     @RequestMapping(params = "methodToCall=releaseToDepts")
516     public ModelAndView releaseToDepts(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
517                                             HttpServletRequest request, HttpServletResponse response) throws Exception {
518         LOGGER.info("releaseToDepts");
519         CourseOfferingViewHelperService helper = getViewHelperService(form);
520         boolean accept = form.getAcceptIndicator();
521         TermInfo targetTerm = form.getTargetTerm();
522         if (!accept) {
523             // Didn't click approval
524             GlobalVariables.getMessageMap().putError("approveCheckbox", "error.rollover.release.notApproved");
525         } else if (targetTerm == null) {
526             // Didn't get term info from Rollover Results page
527             GlobalVariables.getMessageMap().putError("approveCheckbox", "error.rollover.invalidTerm");
528         } else {
529             // We're good!
530             LOGGER.info("Ready to release to depts");
531             SocInfo socInfo = helper.getMainSoc(targetTerm.getId());
532             if (!socInfo.getStateKey().equals(CourseOfferingSetServiceConstants.DRAFT_SOC_STATE_KEY)) {
533                 // If it's not draft, then set variable to disable release to depts in the UI
534                 form.setSocReleasedToDepts(true);
535             } else {
536                 // It's draft, so change to state to open
537                 socInfo.setStateKey(CourseOfferingSetServiceConstants.OPEN_SOC_STATE_KEY);
538                 // Persist the state change
539                 _getSocService().updateSoc(socInfo.getId(), socInfo, new ContextInfo());
540                 form.setSocReleasedToDepts(true);
541             }
542             // Do a refresh of the data on rollover details
543             showRolloverResults(form, result, request, response);
544         }
545         return getUIFModelAndView(form);
546     }
547 
548     @RequestMapping(params = "methodToCall=checkApproval")
549     public ModelAndView checkApproval(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
550                                             HttpServletRequest request, HttpServletResponse response) throws Exception {
551         LOGGER.info("checkApproval " + form.getAcceptIndicator());
552         return getUIFModelAndView(form);
553     }
554 
555     @RequestMapping(params = "methodToCall=redoRollover")
556     public ModelAndView redoRollover(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
557                                       HttpServletRequest request, HttpServletResponse response) throws Exception {
558         LOGGER.info("redoRollover ");
559         return getUIFModelAndView(form);
560     }
561 
562     @RequestMapping(params = "methodToCall=confirmReleaseToDepts")
563     public ModelAndView confirmReleaseToDepts(@ModelAttribute("KualiForm") CourseOfferingRolloverManagementForm form, BindingResult result,
564                                               HttpServletRequest request, HttpServletResponse response) throws Exception {
565         LOGGER.info("confirmReleaseToDepts ");
566         return getUIFModelAndView(form, ROLLOVER_CONFIRM_RELEASE);
567     }
568 
569     private CourseOfferingSetService _getSocService() {
570         if (socService == null) {
571             socService = (CourseOfferingSetService) GlobalResourceLoader.getService(new QName(CourseOfferingSetServiceConstants.NAMESPACE,
572                     CourseOfferingSetServiceConstants.SERVICE_NAME_LOCAL_PART));
573         }
574         return socService;
575     }
576 
577     private CourseOfferingService _getCourseOfferingService() {
578         if (coService == null) {
579             coService = (CourseOfferingService) GlobalResourceLoader.getService(new QName(CourseOfferingServiceConstants.NAMESPACE,
580                     CourseOfferingServiceConstants.SERVICE_NAME_LOCAL_PART));
581         }
582         return coService;
583     }
584 
585     private TypeService _getTypeService() {
586         if (typeService == null) {
587             typeService = (TypeService) GlobalResourceLoader.getService(new QName(TypeServiceConstants.NAMESPACE,
588                     TypeServiceConstants.SERVICE_NAME_LOCAL_PART));
589         }
590         return typeService;
591     }
592 
593     private StateService _getStateService() {
594         if (stateService == null) {
595             stateService = (StateService) GlobalResourceLoader.getService(new QName(StateServiceConstants.NAMESPACE,
596                     StateServiceConstants.SERVICE_NAME_LOCAL_PART));
597         }
598         return stateService;
599     }
600 }