View Javadoc

1   package org.kuali.student.enrollment.class2.courseoffering.service.impl;
2   
3   import org.apache.commons.lang.StringUtils;
4   import org.kuali.rice.core.api.criteria.PredicateFactory;
5   import org.kuali.rice.core.api.criteria.QueryByCriteria;
6   import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
7   import org.kuali.rice.core.api.util.RiceKeyConstants;
8   import org.kuali.rice.krad.uif.service.impl.ViewHelperServiceImpl;
9   import org.kuali.rice.krad.util.GlobalVariables;
10  import org.kuali.student.enrollment.acal.dto.TermInfo;
11  import org.kuali.student.enrollment.acal.service.AcademicCalendarService;
12  import org.kuali.student.enrollment.class2.courseoffering.dto.ActivityOfferingWrapper;
13  import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingEditWrapper;
14  import org.kuali.student.enrollment.class2.courseoffering.form.CourseOfferingManagementForm;
15  import org.kuali.student.enrollment.class2.courseoffering.service.CourseOfferingManagementViewHelperService;
16  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingConstants;
17  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingResourceLoader;
18  import org.kuali.student.enrollment.class2.courseoffering.util.ViewHelperUtil;
19  import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingInfo;
20  import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo;
21  import org.kuali.student.enrollment.courseoffering.dto.FormatOfferingInfo;
22  import org.kuali.student.enrollment.courseoffering.dto.OfferingInstructorInfo;
23  import org.kuali.student.enrollment.courseoffering.dto.RegistrationGroupInfo;
24  import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService;
25  import org.kuali.student.r2.common.dto.ContextInfo;
26  import org.kuali.student.r2.common.dto.LocaleInfo;
27  import org.kuali.student.r2.common.dto.TimeOfDayInfo;
28  import org.kuali.student.r2.common.permutation.PermutationUtils;
29  import org.kuali.student.r2.common.util.constants.AcademicCalendarServiceConstants;
30  import org.kuali.student.r2.common.util.constants.CourseOfferingServiceConstants;
31  import org.kuali.student.r2.common.util.constants.LuiServiceConstants;
32  import org.kuali.student.r2.core.class1.state.dto.StateInfo;
33  import org.kuali.student.r2.core.class1.state.service.StateService;
34  import org.kuali.student.r2.core.class1.type.dto.TypeInfo;
35  import org.kuali.student.r2.core.class1.type.service.TypeService;
36  import org.kuali.student.r2.core.room.dto.BuildingInfo;
37  import org.kuali.student.r2.core.room.dto.RoomInfo;
38  import org.kuali.student.r2.core.room.service.RoomService;
39  import org.kuali.student.r2.core.scheduling.dto.ScheduleRequestComponentInfo;
40  import org.kuali.student.r2.core.scheduling.dto.ScheduleRequestInfo;
41  import org.kuali.student.r2.core.scheduling.dto.TimeSlotInfo;
42  import org.kuali.student.r2.core.scheduling.service.SchedulingService;
43  import org.kuali.student.r2.lum.course.dto.ActivityInfo;
44  import org.kuali.student.r2.lum.course.dto.CourseInfo;
45  import org.kuali.student.r2.lum.course.dto.FormatInfo;
46  import org.kuali.student.r2.lum.course.service.CourseService;
47  import org.kuali.student.r2.lum.lrc.dto.ResultValuesGroupInfo;
48  import org.kuali.student.r2.lum.lrc.service.LRCService;
49  
50  import javax.xml.namespace.QName;
51  import java.text.SimpleDateFormat;
52  import java.util.ArrayList;
53  import java.util.Calendar;
54  import java.util.Collections;
55  import java.util.Comparator;
56  import java.util.GregorianCalendar;
57  import java.util.HashMap;
58  import java.util.List;
59  import java.util.Locale;
60  import java.util.Map;
61  
62  
63  public class CourseOfferingManagementViewHelperServiceImpl extends ViewHelperServiceImpl implements CourseOfferingManagementViewHelperService{
64      private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CourseOfferingManagementViewHelperServiceImpl.class);
65  
66      private transient AcademicCalendarService acalService = null;
67      private transient CourseOfferingService coService = null;
68  
69      private CourseService courseService;
70      private TypeService typeService;
71      private StateService stateService;
72      private transient LRCService lrcService;
73      private SchedulingService schedulingService;
74      private RoomService roomService;
75  
76  
77      public List<TermInfo> findTermByTermCode(String termCode) throws Exception {
78          // TODO: Find sensible way to rewrap exception that acal service may throw
79          // Find the term (alas, I think it does approximate search)
80          QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
81          // TODO: How does one get rid of hard-coding "atpCode"?
82          qbcBuilder.setPredicates(PredicateFactory.equal("atpCode", termCode));
83  
84          QueryByCriteria criteria = qbcBuilder.build();
85  
86          // Do search.  In ideal case, terms returns one element, which is the desired term.
87          AcademicCalendarService acalService = _getAcalService();
88          return acalService.searchForTerms(criteria, new ContextInfo());
89      }
90  
91      public void loadCourseOfferingsByTermAndSubjectCode (String termId, String subjectCode, CourseOfferingManagementForm form) throws Exception{
92          List<String> courseOfferingIds = _getCourseOfferingService().getCourseOfferingIdsByTermAndSubjectArea(termId, subjectCode, getContextInfo());
93          if(courseOfferingIds.size()>0){
94              form.getCourseOfferingEditWrapperList().clear();
95              for(String coId : courseOfferingIds) {
96                  CourseOfferingInfo coInfo = getCourseOfferingService().getCourseOffering(coId, getContextInfo());
97                  coInfo.setCreditCnt(getCreditCount(coInfo, null));
98                  CourseOfferingEditWrapper courseOfferingEditWrapper = new CourseOfferingEditWrapper(coInfo);
99                  courseOfferingEditWrapper.setGradingOption(getGradingOption(coInfo.getGradingOptionId()));
100                 StateInfo state = getStateService().getState(coInfo.getStateKey(),getContextInfo());
101                 courseOfferingEditWrapper.setStateName(state.getName());
102                 form.getCourseOfferingEditWrapperList().add(courseOfferingEditWrapper);
103             }
104         } else {
105             LOG.error("Error: Can't find any Course Offering for a Subject Code: "+subjectCode+" in term: "+termId);
106             GlobalVariables.getMessageMap().putError("inputCode", CourseOfferingConstants.COURSEOFFERING_MSG_ERROR_NO_COURSE_OFFERING_IS_FOUND, "Subject", subjectCode, termId);
107             form.getCourseOfferingEditWrapperList().clear();
108         }
109     }
110 
111 
112     private String getGradingOption(String gradingOptionId) throws Exception {
113           String gradingOption = "";
114           if(StringUtils.isNotBlank(gradingOptionId)){
115               ResultValuesGroupInfo rvg = getLrcService().getResultValuesGroup(gradingOptionId, getContextInfo());
116               if(rvg!= null && StringUtils.isNotBlank(rvg.getName())){
117                  gradingOption = rvg.getName();
118               }
119           }
120           return gradingOption;
121     }
122 
123     public List<CourseOfferingInfo> findCourseOfferingsByTermAndCourseOfferingCode (String termCode, String courseOfferingCode, CourseOfferingManagementForm form) throws Exception{
124         List<CourseOfferingInfo> courseOfferings = new ArrayList<CourseOfferingInfo>();
125         String termId = null;
126 
127         try {
128             //1. get termId based on termCode
129             if (StringUtils.isNotBlank(termCode)) {
130                 QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
131                 qbcBuilder.setPredicates(PredicateFactory.equal(CourseOfferingConstants.ATP_CODE, termCode));
132                 QueryByCriteria criteria = qbcBuilder.build();
133 
134                 // Do search.  In ideal case, termList contains one element, which is the desired term.
135                 List<TermInfo> termList = _getAcalService().searchForTerms(criteria, new ContextInfo());
136 
137                 if (termList != null  && termList.size()>0 ){
138                     // Always get first term
139                     termId = termList.get(0).getId();
140                     System.out.println(">>> termId = "+termId);
141                     if(termList.size()>1){
142                         //logger.warn("AdvanceActivityOfferingLookupableImpl - find more than one term for specified termCode: " + termCode) ;
143                         //System.out.println(">>Alert: find more than one term for specified termCode: "+termCode);
144                         throw new RuntimeException("Alert: find more than one term for specified termCode: "+termCode);
145                     }
146                 } else {
147                     throw new RuntimeException("Error: Does not find a valid term with Term = "+ termCode);
148                 }
149             }
150 
151             //get courseOfferingId based on courseOfferingCode and termId
152             if (StringUtils.isNotBlank(courseOfferingCode) && StringUtils.isNotBlank(termId)) {
153                 QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
154                 qbcBuilder.setPredicates(PredicateFactory.and(
155                         PredicateFactory.equalIgnoreCase(CourseOfferingConstants.COURSEOFFERING_COURSE_OFFERING_CODE, courseOfferingCode),
156                         PredicateFactory.equalIgnoreCase(CourseOfferingConstants.ATP_ID, termId)));
157                 QueryByCriteria criteria = qbcBuilder.build();
158 
159                 //Do search. In ideal case, returns one element, which is the desired CO.
160                 courseOfferings = getCourseOfferingService().searchForCourseOfferings(criteria, new ContextInfo());
161                 if (courseOfferings.size()>0){
162                     for (CourseOfferingInfo coInfo:courseOfferings){
163                         coInfo.setCreditCnt(getCreditCount(coInfo, null));
164                     }
165                 }
166             }
167 
168         } catch (Exception e) {
169             throw new RuntimeException(e);
170         }
171         return courseOfferings;
172     }
173 
174     public void loadPreviousAndNextCourseOffering(CourseOfferingManagementForm form, CourseOfferingInfo courseOfferingInfo){
175         try{
176             List<String> coIds = getCourseOfferingService().getCourseOfferingIdsByTermAndSubjectArea(courseOfferingInfo.getTermId(),courseOfferingInfo.getSubjectArea(),getContextInfo());
177             List<CourseOfferingInfo> courseOfferingInfos = getCourseOfferingService().getCourseOfferingsByIds(coIds,getContextInfo());
178 
179             Collections.sort(courseOfferingInfos, new Comparator<CourseOfferingInfo>() {
180                 @Override
181                 public int compare(CourseOfferingInfo o1, CourseOfferingInfo o2) {
182                     if (o1.getCourseOfferingCode().length() == o2.getCourseOfferingCode().length()) {
183                         return o1.getCourseOfferingCode().compareTo(o2.getCourseOfferingCode());
184                     } else {
185                         return o1.getCourseOfferingCode().length() - o2.getCourseOfferingCode().length();
186                     }
187                 }
188             });
189 
190             for (CourseOfferingInfo offeringInfo : courseOfferingInfos) {
191                 if (StringUtils.equals(courseOfferingInfo.getId(),offeringInfo.getId())){
192                     int currentIndex = courseOfferingInfos.indexOf(offeringInfo);
193                     form.setInputCode(offeringInfo.getCourseOfferingCode());
194                     if (currentIndex > 0){
195                          form.setPreviousCourseOffering(courseOfferingInfos.get(currentIndex-1));
196                     }else{
197                         form.setPreviousCourseOffering(null);
198                     }
199                     if (currentIndex < courseOfferingInfos.size()-1){
200                          form.setNextCourseOffering(courseOfferingInfos.get(currentIndex+1));
201                     }else{
202                         form.setNextCourseOffering(null);
203                     }
204                     break;
205                 }
206             }
207 
208         } catch(Exception e) {
209             throw new RuntimeException(e);
210         }
211     }
212 
213     public void createActivityOfferings(String formatId, String activityId, int noOfActivityOfferings, CourseOfferingManagementForm form){
214 
215         FormatInfo format = null;
216         CourseInfo course;
217         CourseOfferingInfo courseOffering = form.getTheCourseOffering();
218 
219         // Get the format object for the id selected
220         try {
221             course = getCourseService().getCourse(courseOffering.getCourseId(), getContextInfo());
222             for (FormatInfo f : course.getFormats()) {
223                 if(f.getId().equals(formatId)) {
224                     format = f;
225                     break;
226                 }
227             }
228         } catch (Exception e) {
229             throw new RuntimeException(e);
230         }
231 
232         // find the format offering object for the selected format
233         FormatOfferingInfo formatOfferingInfo = null;
234         try {
235             List<FormatOfferingInfo> courseOfferingFOs = getCourseOfferingService().getFormatOfferingsByCourseOffering(courseOffering.getId(), getContextInfo());
236             for(FormatOfferingInfo fo : courseOfferingFOs) {
237                 if (fo.getFormatId().equals(formatId)) {
238                     formatOfferingInfo = fo;
239                     break;
240                 }
241             }
242         } catch (Exception e) {
243             throw new RuntimeException(e);
244         }
245 
246         // find the Activity object that matches the activity id selected
247         ActivityInfo activity = null;
248         List<ActivityInfo> activities = format.getActivities();
249         for (ActivityInfo info : activities) {
250             if (StringUtils.equals(activityId, info.getId())) {
251                 activity = info;
252             }
253         }
254 
255         // Get the matching activity offering type for the selected activity
256         TypeInfo activityOfferingType;
257         try {
258             List<TypeInfo> types = getTypeService().getAllowedTypesForType(activity.getTypeKey(), getContextInfo());
259             // only one AO type should be mapped to each Activity type
260             if(types.size() > 1) {
261                 throw new RuntimeException("More than one allowed type is matched to activity type of: " + activity.getTypeKey());
262             }
263 
264             activityOfferingType = types.get(0);
265         } catch (Exception e) {
266             throw new RuntimeException(e);
267         }
268 
269         for (int i=0;i<noOfActivityOfferings;i++){
270             ActivityOfferingInfo aoInfo = new ActivityOfferingInfo();
271             aoInfo.setActivityId(activityId);
272             aoInfo.setFormatOfferingId(formatOfferingInfo.getId());
273             aoInfo.setTypeKey(activityOfferingType.getKey());
274             aoInfo.setCourseOfferingId(courseOffering.getId());
275             aoInfo.setStateKey(LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY);
276             try {
277                 ActivityOfferingInfo activityOfferingInfo = _getCourseOfferingService().createActivityOffering(formatOfferingInfo.getId(), activityId, activityOfferingType.getKey(), aoInfo, getContextInfo());
278                 ActivityOfferingWrapper wrapper = new ActivityOfferingWrapper(activityOfferingInfo);
279                 StateInfo state = getStateService().getState(wrapper.getAoInfo().getStateKey(), getContextInfo());
280                 wrapper.setStateName(state.getName());
281                 TypeInfo typeInfo = getTypeService().getType(wrapper.getAoInfo().getTypeKey(), getContextInfo());
282                 wrapper.setTypeName(typeInfo.getName());
283                 form.getActivityWrapperList().add(wrapper);
284             } catch (Exception e) {
285                 throw new RuntimeException(e);
286             }
287         }
288     }
289 
290     public void loadActivityOfferingsByCourseOffering (CourseOfferingInfo theCourseOfferingInfo, CourseOfferingManagementForm form) throws Exception{
291         String courseOfferingId = theCourseOfferingInfo.getId();
292         List<ActivityOfferingInfo> activityOfferingInfoList;
293         List<ActivityOfferingWrapper> activityOfferingWrapperList;
294 
295         try {
296             activityOfferingInfoList =_getCourseOfferingService().getActivityOfferingsByCourseOffering(courseOfferingId, getContextInfo());
297             activityOfferingWrapperList = new ArrayList<ActivityOfferingWrapper>(activityOfferingInfoList.size());
298             Calendar calendar = new  GregorianCalendar();
299 
300             for (ActivityOfferingInfo info : activityOfferingInfoList) {
301                 ActivityOfferingWrapper wrapper = new ActivityOfferingWrapper(info);
302                 StateInfo state = getStateService().getState(info.getStateKey(), getContextInfo());
303                 wrapper.setStateName(state.getName());
304                 TypeInfo typeInfo = getTypeService().getType(info.getTypeKey(), getContextInfo());
305                 wrapper.setTypeName(typeInfo.getName());
306                 FormatOfferingInfo fo = getCourseOfferingService().getFormatOffering(info.getFormatOfferingId(), getContextInfo());
307                 wrapper.setFormatOffering(fo);
308                 OfferingInstructorInfo displayInstructor = ViewHelperUtil.findDisplayInstructor(info.getInstructors());
309                 if(displayInstructor != null) {
310                     wrapper.setFirstInstructorDisplayName(displayInstructor.getPersonName());
311                 }
312 
313                 // assign the time and days
314                 SimpleDateFormat format = new SimpleDateFormat("hh:mm a");
315                 List<ScheduleRequestInfo> scheduleRequestInfoList = getSchedulingService().getScheduleRequestsByRefObject(LuiServiceConstants.ACTIVITY_OFFERING_GROUP_TYPE_KEY  , info.getId(), getContextInfo());
316                 if (scheduleRequestInfoList != null && scheduleRequestInfoList.size() > 0) {
317                     ScheduleRequestInfo scheduleRequestInfo = scheduleRequestInfoList.get(0);
318                     List<ScheduleRequestComponentInfo> componentList = scheduleRequestInfo.getScheduleRequestComponents();
319                     if (componentList != null && componentList.size() > 0) {
320                         List<String> ids = componentList.get(0).getTimeSlotIds();
321                         if (ids != null && ids.size() > 0) {
322                             TimeSlotInfo timeSlot = getSchedulingService().getTimeSlot(ids.get(0), getContextInfo());
323                             if (timeSlot != null) {
324                                 TimeOfDayInfo startTime = timeSlot.getStartTime();
325                                 TimeOfDayInfo endTime = timeSlot.getEndTime();
326                                 List<Integer> days = timeSlot.getWeekdays();
327 
328                                 if (startTime != null) {
329                                     calendar.setTimeInMillis(startTime.getMilliSeconds());
330                                     wrapper.setStartTimeDisplay(format.format(calendar.getTime()));
331                                 }
332                                 if (endTime != null) {
333                                     calendar.setTimeInMillis(endTime.getMilliSeconds());
334                                     wrapper.setEndTimeDisplay(format.format(calendar.getTime()));
335                                 }
336                                 if (days != null && days.size() > 0) {
337                                     wrapper.setDaysDisplayName(getDays(days));
338                                 }
339                             }
340                         }
341 
342                         // assign building and room info
343                         List<String> roomIds = componentList.get(0).getRoomIds();
344                         if (roomIds != null && roomIds.size() > 0) {
345                             if (roomIds.get(0) != null) {
346                                 RoomInfo roomInfo = getRoomService().getRoom(roomIds.get(0), getContextInfo());
347                                 if (roomInfo != null) {
348                                     if (roomInfo.getBuildingId() != null && !roomInfo.getBuildingId().isEmpty()) {
349                                         BuildingInfo buildingInfo = getRoomService().getBuilding(roomInfo.getBuildingId(), getContextInfo());
350                                         if (buildingInfo != null)
351                                             wrapper.setBuildingName(buildingInfo.getName());
352                                     }
353                                     wrapper.setRoomName(roomInfo.getName());
354                                 }
355                             }
356                         }
357 
358                     }
359                 }
360                 activityOfferingWrapperList.add(wrapper);
361             }
362         } catch (Exception e) {
363             throw new RuntimeException(String.format("Could not load AOs for course offering [%s].", courseOfferingId), e);
364         }
365         form.setActivityWrapperList(activityOfferingWrapperList);
366     }
367 
368     /**
369      * Performs
370      * @param aoList The list of AOs to evaluate.
371      * @param selectedAction The state change action to perform.
372      * @throws Exception
373      */
374     public void changeActivityOfferingsState(List<ActivityOfferingWrapper> aoList, CourseOfferingInfo courseOfferingInfo, String selectedAction) throws Exception {
375         StateInfo draftState = getStateService().getState(LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY, getContextInfo());
376         StateInfo approvedState = getStateService().getState(LuiServiceConstants.LUI_AO_STATE_APPROVED_KEY, getContextInfo());
377 
378         boolean isErrorAdded = false;
379 
380         for (ActivityOfferingWrapper wrapper : aoList) {
381             //  Only evaluate items that were selected/checked in the UI.
382             if (wrapper.getIsChecked()) {
383                 //  If the action is "Set as Draft" then the current state of the AO must be "Approved".
384                 if (StringUtils.equals(CourseOfferingConstants.ACTIVITY_OFFERING_DRAFT_ACTION, selectedAction)) {
385                     if (StringUtils.equals(wrapper.getAoInfo().getStateKey(), LuiServiceConstants.LUI_AO_STATE_APPROVED_KEY)){
386                         wrapper.getAoInfo().setStateKey(LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY);
387                         wrapper.setStateName(draftState.getName());
388                         ActivityOfferingInfo updatedAO = getCourseOfferingService().updateActivityOffering(wrapper.getAoInfo().getId(),wrapper.getAoInfo(),getContextInfo());
389                         wrapper.setAoInfo(updatedAO);
390                     } else {
391                         //  Add the validation error once
392                         if ( ! isErrorAdded){
393                             GlobalVariables.getMessageMap().putError("selectedOfferingAction", RiceKeyConstants.ERROR_CUSTOM, "Some Activity Offerings are not in draft state");
394                             isErrorAdded = true;
395                         }
396                     }
397                 //  If the action is "Approve for Scheduling" then AO state must be "Draft"
398                 } else if (StringUtils.equals(CourseOfferingConstants.ACTIVITY_OFFERING_SCHEDULING_ACTION, selectedAction)) {
399                     if (StringUtils.equals(LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY, wrapper.getAoInfo().getStateKey())) {
400                         wrapper.getAoInfo().setStateKey(LuiServiceConstants.LUI_AO_STATE_APPROVED_KEY);
401                         wrapper.setStateName(approvedState.getName());
402                         ActivityOfferingInfo updatedAO = getCourseOfferingService().updateActivityOffering(wrapper.getAoInfo().getId(),wrapper.getAoInfo(),getContextInfo());
403                         wrapper.setAoInfo(updatedAO);
404                     }else{
405                         // Add the validation error once
406                         if (!isErrorAdded){
407                             GlobalVariables.getMessageMap().putError("selectedOfferingAction",RiceKeyConstants.ERROR_CUSTOM,"Some Activity Offerings are not in draft state");
408                             isErrorAdded = true;
409                         }
410                     }
411                 }
412             }
413         }
414         // check for changes to states in the related COs and FOs
415         ViewHelperUtil.updateCourseOfferingStateFromActivityOfferingStateChange(courseOfferingInfo, getContextInfo());
416     }
417 
418     /**
419      *  Same as markCourseOfferingsForScheduling() but defaults isChecked() == true.
420      *  @param coWrappers The list of CourseOffering wrappers.
421      */
422     public void  markCourseOfferingsForScheduling(List<CourseOfferingEditWrapper> coWrappers) throws Exception {
423         markCourseOfferingsForScheduling(coWrappers, true);
424     }
425 
426     /**
427      *  Examines a List of CourseOffering wrappers and changes the state of each "checked" AO (meaning the
428      *  CO was selected on the UI) from "Draft" to "Approved". If the AO has a state other than "Draft" the AO is ignored.
429      *  Also, changes the state of the CourseOffering if appropriate.
430      *
431      * @param coWrappers The list of CourseOfferings.
432      * @param checkedOnly True if the CO wrapper isChecked() flag should be respected.
433      */
434     public void markCourseOfferingsForScheduling(List<CourseOfferingEditWrapper> coWrappers, boolean checkedOnly) throws Exception {
435         boolean isErrorAdded = false;
436         boolean isWarningAdded = false;
437         for (CourseOfferingEditWrapper coWrapper : coWrappers) {
438             if ((coWrapper.getIsChecked() && checkedOnly) || ! checkedOnly) {
439                 List<ActivityOfferingInfo> activityOfferingInfos = getCourseOfferingService().getActivityOfferingsByCourseOffering(coWrapper.getCoInfo().getId(),getContextInfo());
440                 if (activityOfferingInfos.size() == 0) {
441                     if(!isErrorAdded) {
442                         GlobalVariables.getMessageMap().putError("selectedOfferingAction", CourseOfferingConstants.COURSEOFFERING_INVALID_STATE_FOR_SELECTED_ACTION_ERROR);
443                         isErrorAdded = true;
444                     }
445                     continue;
446                 }
447                 //  Iterate through the AOs and state change Draft -> Approved.
448                 for (ActivityOfferingInfo activityOfferingInfo : activityOfferingInfos) {
449                     boolean isAOStateDraft = StringUtils.equals(activityOfferingInfo.getStateKey(), LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY);
450                     if (isAOStateDraft) {
451                         activityOfferingInfo.setStateKey(LuiServiceConstants.LUI_AO_STATE_APPROVED_KEY);
452                         getCourseOfferingService().updateActivityOffering(activityOfferingInfo.getId(), activityOfferingInfo,getContextInfo());
453                     } else {
454                         if ( ! isWarningAdded) {
455                             GlobalVariables.getMessageMap().putWarning("manageCourseOfferingsPage", CourseOfferingConstants.COURSEOFFERING_WITH_AO_DRAFT_APPROVED_ONLY);
456                             isWarningAdded = true;
457                         }
458                     }
459                 }
460             }
461 
462             // check for changes to states in CO and related FOs
463             ViewHelperUtil.updateCourseOfferingStateFromActivityOfferingStateChange(coWrapper.getCoInfo(), getContextInfo());
464         }
465     }
466 
467     /*
468      * For Manage Registration Group page
469      */
470     public void validateRegistrationGroupsForFormatOffering (List<RegistrationGroupInfo> rgInfos,
471                                                              String formatOfferingId,
472                                                              CourseOfferingManagementForm form) throws Exception {
473         List<ActivityOfferingInfo> aoList = coService.getActivityOfferingsByFormatOffering(
474                 formatOfferingId, getContextInfo());
475 
476         Map<String, List<String>> activityOfferingTypeToAvailableActivityOfferingMap =
477                 constructActivityOfferingTypeToAvailableActivityOfferingMap(aoList);
478 
479         List<List<String>> generatedPermutations = new ArrayList<List<String>>();
480         List<List<String>> foundList = new ArrayList<List<String>>();
481 
482         PermutationUtils.generatePermutations(new ArrayList<String>(
483                 activityOfferingTypeToAvailableActivityOfferingMap.keySet()),
484                 new ArrayList<String>(),
485                 activityOfferingTypeToAvailableActivityOfferingMap,
486                 generatedPermutations);
487 
488         
489         for (List<String> activityOfferingPermutation : generatedPermutations) {
490               for (RegistrationGroupInfo rgInfo : rgInfos){
491                   if (hasGeneratedRegGroup(activityOfferingPermutation,rgInfo)){
492                       rgInfos.remove(rgInfo);
493                       foundList.add(activityOfferingPermutation);
494                       break;
495                   }
496               }
497         }
498         if (generatedPermutations.size() != foundList.size() )  {
499             GlobalVariables.getMessageMap().putWarningForSectionId("registrationGroupsPerFormatSection", CourseOfferingConstants.REGISTRATIONGROUP_MISSING_REGGROUPS);
500         }
501         if (!rgInfos.isEmpty()){
502             GlobalVariables.getMessageMap().putWarningForSectionId("registrationGroupsPerFormatSection", CourseOfferingConstants.REGISTRATIONGROUP_INVALID_REGGROUPS);
503         }
504     }
505     
506     private CourseOfferingService _getCourseOfferingService() {
507         if (coService == null) {
508             coService = (CourseOfferingService) GlobalResourceLoader.getService(new QName(CourseOfferingServiceConstants.NAMESPACE,
509                     CourseOfferingServiceConstants.SERVICE_NAME_LOCAL_PART));
510         }
511         return coService;
512     }
513 
514     public ContextInfo getContextInfo() {
515         ContextInfo contextInfo = new ContextInfo();
516         contextInfo.setAuthenticatedPrincipalId(GlobalVariables.getUserSession().getPrincipalId());
517         contextInfo.setPrincipalId(GlobalVariables.getUserSession().getPrincipalId());
518         LocaleInfo localeInfo = new LocaleInfo();
519         localeInfo.setLocaleLanguage(Locale.getDefault().getLanguage());
520         localeInfo.setLocaleRegion(Locale.getDefault().getCountry());
521         contextInfo.setLocale(localeInfo);
522         return contextInfo;
523     }
524 
525     private AcademicCalendarService _getAcalService() {
526         if (acalService == null) {
527             acalService = (AcademicCalendarService) GlobalResourceLoader.getService(new QName(AcademicCalendarServiceConstants.NAMESPACE,
528                     AcademicCalendarServiceConstants.SERVICE_NAME_LOCAL_PART));
529         }
530         return acalService;
531     }
532 
533     public CourseOfferingService getCourseOfferingService() {
534         return CourseOfferingResourceLoader.loadCourseOfferingService();
535     }
536 
537     public CourseService getCourseService() {
538         if (courseService == null){
539             courseService = CourseOfferingResourceLoader.loadCourseService();
540         }
541         return courseService;
542     }
543 
544     public TypeService getTypeService() {
545         if(typeService == null) {
546             typeService = CourseOfferingResourceLoader.loadTypeService();
547         }
548         return this.typeService;
549     }
550 
551     public StateService getStateService() {
552         if(stateService == null) {
553             stateService = CourseOfferingResourceLoader.loadStateService();
554         }
555         return stateService;
556     }
557 
558     protected LRCService getLrcService() {
559         if(lrcService == null) {
560             lrcService = (LRCService) GlobalResourceLoader.getService(new QName("http://student.kuali.org/wsdl/lrc", "LrcService"));
561         }
562         return this.lrcService;
563     }
564 
565     public SchedulingService getSchedulingService() {
566          if(schedulingService == null)  {
567              schedulingService = CourseOfferingResourceLoader.loadSchedulingService();
568          }
569          return schedulingService;
570     }
571 
572     public RoomService getRoomService(){
573         if (roomService == null){
574             roomService = CourseOfferingResourceLoader.loadRoomService();
575         }
576         return roomService;
577     }
578 
579     // get credit count from persisted COInfo or from CourseInfo
580     private String getCreditCount(CourseOfferingInfo coInfo, CourseInfo courseInfo) throws Exception{
581         return ViewHelperUtil.getCreditCount(coInfo, courseInfo);
582     }
583 
584     private Map<String, List<String>> constructActivityOfferingTypeToAvailableActivityOfferingMap(List<ActivityOfferingInfo> aoList) {
585         Map<String, List<String>> activityOfferingTypeToAvailableActivityOfferingMap = new HashMap<String, List<String>>();
586 
587         for (ActivityOfferingInfo info : aoList) {
588             String activityType = info.getTypeKey();
589             List<String> activityList = activityOfferingTypeToAvailableActivityOfferingMap
590                     .get(activityType);
591 
592             if (activityList == null) {
593                 activityList = new ArrayList<String>();
594                 activityOfferingTypeToAvailableActivityOfferingMap.put(
595                         activityType, activityList);
596             }
597 
598             activityList.add(info.getId());
599 
600         }
601         return activityOfferingTypeToAvailableActivityOfferingMap;
602     }
603     
604     private boolean hasGeneratedRegGroup(List<String>activityOfferingPermutation, RegistrationGroupInfo rgInfo){
605         boolean isMatched = true;
606         List<String> aoIds = rgInfo.getActivityOfferingIds();
607         List<String> foundList = new ArrayList<String>();
608         for (String activityOfferingPermutationItem : activityOfferingPermutation){
609             for (String aoId: aoIds){
610                 if (activityOfferingPermutationItem.equals(aoId)){
611                     aoIds.remove(aoId);
612                     foundList.add(activityOfferingPermutationItem);
613                     break;
614                 }
615             }
616         }
617         if (activityOfferingPermutation.size() != foundList.size() ||!aoIds.isEmpty()  )  {
618             isMatched = false;
619         }
620         return isMatched;        
621     }
622 
623 
624     private String convertIntoDays(int day) {
625         String dayOfWeek;
626         switch (day) {
627             case 1:
628                 dayOfWeek = "U";
629                 break;
630             case 2:
631                 dayOfWeek = "M";
632                 break;
633             case 3:
634                 dayOfWeek = "T";
635                 break;
636             case 4:
637                 dayOfWeek = "W";
638                 break;
639             case 5:
640                 dayOfWeek = "H";
641                 break;
642             case 6:
643                 dayOfWeek = "F";
644                 break;
645             case 7:
646                 dayOfWeek = "S";
647                 break;
648             default:
649                 dayOfWeek = "";
650         }
651         // TODO implement TBA when service stores it.
652         return dayOfWeek;
653     }
654 
655     private String getDays(List<Integer> intList) {
656 
657         StringBuilder sb = new StringBuilder();
658         if(intList == null) return sb.toString();
659 
660         for(Integer d : intList) {
661             sb.append(convertIntoDays(d));
662         }
663         return sb.toString();
664     }
665 }