View Javadoc

1   /**
2    * Copyright 2013 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   */
16  package org.kuali.student.enrollment.class2.courseoffering.controller;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.core.api.criteria.Predicate;
20  import org.kuali.rice.core.api.criteria.PredicateFactory;
21  import org.kuali.rice.core.api.criteria.QueryByCriteria;
22  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
23  import org.kuali.rice.core.api.util.RiceKeyConstants;
24  import org.kuali.rice.kim.api.identity.Person;
25  import org.kuali.rice.krad.util.GlobalVariables;
26  import org.kuali.rice.krad.util.KRADConstants;
27  import org.kuali.rice.krad.web.form.MaintenanceDocumentForm;
28  import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingCreateWrapper;
29  import org.kuali.student.enrollment.class2.courseoffering.dto.ExistingCourseOffering;
30  import org.kuali.student.enrollment.class2.courseoffering.dto.JointCourseWrapper;
31  import org.kuali.student.enrollment.class2.courseoffering.service.impl.CourseOfferingCreateMaintainableImpl;
32  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingConstants;
33  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingResourceLoader;
34  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingViewHelperUtil;
35  import org.kuali.student.enrollment.class2.courseoffering.util.ManageSocConstants;
36  import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo;
37  import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService;
38  import org.kuali.student.enrollment.courseofferingset.dto.SocInfo;
39  import org.kuali.student.enrollment.courseofferingset.dto.SocRolloverResultItemInfo;
40  import org.kuali.student.enrollment.courseofferingset.service.CourseOfferingSetService;
41  import org.kuali.student.enrollment.uif.util.GrowlIcon;
42  import org.kuali.student.enrollment.uif.util.KSControllerHelper;
43  import org.kuali.student.enrollment.uif.util.KSUifUtils;
44  import org.kuali.student.r2.common.constants.CommonServiceConstants;
45  import org.kuali.student.r2.common.dto.ContextInfo;
46  import org.kuali.student.r2.common.util.ContextUtils;
47  import org.kuali.student.r2.common.util.constants.CourseOfferingServiceConstants;
48  import org.kuali.student.r2.common.util.constants.CourseOfferingSetServiceConstants;
49  import org.kuali.student.r2.common.util.constants.LuiServiceConstants;
50  import org.kuali.student.r2.core.acal.dto.TermInfo;
51  import org.kuali.student.r2.core.acal.service.AcademicCalendarService;
52  import org.kuali.student.r2.core.class1.search.CourseOfferingHistorySearchImpl;
53  import org.kuali.student.r2.core.class1.type.service.TypeService;
54  import org.kuali.student.r2.core.constants.AcademicCalendarServiceConstants;
55  import org.kuali.student.r2.core.search.dto.SearchParamInfo;
56  import org.kuali.student.r2.core.search.dto.SearchRequestInfo;
57  import org.kuali.student.r2.core.search.dto.SearchResultCellInfo;
58  import org.kuali.student.r2.core.search.dto.SearchResultInfo;
59  import org.kuali.student.r2.core.search.dto.SearchResultRowInfo;
60  import org.kuali.student.r2.core.search.service.SearchService;
61  import org.kuali.student.r2.lum.clu.service.CluService;
62  import org.kuali.student.r2.lum.course.dto.CourseInfo;
63  import org.kuali.student.r2.lum.course.service.CourseService;
64  import org.kuali.student.r2.lum.lrc.dto.ResultValuesGroupInfo;
65  import org.kuali.student.r2.lum.lrc.service.LRCService;
66  import org.springframework.stereotype.Controller;
67  import org.springframework.validation.BindingResult;
68  import org.springframework.web.bind.annotation.ModelAttribute;
69  import org.springframework.web.bind.annotation.RequestMapping;
70  import org.springframework.web.servlet.ModelAndView;
71  
72  import javax.servlet.http.HttpServletRequest;
73  import javax.servlet.http.HttpServletResponse;
74  import javax.xml.namespace.QName;
75  import java.util.ArrayList;
76  import java.util.Arrays;
77  import java.util.Calendar;
78  import java.util.List;
79  
80  import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
81  
82  
83  /**
84   * This is the controller class what handles all the requests (actions) from the <i>'create course offering'</i> ui.
85   * <p>
86   *      Wireframes at {@link http://ux.ks.kuali.org.s3.amazonaws.com/wireframes/ENR/Course_Offering/v17/start.html} and
87   *      {@link http://ux.ks.kuali.org.s3.amazonaws.com/wireframes/ENR/Complex%20Course%20Offerings/Sandbox/start.html}
88   * </p>
89   *
90   * @see CourseOfferingCreateWrapper
91   * @see JointCourseWrapper
92   * @see org.kuali.student.enrollment.class2.courseoffering.dto.FormatOfferingWrapper
93   * @see CourseOfferingCreateMaintainableImpl
94   */
95  @Controller
96  @RequestMapping(value = "/courseOfferingCreate")
97  public class CourseOfferingCreateController extends CourseOfferingBaseController {
98  
99      private CluService cluService;
100     private CourseService courseService;
101     private AcademicCalendarService academicCalendarService;
102     private CourseOfferingService courseOfferingService;
103     private transient LRCService lrcService;
104     private transient SearchService searchService;
105     private transient TypeService typeService;
106     private CourseOfferingSetService courseOfferingSetService;
107 
108     /**
109      * This is called when the user clicks on the <i>'show'</i> button after entering the term and course code.
110      */
111     @RequestMapping(params = "methodToCall=loadCourseCatalog")
112     public ModelAndView loadCourseCatalog(@ModelAttribute("KualiForm") MaintenanceDocumentForm form, HttpServletRequest request) throws Exception {
113 
114         CourseOfferingCreateWrapper coWrapper = ((CourseOfferingCreateWrapper) form.getDocument().getNewMaintainableObject().getDataObject());
115         String courseCode = coWrapper.getCatalogCourseCode();
116         String termCode = coWrapper.getTargetTermCode();
117 
118         TermInfo term = getTerm(termCode);
119         coWrapper.setTerm(term);
120 
121         List<CourseInfo> matchingCourses = retrieveMatchingCourses(courseCode);
122 
123         ContextInfo contextInfo = ContextUtils.createDefaultContextInfo();
124 
125         coWrapper.clear();
126 
127         if (matchingCourses.size() == 1 && term != null) {
128             CourseInfo course = matchingCourses.get(0);
129 
130             // set organization IDs and check if the user can edit the course
131             List<String> orgIds = course.getUnitsContentOwner();
132             if(orgIds != null && !orgIds.isEmpty()){
133                 String orgIDs = "";
134                 for (String orgId : orgIds) {
135                     orgIDs = orgIDs + orgId + ",";
136                 }
137                 if (orgIDs.length() > 0) {
138                     coWrapper.setAdminOrg(orgIDs.substring(0, orgIDs.length()-1));
139                 }
140             }
141             coWrapper.setCourse(course);
142             Person user = GlobalVariables.getUserSession().getPerson();
143             boolean canOpenView = form.getView().getAuthorizer().canOpenView(form.getView(), form, user);
144 
145             if (!canOpenView) {
146                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_CUSTOM, "You are not authorized to create a New Course Offering from " + courseCode + " Catalog Course Code");
147                 coWrapper.setAdminOrg(null);
148                 coWrapper.setCourse(null);
149                 coWrapper.setEnableCreateButton(false);
150 
151                 return getUIFModelAndView(form);
152             } else {
153                 // check if SOC state is "published"
154                 List<String> socIds = getCourseOfferingSetService().getSocIdsByTerm(term.getId(), contextInfo);
155                 if (socIds != null && !socIds.isEmpty()){
156                     SocInfo soc = getCourseOfferingSetService().getSoc(socIds.get(0), contextInfo);
157                     coWrapper.setSocInfo(soc);
158 
159                 //Get all the course offerings in a term
160                 List<CourseOfferingInfo> courseOfferingInfos = getCourseOfferingService().getCourseOfferingsByCourseAndTerm(course.getId(), term.getId(), contextInfo);
161 
162                 coWrapper.setCourse(course);
163                 coWrapper.setCreditCount(CourseOfferingViewHelperUtil.trimTrailing0(getLrcService().getResultValue(course.getCreditOptions().get(0).getResultValueKeys().get(0), contextInfo).getValue()));
164                 coWrapper.setShowAllSections(true);
165                 coWrapper.setShowCatalogLink(false);
166                 coWrapper.setShowTermOfferingLink(true);
167 
168                 coWrapper.getExistingTermOfferings().clear();
169                 coWrapper.getExistingOfferingsInCurrentTerm().clear();
170 
171                 for (CourseOfferingInfo courseOfferingInfo : courseOfferingInfos) {
172                     if (StringUtils.equals(courseOfferingInfo.getStateKey(), LuiServiceConstants.LUI_CO_STATE_OFFERED_KEY)) {
173                         ExistingCourseOffering co = new ExistingCourseOffering(courseOfferingInfo);
174                         co.setCredits(courseOfferingInfo.getCreditCnt());
175                         co.setGrading(getGradingOption(courseOfferingInfo.getGradingOptionId()));
176                         coWrapper.getExistingOfferingsInCurrentTerm().add(co);
177                     }
178                 }
179 
180                 //Get past 5 years CO
181                 Calendar termStart = Calendar.getInstance();
182                 termStart.setTime(term.getStartDate());
183                 String termYear = Integer.toString(termStart.get(Calendar.YEAR));
184 
185                 org.kuali.student.r2.core.search.dto.SearchRequestInfo searchRequest = new org.kuali.student.r2.core.search.dto.SearchRequestInfo(CourseOfferingHistorySearchImpl.PAST_CO_SEARCH.getKey());
186                 searchRequest.addParam(CourseOfferingHistorySearchImpl.COURSE_ID, coWrapper.getCourse().getId());
187 
188                 searchRequest.addParam(CourseOfferingHistorySearchImpl.TARGET_YEAR_PARAM, termYear);
189                 org.kuali.student.r2.core.search.dto.SearchResultInfo searchResult = getSearchService().search(searchRequest, null);
190 
191                 List<String> courseOfferingIds = new ArrayList<String>(searchResult.getTotalResults());
192                 for (org.kuali.student.r2.core.search.dto.SearchResultRowInfo row : searchResult.getRows()) {
193                     courseOfferingIds.add(row.getCells().get(0).getValue());
194                 }
195 
196                 courseOfferingInfos = getCourseOfferingService().getCourseOfferingsByIds(courseOfferingIds, contextInfo);
197 
198                 for (CourseOfferingInfo courseOfferingInfo : courseOfferingInfos) {
199                     ExistingCourseOffering co = new ExistingCourseOffering(courseOfferingInfo);
200                     TermInfo termInfo = getAcademicCalendarService().getTerm(courseOfferingInfo.getTermId(), contextInfo);
201                     co.setTermCode(termInfo.getCode());
202                     co.setCredits(courseOfferingInfo.getCreditCnt());
203                     co.setGrading(getGradingOption(courseOfferingInfo.getGradingOptionId()));
204                     coWrapper.getExistingTermOfferings().add(co);
205                 }
206 
207                 CourseOfferingCreateMaintainableImpl maintainable = (CourseOfferingCreateMaintainableImpl)KSControllerHelper.getViewHelperService(form);
208                 maintainable.loadCourseJointInfos(coWrapper, form.getViewId());
209                 //Enable the create button
210                 coWrapper.setEnableCreateButton(true);
211             } else {
212                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, ManageSocConstants.MessageKeys.ERROR_SOC_NOT_EXISTS);
213                 }
214             }
215         } else {
216 
217             if (matchingCourses.size() > 1) {
218                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_CUSTOM, "Multiple matches found for the course code");
219                 return null;
220             } else if (matchingCourses.isEmpty() && term == null) {
221                 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_CUSTOM, "Both Catalog Course Code and Target Term are invalid");
222             } else {
223                 if (term == null) {
224                     GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_CUSTOM, "Invalid Target Term");
225                 } else if (matchingCourses.isEmpty()) {
226                     GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, RiceKeyConstants.ERROR_CUSTOM, "Invalid Catalog Course Code");
227                 }
228             }
229 
230             coWrapper.setEnableCreateButton(false);
231 
232             return getUIFModelAndView(form);
233         }
234 
235         return getUIFModelAndView(form);
236     }
237 
238     private String getGradingOption(String gradingOptionId) throws Exception {
239         String gradingOption = "";
240         if (StringUtils.isNotBlank(gradingOptionId)) {
241             ResultValuesGroupInfo rvg = getLrcService().getResultValuesGroup(gradingOptionId, ContextUtils.createDefaultContextInfo());
242             if (rvg != null && StringUtils.isNotBlank(rvg.getName())) {
243                 gradingOption = rvg.getName();
244             }
245         }
246 
247         return gradingOption;
248     }
249 
250     /**
251      * This is mapped to the <i>'Create from Catalog'</i> link
252      *
253      */
254     @RequestMapping(params = "methodToCall=createFromCatalog")
255     public ModelAndView createFromCatalog(@ModelAttribute("KualiForm") MaintenanceDocumentForm form) throws Exception {
256 
257         CourseOfferingCreateWrapper wrapper = (CourseOfferingCreateWrapper) form.getDocument().getNewMaintainableObject().getDataObject();
258 
259         wrapper.setShowCatalogLink(false);
260         wrapper.setShowTermOfferingLink(true);
261 
262         return getUIFModelAndView(form);
263     }
264 
265     /**
266      * This is mapped to the <i>'Copy from existing'</i> link
267      *
268      */
269     @RequestMapping(params = "methodToCall=copyExistingCourseOffering")
270     public ModelAndView copyExistingCourseOffering(@ModelAttribute("KualiForm") MaintenanceDocumentForm form) throws Exception {
271 
272         CourseOfferingInfo existingCO = ((ExistingCourseOffering) KSControllerHelper.getSelectedCollectionItem(form)).getCourseOfferingInfo();
273         CourseOfferingCreateWrapper createWrapper = (CourseOfferingCreateWrapper) form.getDocument().getNewMaintainableObject().getDataObject();
274 
275         List<String> optionKeys = new ArrayList<String>();
276 
277         if (createWrapper.isExcludeInstructorInformation()) {
278             optionKeys.add(CourseOfferingSetServiceConstants.NO_INSTRUCTORS_OPTION_KEY);
279         }
280 
281         if (createWrapper.isExcludeSchedulingInformation()) {
282             optionKeys.add(CourseOfferingSetServiceConstants.NO_SCHEDULE_OPTION_KEY);
283         }
284 
285         if (createWrapper.isExcludeCancelledActivityOfferings()) {
286             optionKeys.add(CourseOfferingSetServiceConstants.IGNORE_CANCELLED_AO_OPTION_KEY);
287         }
288 
289         ContextInfo contextInfo = ContextUtils.createDefaultContextInfo();
290 
291         // if source term differs from target term determine if add suffix or not
292         if (StringUtils.equals(existingCO.getTermId(), createWrapper.getTerm().getId())) {
293             optionKeys.add(CourseOfferingServiceConstants.APPEND_COURSE_OFFERING_IN_SUFFIX_OPTION_KEY);
294         } else {
295             QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create();
296             qbcBuilder.setPredicates(PredicateFactory.and(
297                     PredicateFactory.like("courseOfferingCode", existingCO.getCourseOfferingCode() + "%"),
298                     PredicateFactory.equalIgnoreCase("atpId", createWrapper.getTerm().getId())));
299             QueryByCriteria criteria = qbcBuilder.build();
300             List<String> courseOfferingIds = getCourseOfferingService().searchForCourseOfferingIds(criteria, contextInfo);
301 
302             if (courseOfferingIds.size() > 0) {
303                 optionKeys.add(CourseOfferingServiceConstants.APPEND_COURSE_OFFERING_IN_SUFFIX_OPTION_KEY);
304             }
305         }
306 
307         SocRolloverResultItemInfo item = getCourseOfferingService().rolloverCourseOffering(existingCO.getId(),
308                 createWrapper.getTerm().getId(),
309                 optionKeys,
310                 contextInfo);
311 
312         CourseOfferingInfo newCO = getCourseOfferingService().getCourseOffering(item.getTargetCourseOfferingId(), contextInfo);
313         KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, CourseOfferingConstants.COURSEOFFERING_INFO_COPIED_SUCCESSFULLY, newCO.getCourseOfferingCode());
314         return getUIFModelAndView(form);
315 
316     }
317 
318     @RequestMapping(params = "methodToCall=createFromTermOffering")
319     public ModelAndView createFromTermOffering(@ModelAttribute("KualiForm") MaintenanceDocumentForm form) throws Exception {
320 
321         CourseOfferingCreateWrapper wrapper = (CourseOfferingCreateWrapper) form.getDocument().getNewMaintainableObject().getDataObject();
322         wrapper.setShowCatalogLink(true);
323         wrapper.setShowTermOfferingLink(false);
324 
325         return getUIFModelAndView(form);
326     }
327 
328     /**
329      * This is mapped to the link to to toggle between creating a new format offering or
330      * copy from existing joint format offerings.
331      *
332      */
333     @RequestMapping(params = "methodToCall=showCreateFormatSection")
334     public ModelAndView showCreateFormatSection(@ModelAttribute("KualiForm") MaintenanceDocumentForm form) throws Exception {
335 
336         CourseOfferingCreateWrapper wrapper = (CourseOfferingCreateWrapper) form.getDocument().getNewMaintainableObject().getDataObject();
337         wrapper.setShowCreateFormatSection(true);
338         wrapper.setShowCopyFormatSection(false);
339 
340         return getUIFModelAndView(form);
341     }
342 
343     /**
344      * This is mapped to the link to to toggle between creating a new format offering or
345      * copy from existing joint format offerings.
346      *
347      */
348     @RequestMapping(params = "methodToCall=showCopyFromJointOffering")
349     public ModelAndView showCopyFromJointOffering(@ModelAttribute("KualiForm") MaintenanceDocumentForm form) throws Exception {
350 
351         CourseOfferingCreateWrapper wrapper = (CourseOfferingCreateWrapper) form.getDocument().getNewMaintainableObject().getDataObject();
352         wrapper.setShowCreateFormatSection(false);
353         wrapper.setShowCopyFormatSection(true);
354 
355         return getUIFModelAndView(form);
356     }
357 
358     /**
359      * This will be called whenever the user selects/deselects a joint course. If user deselects a joint course, make sure
360      * it doesnt have associated formats. If exists, display a confirmation dialog with all the available formats.
361      *
362      * XML reference at CourseOfferingCreateMaintenanceView.xml
363      *
364      */
365     @RequestMapping(params = "methodToCall=markCourseForJointOffering")
366     public ModelAndView markCourseForJointOffering(@ModelAttribute("KualiForm") MaintenanceDocumentForm form, BindingResult result,
367                 HttpServletRequest request, HttpServletResponse response) throws Exception {
368 
369         CourseOfferingCreateWrapper wrapper = (CourseOfferingCreateWrapper) form.getDocument().getNewMaintainableObject().getDataObject();
370         int index = wrapper.getSelectedJointCourseIndex();
371         if(form.getActionParameters().size() > 1)   {
372             String lineIndex = form.getActionParameters().get("selectedLineIndex");
373             index = Integer.parseInt(lineIndex);
374             wrapper.setSelectedJointCourseIndex(index);
375         }
376         JointCourseWrapper joint = wrapper.getJointCourses().get(index);
377 
378         if (joint.isSelectedToJointlyOfferred()){
379             String dialogName = CourseOfferingConstants.JOINT_COURSE_FORMATS_DELETE_DIALOG;
380             
381             if (!hasDialogBeenAnswered(dialogName, form)) {
382                 wrapper.setSelectedJointCourseCode(joint.getCourseCode());
383                 wrapper.setDialogFormatOfferingWrapperList(joint.getFormatOfferingWrappers());
384                 return showDialog(dialogName, form, request, response);
385             }
386 
387             boolean dialogAnswer = getBooleanDialogResponse(dialogName, form, request, response);
388             form.getDialogManager().resetDialogStatus(dialogName);
389 
390             if (dialogAnswer) {
391                 joint.setSelectedToJointlyOfferred(false);
392                 String jointCodes = StringUtils.remove(wrapper.getJointCourseCodes(), ", " + joint.getCourseCode());
393                 wrapper.setJointCourseCodes(jointCodes);
394                 wrapper.getFormatOfferingWrappers().removeAll(joint.getFormatOfferingWrappers());
395             }
396 
397         } else {
398             wrapper.setJointCourseCodes(wrapper.getJointCourseCodes() + ", " + joint.getCourseCode());
399             joint.setSelectedToJointlyOfferred(true);
400         }
401 
402         return getUIFModelAndView(form);
403     }
404 
405     /**
406      * Mapped to the <i>'Add'</i> button at the format section. This either copies from the user selected joint
407      * offerings or create a new format.
408      *
409      */
410     @RequestMapping(params = "methodToCall=addFormat")
411         public ModelAndView addFormat(@ModelAttribute("KualiForm") MaintenanceDocumentForm form) throws Exception {
412 
413         CourseOfferingCreateWrapper wrapper = (CourseOfferingCreateWrapper)form.getDocument().getNewMaintainableObject().getDataObject();
414         CourseOfferingCreateMaintainableImpl maintainable = (CourseOfferingCreateMaintainableImpl)KSControllerHelper.getViewHelperService(form);
415 
416         //If the user creates a new format
417         if (wrapper.isShowCreateFormatSection()){
418             maintainable.addFormatOffering(wrapper);
419         } else { //If the user copies from existing joint formats
420             maintainable.copyJointFormatOfferings(wrapper);
421         }
422 
423         return getUIFModelAndView(form);
424     }
425 
426 
427     private TermInfo getTerm(String termCode) {
428         QueryByCriteria.Builder qBuilder = QueryByCriteria.Builder.create();
429         List<Predicate> pList = new ArrayList<Predicate>();
430         Predicate p = null;
431 
432         qBuilder.setPredicates();
433         if (StringUtils.isNotBlank(termCode)) {
434             p = equal("atpCode", termCode);
435             pList.add(p);
436         }
437 
438         qBuilder.setPredicates(p);
439 
440         try {
441             List<TermInfo> terms = getAcademicCalendarService().searchForTerms(qBuilder.build(), ContextUtils.createDefaultContextInfo());
442             if (terms.size() > 1) {
443                 //GlobalVariables.getMessageMap().putError("asf","asdf");//FIXME
444                 return null;
445             } else if (terms.isEmpty()) {
446                 return null;
447             }
448             return terms.get(0);
449         } catch (Exception e) {
450             throw new RuntimeException(e);
451         }
452 
453     }
454 
455     protected AcademicCalendarService getAcademicCalendarService() {
456         if (academicCalendarService == null) {
457             academicCalendarService = (AcademicCalendarService) GlobalResourceLoader.getService(new QName(AcademicCalendarServiceConstants.NAMESPACE, AcademicCalendarServiceConstants.SERVICE_NAME_LOCAL_PART));
458         }
459         return this.academicCalendarService;
460     }
461 
462     private CourseService getCourseService() {
463         if (courseService == null) {
464             courseService = CourseOfferingResourceLoader.loadCourseService();
465         }
466         return courseService;
467     }
468 
469     private CourseOfferingService getCourseOfferingService() {
470         if (courseOfferingService == null) {
471             courseOfferingService = CourseOfferingResourceLoader.loadCourseOfferingService();
472         }
473         return courseOfferingService;
474     }
475 
476     private List<CourseInfo> retrieveMatchingCourses(String courseName) {
477 
478         CourseInfo returnCourseInfo;
479         String courseId;
480         List<SearchParamInfo> searchParams = new ArrayList<SearchParamInfo>();
481         List<CourseInfo> courseInfoList = new ArrayList<CourseInfo>();
482 
483         SearchParamInfo qpv1 = new SearchParamInfo();
484         qpv1.setKey("lu.queryParam.startsWith.cluCode");
485         qpv1.getValues().add(courseName.toUpperCase());
486         searchParams.add(qpv1);
487 
488         SearchParamInfo qpv2 = new SearchParamInfo();
489         qpv2.setKey("lu.queryParam.cluState");
490         qpv2.setValues(Arrays.asList("Active"));
491         searchParams.add(qpv2);
492 
493         SearchRequestInfo searchRequest = new SearchRequestInfo();
494         searchRequest.setParams(searchParams);
495         searchRequest.setSearchKey("lu.search.cluByCodeAndState");
496 
497         try {
498             SearchResultInfo searchResult = getCluService().search(searchRequest, ContextUtils.getContextInfo());
499             if (searchResult.getRows().size() > 0) {
500                 for (SearchResultRowInfo row : searchResult.getRows()) {
501                     List<SearchResultCellInfo> srCells = row.getCells();
502                     if (srCells != null && srCells.size() > 0) {
503                         for (SearchResultCellInfo cell : srCells) {
504                             if ("lu.resultColumn.cluId".equals(cell.getKey())) {
505                                 courseId = cell.getValue();
506                                 returnCourseInfo = getCourseService().getCourse(courseId, ContextUtils.getContextInfo());
507                                 courseInfoList.add(returnCourseInfo);
508                             }
509                         }
510                     }
511                 }
512             }
513         } catch (Exception e) {
514             throw new RuntimeException(e);
515         }
516 
517         return courseInfoList;
518 
519     }
520 
521     protected TypeService getTypeService() {
522         if(typeService == null) {
523             typeService = CourseOfferingResourceLoader.loadTypeService();
524         }
525         return this.typeService;
526     }
527 
528     private CluService getCluService() {
529         if (cluService == null) {
530             cluService = CourseOfferingResourceLoader.loadCluService();
531         }
532         return cluService;
533     }
534 
535     protected LRCService getLrcService() {
536         if (lrcService == null) {
537             lrcService = CourseOfferingResourceLoader.loadLrcService();
538         }
539         return this.lrcService;
540     }
541 
542     protected SearchService getSearchService() {
543         if (searchService == null) {
544             searchService = (SearchService) GlobalResourceLoader.getService(new QName(CommonServiceConstants.REF_OBJECT_URI_GLOBAL_PREFIX + "search", SearchService.class.getSimpleName()));
545         }
546         return searchService;
547     }
548 
549     protected CourseOfferingSetService getCourseOfferingSetService(){
550         if (courseOfferingSetService == null){
551             courseOfferingSetService = (CourseOfferingSetService) GlobalResourceLoader.getService(new QName(CourseOfferingSetServiceConstants.NAMESPACE, CourseOfferingSetServiceConstants.SERVICE_NAME_LOCAL_PART));
552         }
553         return courseOfferingSetService;
554     }
555 }