Java tutorial
/** * Copyright 2013 The Kuali Foundation Licensed under the * Educational Community License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may * obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS IS" * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing * permissions and limitations under the License. * */ package org.kuali.student.enrollment.class2.courseoffering.service.impl; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.StringUtils; import org.kuali.rice.core.api.criteria.PredicateFactory; import org.kuali.rice.core.api.criteria.QueryByCriteria; import org.kuali.rice.kim.api.KimConstants; import org.kuali.rice.kim.api.identity.entity.EntityDefault; import org.kuali.rice.kim.api.identity.entity.EntityDefaultQueryResults; import org.kuali.rice.krad.util.GlobalVariables; import org.kuali.rice.krad.util.KRADConstants; import org.kuali.rice.krad.util.ObjectUtils; import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition; import org.kuali.rice.krms.api.repository.reference.ReferenceObjectBinding; import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition; import org.kuali.rice.krms.framework.engine.Agenda; import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator; import org.kuali.student.common.collection.KSCollectionUtils; import org.kuali.student.common.uif.util.CommentUtil; import org.kuali.student.common.uif.util.GrowlIcon; import org.kuali.student.common.uif.util.KSUifUtils; import org.kuali.student.common.util.security.ContextUtils; import org.kuali.student.enrollment.class2.courseoffering.dto.ActivityOfferingClusterWrapper; import org.kuali.student.enrollment.class2.courseoffering.dto.ActivityOfferingWrapper; import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingContextBar; import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingListSectionWrapper; import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingWrapper; import org.kuali.student.enrollment.class2.courseoffering.dto.ExamOfferingClusterWrapper; import org.kuali.student.enrollment.class2.courseoffering.dto.ExamOfferingWrapper; import org.kuali.student.enrollment.class2.courseoffering.dto.RegistrationGroupWrapper; import org.kuali.student.enrollment.class2.courseoffering.dto.ScheduleCalcContainer; import org.kuali.student.enrollment.class2.courseoffering.dto.ScheduleRequestCalcContainer; import org.kuali.student.enrollment.class2.courseoffering.form.CourseOfferingManagementForm; import org.kuali.student.enrollment.class2.courseoffering.service.CourseOfferingManagementViewHelperService; import org.kuali.student.enrollment.class2.courseoffering.service.decorators.PermissionServiceConstants; import org.kuali.student.enrollment.class2.courseoffering.service.facade.ActivityOfferingResult; import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingConstants; import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingManagementToolbarUtil; import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingManagementUtil; import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingViewHelperUtil; import org.kuali.student.enrollment.class2.courseoffering.util.ExamOfferingManagementUtil; import org.kuali.student.enrollment.class2.courseoffering.util.ManageSocConstants; import org.kuali.student.enrollment.class2.courseoffering.util.RegistrationGroupConstants; import org.kuali.student.enrollment.class2.courseofferingset.util.CourseOfferingSetUtil; import org.kuali.student.enrollment.class2.examoffering.service.facade.ExamOfferingContext; import org.kuali.student.enrollment.class2.examoffering.service.facade.ExamOfferingResult; import org.kuali.student.enrollment.class2.scheduleofclasses.dto.ActivityOfferingDisplayWrapper; import org.kuali.student.enrollment.class2.scheduleofclasses.dto.CourseOfferingDisplayWrapper; import org.kuali.student.enrollment.class2.scheduleofclasses.form.ActivityOfferingDisplayUI; import org.kuali.student.enrollment.class2.scheduleofclasses.form.CourseOfferingDisplayUI; import org.kuali.student.enrollment.class2.scheduleofclasses.form.ScheduleOfClassesSearchForm; import org.kuali.student.enrollment.class2.scheduleofclasses.sort.impl.ActivityOfferingTypeComparator; import org.kuali.student.enrollment.class2.scheduleofclasses.util.ScheduleOfClassesConstants; import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingClusterInfo; import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingDisplayInfo; import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingInfo; import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingSetInfo; import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo; import org.kuali.student.enrollment.courseoffering.dto.FormatOfferingInfo; import org.kuali.student.enrollment.courseoffering.dto.RegistrationGroupInfo; import org.kuali.student.enrollment.courseofferingset.dto.SocInfo; import org.kuali.student.enrollment.coursewaitlist.dto.CourseWaitListInfo; import org.kuali.student.enrollment.examoffering.dto.ExamOfferingInfo; import org.kuali.student.enrollment.examoffering.dto.ExamOfferingRelationInfo; import org.kuali.student.enrollment.lpr.dto.LprInfo; import org.kuali.student.r2.common.dto.AttributeInfo; import org.kuali.student.r2.common.dto.ContextInfo; import org.kuali.student.r2.common.dto.RichTextInfo; import org.kuali.student.r2.common.dto.StatusInfo; import org.kuali.student.r2.common.dto.TimeOfDayInfo; import org.kuali.student.r2.common.dto.ValidationResultInfo; import org.kuali.student.r2.common.exceptions.DoesNotExistException; import org.kuali.student.r2.common.exceptions.InvalidParameterException; import org.kuali.student.r2.common.exceptions.MissingParameterException; import org.kuali.student.r2.common.exceptions.OperationFailedException; import org.kuali.student.r2.common.exceptions.PermissionDeniedException; import org.kuali.student.r2.common.infc.ValidationResult; import org.kuali.student.r2.common.permutation.PermutationUtils; import org.kuali.student.r2.common.util.TimeOfDayHelper; import org.kuali.student.r2.common.util.constants.CourseOfferingServiceConstants; import org.kuali.student.r2.common.util.constants.CourseOfferingSetServiceConstants; import org.kuali.student.r2.common.util.constants.ExamOfferingServiceConstants; import org.kuali.student.r2.common.util.constants.LprServiceConstants; import org.kuali.student.r2.common.util.constants.LuiServiceConstants; import org.kuali.student.r2.common.util.date.DateFormatters; import org.kuali.student.r2.core.acal.dto.KeyDateInfo; import org.kuali.student.r2.core.acal.dto.TermInfo; import org.kuali.student.r2.core.atp.dto.AtpInfo; import org.kuali.student.r2.core.class1.search.ActivityOfferingSearchServiceImpl; import org.kuali.student.r2.core.class1.search.CoreSearchServiceImpl; import org.kuali.student.r2.core.class1.search.CourseOfferingManagementSearchImpl; import org.kuali.student.r2.core.class1.state.dto.StateInfo; import org.kuali.student.r2.core.class1.type.dto.TypeInfo; import org.kuali.student.r2.core.class1.type.dto.TypeTypeRelationInfo; import org.kuali.student.r2.core.constants.AtpServiceConstants; import org.kuali.student.r2.core.constants.KSKRMSServiceConstants; import org.kuali.student.r2.core.constants.TypeServiceConstants; import org.kuali.student.r2.core.room.dto.BuildingInfo; import org.kuali.student.r2.core.room.dto.RoomInfo; import org.kuali.student.r2.core.scheduling.constants.SchedulingServiceConstants; import org.kuali.student.r2.core.scheduling.dto.ScheduleRequestComponentInfo; import org.kuali.student.r2.core.scheduling.dto.ScheduleRequestInfo; import org.kuali.student.r2.core.scheduling.dto.TimeSlotInfo; import org.kuali.student.r2.core.scheduling.infc.ScheduleComponentDisplay; import org.kuali.student.r2.core.scheduling.infc.TimeSlot; import org.kuali.student.r2.core.scheduling.util.SchedulingServiceUtil; import org.kuali.student.r2.core.search.dto.SearchParamInfo; import org.kuali.student.r2.core.search.dto.SearchRequestInfo; import org.kuali.student.r2.core.search.dto.SearchResultCellInfo; import org.kuali.student.r2.core.search.dto.SearchResultInfo; import org.kuali.student.r2.core.search.dto.SearchResultRowInfo; import org.kuali.student.r2.lum.course.dto.ActivityInfo; import org.kuali.student.r2.lum.course.dto.CourseInfo; import org.kuali.student.r2.lum.course.dto.CourseJointInfo; import org.kuali.student.r2.lum.course.dto.FormatInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import static java.util.Arrays.asList; /** * This class implements Course offering management functionality using auto-generated registration groups * * @author Kuali Student Team */ public class CourseOfferingManagementViewHelperServiceImpl extends CO_AO_RG_ViewHelperServiceImpl implements CourseOfferingManagementViewHelperService { private static final Logger LOG = LoggerFactory.getLogger(CourseOfferingManagementViewHelperServiceImpl.class); /** * This method fetches the <code>TermInfo</code> and validate for exact match * * @param form input CourseOfferingManagementForm * @throws Exception */ public void populateTerm(CourseOfferingManagementForm form) throws Exception { String termCode = form.getTermCode(); form.getCourseOfferingResultList().clear(); List<TermInfo> terms = CourseOfferingManagementUtil.getAcademicCalendarService().getTermsByCode(termCode, createContextInfo()); if (terms.isEmpty()) { GlobalVariables.getMessageMap().putError("termCode", CourseOfferingConstants.COURSEOFFERING_MSG_ERROR_NO_TERM_IS_FOUND, termCode); } else if (terms.size() > 1) { GlobalVariables.getMessageMap().putError("termCode", CourseOfferingConstants.COURSEOFFERING_MSG_ERROR_FOUND_MORE_THAN_ONE_TERM, termCode); } else { form.setTermInfo(terms.get(0)); //Checking soc SocInfo soc = CourseOfferingSetUtil.getMainSocForTermId(form.getTermInfo().getId(), createContextInfo()); if (soc == null) { GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, ManageSocConstants.MessageKeys.ERROR_SOC_NOT_EXISTS); } else { setSocStateKeys(form, soc); blockUserIfSocStateIs(form, CourseOfferingSetServiceConstants.SOC_SCHEDULING_STATE_IN_PROGRESS, ManageSocConstants.MessageKeys.ERROR_CANNOT_ACCESS_COURSE_OFFERING_WHILE_SOC_IS_IN_PROGRESS); blockUserIfSocStateIs(form, CourseOfferingSetServiceConstants.PUBLISHING_SOC_STATE_KEY, ManageSocConstants.MessageKeys.ERROR_CANNOT_ACCESS_COURSE_OFFERING_WHILE_SOC_IS_PUBLISHING); // setting term first day of classes List<KeyDateInfo> keyDateInfoList = CourseOfferingManagementUtil.getAcademicCalendarService() .getKeyDatesForTerm(form.getTermInfo().getId(), createContextInfo()); Date termClassStartDate = null; for (KeyDateInfo keyDateInfo : keyDateInfoList) { if (keyDateInfo.getTypeKey() .equalsIgnoreCase(AtpServiceConstants.MILESTONE_SEATPOOL_FIRST_DAY_OF_CLASSES_TYPE_KEY) && keyDateInfo.getStartDate() != null) { termClassStartDate = keyDateInfo.getStartDate(); break; } } for (KeyDateInfo keyDateInfo : keyDateInfoList) { if (keyDateInfo.getTypeKey() .equalsIgnoreCase(AtpServiceConstants.MILESTONE_INSTRUCTIONAL_PERIOD_TYPE_KEY) && keyDateInfo.getStartDate() != null && keyDateInfo.getEndDate() != null) { termClassStartDate = keyDateInfo.getStartDate(); break; } } form.setTermClassStartDate(termClassStartDate); } } } private void blockUserIfSocStateIs(CourseOfferingManagementForm form, String socStateKeyToBlockUserOn, String errorMessageKey) { errorMessageKey = StringUtils.defaultIfEmpty(errorMessageKey, ManageSocConstants.MessageKeys.ERROR_CANNOT_ACCESS_COURSE_OFFERING_WHILE_SOC_INVALID_STATE_DEFAULT); if (StringUtils.equalsIgnoreCase(form.getSocStateKey(), socStateKeyToBlockUserOn)) { GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, errorMessageKey); } } /** * This method loads all the course offerings for a term and course code. * * @param termInfo Term Info * @param courseCode Course Code * @param form Input Form * @throws Exception */ public void loadCourseOfferingsByTermAndCourseCode(TermInfo termInfo, String courseCode, CourseOfferingManagementForm form) throws Exception { SearchRequestInfo searchRequest = new SearchRequestInfo( CourseOfferingManagementSearchImpl.CO_MANAGEMENT_SEARCH.getKey()); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.COURSE_CODE, courseCode); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.ATP_ID, termInfo.getId()); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.CROSS_LIST_SEARCH_ENABLED, BooleanUtils.toStringTrueFalse(true)); // Check to see if the "exact co code match" param has been set. If so, add a query param. boolean isExactMatchSearch = BooleanUtils.toBoolean(form.getViewRequestParameters() .get(CourseOfferingManagementSearchImpl.SearchParameters.IS_EXACT_MATCH_CO_CODE_SEARCH)); if (isExactMatchSearch) { searchRequest.addParam( CourseOfferingManagementSearchImpl.SearchParameters.IS_EXACT_MATCH_CO_CODE_SEARCH, BooleanUtils.toStringTrueFalse(true)); } loadCourseOfferings(searchRequest, form); if (form.getCourseOfferingResultList().isEmpty()) { LOG.error("Error: Can't find any Course Offering for a course code: {} in term: {}", courseCode, termInfo.getName()); GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, CourseOfferingConstants.COURSEOFFERING_MSG_ERROR_NO_COURSE_OFFERING_IS_FOUND, "course code", courseCode, termInfo.getName()); } form.setContextBar(CourseOfferingContextBar.NEW_INSTANCE(form.getTermInfo(), form.getSocStateKey(), getStateService(), CourseOfferingManagementUtil.getAcademicCalendarService(), createContextInfo())); } /** * This method loads all the course offerings for a term and subject area/code. * * @param termId term id * @param subjectCode subject area * @param form course offering management form * @throws Exception */ public void loadCourseOfferingsByTermAndSubjectCode(String termId, String subjectCode, CourseOfferingDisplayUI form) throws Exception { SearchRequestInfo searchRequest = new SearchRequestInfo( CourseOfferingManagementSearchImpl.CO_MANAGEMENT_SEARCH.getKey()); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.SUBJECT_AREA, subjectCode); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.ATP_ID, termId); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.CROSS_LIST_SEARCH_ENABLED, BooleanUtils.toStringTrueFalse(true)); loadCourseOfferings(searchRequest, form); /* if (form.getCourseOfferingResultList().isEmpty()) { LOG.error("Error: Can't find any Course Offering for a Subject Code: " + subjectCode + " in term: " + termId); GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS, CourseOfferingConstants.COURSEOFFERING_MSG_ERROR_NO_COURSE_OFFERING_IS_FOUND, "Subject Code", subjectCode, termId); }*/ } /** * This method fetches, prepares and sets * activityWrapperList for View All Activities tab, * clusterResultList for View byClusters * rgResultList for View Registration Groupsall the course offerings for a term and course/subject code. * Note: Use the other overloaded function when the client needs to specify search params * * @param form input form * @throws Exception */ public void build_AOs_RGs_AOCs_Lists_For_TheCourseOffering(ActivityOfferingDisplayUI form) throws Exception { //First search for AOs and Cluster information SearchRequestInfo searchRequestInfo = new SearchRequestInfo( ActivityOfferingSearchServiceImpl.AOS_AND_CLUSTERS_BY_CO_ID_SEARCH_KEY); this.build_AOs_RGs_AOCs_Lists_For_TheCourseOffering(form, searchRequestInfo, false); } /** * This method fetches, prepares and sets * activityWrapperList for View All Activities tab, * clusterResultList for View byClusters * rgResultList for View Registration Groupsall the course offerings for a term and course/subject code. * Note: Use the other overloaded function when the client does not need to specify search params * * @param form input form * @param sr Client supplied search info with params * @throws Exception */ public void build_AOs_RGs_AOCs_Lists_For_TheCourseOffering(ActivityOfferingDisplayUI form, SearchRequestInfo sr, boolean socView) throws Exception { //KSENROLL-6102 performance improvements, delete this code when performance work is complete //New Search Stuff! String coId = form.getCourseOfferingId(); List<String> filterRegGroupStates = null; List<String> filterAOStates = null; for (SearchParamInfo param : sr.getParams()) { if (StringUtils.equals(param.getKey(), ActivityOfferingSearchServiceImpl.SearchParameters.REGGROUP_STATES)) { filterRegGroupStates = param.getValues(); } if (StringUtils.equals(param.getKey(), ActivityOfferingSearchServiceImpl.SearchParameters.AO_STATES)) { filterAOStates = param.getValues(); } } sr.addParam(ActivityOfferingSearchServiceImpl.SearchParameters.CO_ID, coId); SearchResultInfo results = CourseOfferingManagementUtil.getSearchService().search(sr, null); Map<String, List<ActivityOfferingWrapper>> sch2aoMap = new HashMap<String, List<ActivityOfferingWrapper>>(); List<String> aoIdsWithoutSch = new ArrayList<String>(); Map<String, ActivityOfferingClusterWrapper> clusterMap = new HashMap<String, ActivityOfferingClusterWrapper>(); Map<String, ActivityOfferingWrapper> aoMap = new HashMap<String, ActivityOfferingWrapper>(); Map<String, FormatOfferingInfo> foIds = new HashMap<String, FormatOfferingInfo>(); Map<String, List<ScheduleCalcContainer>> ao2sch = new HashMap<String, List<ScheduleCalcContainer>>(); Map<String, List<ScheduleRequestCalcContainer>> ao2schReq = new HashMap<String, List<ScheduleRequestCalcContainer>>(); ContextInfo contextInfo = ContextUtils.createDefaultContextInfo(); //Parse the search results List<ActivityOfferingWrapper> wrappers = processAoClusterData(results, sch2aoMap, clusterMap, aoMap, foIds, aoIdsWithoutSch, contextInfo); setupRuleIndicator(wrappers); processAosData(coId, clusterMap); //Sort Activity Wrappers and Clusters ArrayList<ActivityOfferingClusterWrapper> clusterWrapperList = new ArrayList<ActivityOfferingClusterWrapper>( clusterMap.values()); if (clusterWrapperList.size() > 1) { Collections.sort(clusterWrapperList, new Comparator<ActivityOfferingClusterWrapper>() { @Override public int compare(ActivityOfferingClusterWrapper o1, ActivityOfferingClusterWrapper o2) { int nameComparison = o1.getAoCluster().getPrivateName() .compareToIgnoreCase(o2.getAoCluster().getPrivateName()); int formatComparison = o1.getFormatNameForDisplay() .compareToIgnoreCase(o2.getFormatNameForDisplay()); if (formatComparison == 0) { return nameComparison; } else { return formatComparison; } } }); } if (wrappers.size() > 1) { Collections.sort(wrappers, new Comparator<ActivityOfferingWrapper>() { @Override public int compare(ActivityOfferingWrapper o1, ActivityOfferingWrapper o2) { int typeComparison = (o1.getTypeName().compareTo(o2.getTypeName())) * -1; int nameComparison = o1.getActivityCode().compareTo(o2.getActivityCode()); if (typeComparison == 0) { return nameComparison; } else { return typeComparison; } } }); } //Set the items in the form form.setActivityWrapperList(wrappers); form.getClusterResultList().clear(); form.getClusterResultList().addAll(clusterWrapperList); //fix for KSENROLL-7886: foIds was populated in processAoClusterData method. //However if one FO does not have a cluster and AO, that FO won't be added to foIds, which causes NPE error later. foIds = new HashMap<String, FormatOfferingInfo>(); List<FormatOfferingInfo> foList = CourseOfferingManagementUtil.getCourseOfferingService() .getFormatOfferingsByCourseOffering(coId, ContextUtils.createDefaultContextInfo()); for (FormatOfferingInfo fo : foList) { foIds.put(fo.getId(), fo); } form.setFoId2aoTypeMap(foIds); if (!aoMap.keySet().isEmpty()) { //Process Colocated sr = new SearchRequestInfo(ActivityOfferingSearchServiceImpl.COLOCATED_AOS_BY_AO_IDS_SEARCH_KEY); sr.addParam(ActivityOfferingSearchServiceImpl.SearchParameters.AO_IDS, new ArrayList<String>(aoMap.keySet())); sr.addParam(ActivityOfferingSearchServiceImpl.SearchParameters.AO_STATES, filterAOStates); results = CourseOfferingManagementUtil.getSearchService().search(sr, null); processColocated(results, aoMap); //Addin LPR data processInstructors(aoMap, ContextUtils.createDefaultContextInfo()); //Search for schedule information if (!sch2aoMap.isEmpty()) { sr = new SearchRequestInfo(CoreSearchServiceImpl.SCH_AND_ROOM_SEARH_BY_ID_SEARCH_KEY); sr.addParam(CoreSearchServiceImpl.SearchParameters.SCHEDULE_IDS, new ArrayList<String>(sch2aoMap.keySet())); results = CourseOfferingManagementUtil.getSearchService().search(sr, null); // the next two methods pull scheduling data from the DB and put them into the ao2sch map processScheduleInfo(results, sch2aoMap, ao2sch); } processScheduleRequestsForAos(aoIdsWithoutSch, ao2schReq, contextInfo); // this takes the scheduling data and puts it into the screen form processScheduleData(aoMap, ao2sch, ao2schReq); //Search for registration group information sr = new SearchRequestInfo(ActivityOfferingSearchServiceImpl.REG_GROUPS_BY_CO_ID_SEARCH_KEY); sr.addParam(ActivityOfferingSearchServiceImpl.SearchParameters.CO_ID, form.getCourseOfferingId()); if (filterRegGroupStates != null && !filterRegGroupStates.isEmpty()) { sr.addParam(ActivityOfferingSearchServiceImpl.SearchParameters.REGGROUP_STATES, filterRegGroupStates); } results = CourseOfferingManagementUtil.getSearchService().search(sr, null); List<RegistrationGroupWrapper> rgWrappers; if (socView) { rgWrappers = processRgDataForSocView(results, clusterMap, aoMap); } else { rgWrappers = processRgData(results, clusterMap, aoMap); } //Sort rgWrappers if (rgWrappers.size() > 1) { Collections.sort(rgWrappers, new Comparator<RegistrationGroupWrapper>() { @Override public int compare(RegistrationGroupWrapper o1, RegistrationGroupWrapper o2) { return o1.getRgInfo().getName().compareTo(o2.getRgInfo().getName()); } }); } form.setRgResultList(rgWrappers); form.setHasMoreThanOneCluster(clusterMap.size() > 1); //Validate Reg Groups Date startOfValidation = new Date(); int i = 0; for (ActivityOfferingClusterWrapper cluster : clusterWrapperList) { List<RegistrationGroupInfo> rgInfos = new ArrayList<RegistrationGroupInfo>(); for (RegistrationGroupWrapper rgWrapper : cluster.getRgWrapperList()) { rgInfos.add(rgWrapper.getRgInfo()); } List<ActivityOfferingInfo> aoInfos = new ArrayList<ActivityOfferingInfo>(); for (ActivityOfferingWrapper aoWrapper : cluster.getAoWrapperList()) { aoInfos.add(aoWrapper.getAoInfo()); } _validateRegistrationGroupsPerCluster(rgInfos, aoInfos, cluster, form, i, ao2sch, ao2schReq, aoMap); // Test the Cluster for Multiple AO types and Term types _validateMulitpleTermsPerCluster( form.getFoId2aoTypeMap().get(cluster.getFormatOfferingId()).getActivityOfferingTypeKeys(), cluster, i); i++; } Date endOfValidation = new Date(); LOG.info("Time of RG Validation: {}ms", (endOfValidation.getTime() - startOfValidation.getTime())); } } private void _validateMulitpleTermsPerCluster(List<String> aoTypeKeys, ActivityOfferingClusterWrapper cluster, int clusterIndex) { // Test the Cluster for Multiple AO types and Term types if (aoTypeKeys.size() > 1) { Set<String> termNameSet = new HashSet<String>(); Set<String> termNames = new HashSet<String>(); // Tests for multiple subTerms for (ActivityOfferingWrapper aoWrapper : cluster.getAoWrapperList()) { String termName = StringUtils.isEmpty(aoWrapper.getSubTermId()) ? aoWrapper.getTermName() : aoWrapper.getSubTermName(); if (!termNameSet.contains(termName)) { termNameSet.add(termName); } } if (termNameSet.size() > 1) { StringBuilder termNameStr = new StringBuilder(); for (String termName : termNameSet) { termNameStr.append(termName).append(", "); } termNameStr.delete(termNameStr.length() - 2, termNameStr.length()); GlobalVariables.getMessageMap().putWarningForSectionId( "activityOfferingsPerCluster_line" + clusterIndex, RegistrationGroupConstants.MSG_ERROR_CLUSTER_MULTIPLE_TERMS, cluster.getAoCluster().getPrivateName(), termNameStr.toString()); } } } private void processColocated(SearchResultInfo searchResults, Map<String, ActivityOfferingWrapper> aoMap) { for (SearchResultRowInfo row : searchResults.getRows()) { String aoId = null; String aoCode = null; String coCode = null; for (SearchResultCellInfo cell : row.getCells()) { if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_ID.equals(cell.getKey())) { aoId = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_CODE.equals(cell.getKey())) { aoCode = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.CO_CODE.equals(cell.getKey())) { coCode = cell.getValue(); } } ActivityOfferingWrapper aoWrapper = aoMap.get(aoId); aoWrapper.setColocatedAO(true); if (aoWrapper.getColocatedAoInfo() == null || aoWrapper.getColocatedAoInfo().isEmpty()) { aoWrapper.setColocatedAoInfo(coCode + " " + aoCode); } else { aoWrapper.setColocatedAoInfo(aoWrapper.getColocatedAoInfo() + "<br/>" + coCode + " " + aoCode); } } } private void processInstructors(Map<String, ActivityOfferingWrapper> aoMap, ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, DoesNotExistException, PermissionDeniedException, OperationFailedException { List<LprInfo> lprInfos = new ArrayList<LprInfo>(); for (String ao : aoMap.keySet()) { QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create(); qbcBuilder.setPredicates(PredicateFactory.in("luiId", ao), PredicateFactory.in("personRelationTypeId", LprServiceConstants.COURSE_INSTRUCTOR_TYPE_KEYS)); QueryByCriteria criteria = qbcBuilder.build(); lprInfos.addAll(CourseOfferingManagementUtil.getLprService().searchForLprs(criteria, contextInfo)); } if (lprInfos != null) { Map<String, Set<String>> personId2aoIdMap = new HashMap<String, Set<String>>(); for (LprInfo lprInfo : lprInfos) { // Only include the main instructor. if (!StringUtils.equals(lprInfo.getTypeKey(), LprServiceConstants.INSTRUCTOR_MAIN_TYPE_KEY)) { continue; } Set<String> aoIds = personId2aoIdMap.get(lprInfo.getPersonId()); if (aoIds == null) { aoIds = new HashSet<String>(); personId2aoIdMap.put(lprInfo.getPersonId(), aoIds); } aoIds.add(lprInfo.getLuiId()); } if (!personId2aoIdMap.keySet().isEmpty()) { EntityDefaultQueryResults results = getInstructorsInfoFromKim( new ArrayList<String>(personId2aoIdMap.keySet())); for (EntityDefault entity : results.getResults()) { Set<String> aoIds = personId2aoIdMap.get(entity.getEntityId()); if (aoIds != null) { for (String aoId : aoIds) { ActivityOfferingWrapper activityOfferingWrapper = aoMap.get(aoId); if (entity.getName() != null) { activityOfferingWrapper .setInstructorDisplayNames(entity.getName().getCompositeName(), true); } else { activityOfferingWrapper.setInstructorDisplayNames(entity.getEntityId()); } } } } } } } /** * Add scheduling information to the map if there are no "actual" schedules already in place for a particular AO. * * @param aoIdsWithoutSch list of aoIds without schedule information * @param ao2sch map of aos to schedules * @param contextInfo @throws Exception */ protected void processScheduleRequestsForAos(Collection<String> aoIdsWithoutSch, Map<String, List<ScheduleRequestCalcContainer>> ao2sch, ContextInfo contextInfo) throws Exception { if (!aoIdsWithoutSch.isEmpty()) { Set<String> buildingIds = new HashSet<String>(); Set<String> roomIds = new HashSet<String>(); Set<String> timeslotIds = new HashSet<String>(); Map<String, BuildingInfo> buildingIdMap = new HashMap<String, BuildingInfo>(); Map<String, RoomInfo> roomIdMap = new HashMap<String, RoomInfo>(); Map<String, TimeSlotInfo> timeslotIdMap = new HashMap<String, TimeSlotInfo>(); Map<String, List<ScheduleRequestInfo>> ao2srMap = new HashMap<String, List<ScheduleRequestInfo>>(); HashSet<String> aoIdsSet = new HashSet<String>(aoIdsWithoutSch); for (String aoId : aoIdsSet) { ao2srMap.put(aoId, new ArrayList<ScheduleRequestInfo>()); List<ScheduleRequestInfo> srList = CourseOfferingManagementUtil.getSchedulingService() .getScheduleRequestsByRefObjects( CourseOfferingServiceConstants.REF_OBJECT_URI_ACTIVITY_OFFERING, new ArrayList<String>(asList(aoId)), contextInfo); ao2srMap.get(aoId).addAll(srList); for (ScheduleRequestInfo sr : srList) { for (ScheduleRequestComponentInfo schRequestCom : sr.getScheduleRequestComponents()) { buildingIds.addAll(schRequestCom.getBuildingIds()); roomIds.addAll(schRequestCom.getRoomIds()); timeslotIds.addAll(schRequestCom.getTimeSlotIds()); } } } //Lookup the information using bulk service calls and store in maps List<TimeSlotInfo> timeSlotInfos = CourseOfferingManagementUtil.getSchedulingService() .getTimeSlotsByIds(new ArrayList<String>(timeslotIds), contextInfo); for (TimeSlotInfo timeSlotInfo : timeSlotInfos) { timeslotIdMap.put(timeSlotInfo.getId(), timeSlotInfo); } // The method cachkey in RoomServiceImpl is checking to see if a list is empty, contains null or contains empaty // and it throws an exception. To avoid that check to see if the list is a valid list first. Awkward, I know. if (!roomIds.isEmpty() && !roomIds.contains(null) && !roomIds.contains("")) { List<RoomInfo> roomInfos = CourseOfferingManagementUtil.getRoomService() .getRoomsByIds(new ArrayList<String>(roomIds), contextInfo); for (RoomInfo roomInfo : roomInfos) { roomIdMap.put(roomInfo.getId(), roomInfo); buildingIds.add(roomInfo.getBuildingId()); } } // The method cachkey in RoomServiceImpl is checking to see if a list is empty, contains null or contains empaty // and it throws an exception. To avoid that check to see if the list is a valid list first. Awkward, I know. if (!buildingIds.isEmpty() && !buildingIds.contains(null) && !buildingIds.contains("")) { List<BuildingInfo> buildingInfos = CourseOfferingManagementUtil.getRoomService() .getBuildingsByIds(new ArrayList<String>(buildingIds), contextInfo); for (BuildingInfo buildingInfo : buildingInfos) { buildingIdMap.put(buildingInfo.getId(), buildingInfo); } } for (String aoId : aoIdsSet) { List<ScheduleRequestCalcContainer> srccList = new ArrayList<ScheduleRequestCalcContainer>(); ao2sch.put(aoId, srccList); for (ScheduleRequestInfo sr : ao2srMap.get(aoId)) { for (ScheduleRequestComponentInfo src : sr.getScheduleRequestComponents()) { List<RoomInfo> rooms = new ArrayList<RoomInfo>(); List<BuildingInfo> buildings = new ArrayList<BuildingInfo>(); List<TimeSlotInfo> timeSlots = new ArrayList<TimeSlotInfo>(); for (String roomId : src.getRoomIds()) { if (roomId != null) { rooms.add(roomIdMap.get(roomId)); buildings.add(buildingIdMap.get(roomIdMap.get(roomId).getBuildingId())); } } if (src.getRoomIds().isEmpty()) { for (String buildingId : src.getBuildingIds()) { buildings.add(buildingIdMap.get(buildingId)); } } for (String timeSlotId : src.getTimeSlotIds()) { TimeSlotInfo timeSlotInfo = timeslotIdMap.get(timeSlotId); timeSlots.add(timeSlotInfo); } ScheduleRequestCalcContainer srcc = new ScheduleRequestCalcContainer(aoId, sr.getId(), CourseOfferingServiceConstants.REF_OBJECT_URI_ACTIVITY_OFFERING, timeSlots, rooms, buildings, src.getIsTBA()); srccList.add(srcc); } } } } } private void processScheduleInfo(SearchResultInfo searchResults, Map<String, List<ActivityOfferingWrapper>> sch2aoMap, Map<String, List<ScheduleCalcContainer>> ao2sch) throws InvalidParameterException, MissingParameterException, PermissionDeniedException, OperationFailedException, DoesNotExistException { //Process the search results for (SearchResultRowInfo row : searchResults.getRows()) { String schId = null; String startTime = null; String endTime = null; Boolean tbaInd = null; String roomCode = null; String buildingName = null; String buildingCode = null; String weekdays = null; for (SearchResultCellInfo cell : row.getCells()) { if (CoreSearchServiceImpl.SearchResultColumns.SCH_ID.equals(cell.getKey())) { schId = cell.getValue(); } else if (CoreSearchServiceImpl.SearchResultColumns.START_TIME.equals(cell.getKey())) { startTime = cell.getValue(); } else if (CoreSearchServiceImpl.SearchResultColumns.END_TIME.equals(cell.getKey())) { endTime = cell.getValue(); } else if (CoreSearchServiceImpl.SearchResultColumns.TBA_IND.equals(cell.getKey())) { tbaInd = Boolean.parseBoolean(cell.getValue()); } else if (CoreSearchServiceImpl.SearchResultColumns.ROOM_CODE.equals(cell.getKey())) { roomCode = cell.getValue(); } else if (CoreSearchServiceImpl.SearchResultColumns.BLDG_NAME.equals(cell.getKey())) { buildingName = cell.getValue(); } else if (CoreSearchServiceImpl.SearchResultColumns.BLDG_CODE.equals(cell.getKey())) { buildingCode = cell.getValue(); } else if (CoreSearchServiceImpl.SearchResultColumns.WEEKDAYS.equals(cell.getKey())) { weekdays = cell.getValue(); } } for (ActivityOfferingWrapper aoWrapper : sch2aoMap.get(schId)) { ScheduleCalcContainer scheduleCalcContainer = new ScheduleCalcContainer(aoWrapper.getId(), schId, SchedulingServiceConstants.SCHEDULE_TYPE_SCHEDULE, startTime, endTime, weekdays, roomCode, buildingName, buildingCode, tbaInd); if (ao2sch.containsKey(aoWrapper.getId())) { ao2sch.get(aoWrapper.getId()).add(scheduleCalcContainer); } else { aoWrapper.getStartTime().clear(); aoWrapper.getEndTime().clear(); aoWrapper.getWeekDays().clear(); List<ScheduleCalcContainer> schList = new ArrayList<ScheduleCalcContainer>(); schList.add(scheduleCalcContainer); aoWrapper.getStartTime().add(startTime); aoWrapper.getEndTime().add(endTime); aoWrapper.getWeekDays().add(weekdays); ao2sch.put(aoWrapper.getId(), schList); } } } } private void processScheduleData(Map<String, ActivityOfferingWrapper> aoMap, Map<String, List<ScheduleCalcContainer>> ao2sch, Map<String, List<ScheduleRequestCalcContainer>> ao2schReq) throws Exception { for (Map.Entry<String, ActivityOfferingWrapper> aoEntry : aoMap.entrySet()) { ActivityOfferingWrapper aoWrapper = aoEntry.getValue(); String aoId = aoEntry.getKey(); if (ao2sch.containsKey(aoId)) { List<ScheduleCalcContainer> schedList = ao2sch.get(aoId); boolean newRow = false; for (ScheduleCalcContainer sched : schedList) { // Start and End are assigned a value of TimeOfDayInfo(0,0,0)). Perhaps this code can be cleaned up. // The same thing is repeated in a few places. See jira KSENROLL-11518 TimeOfDayInfo start = sched.getStart().isEmpty() ? null : TimeOfDayHelper.setMillis(Long.parseLong(sched.getStart())); aoWrapper.setStartTimeDisplay((start == null || start.equals(new TimeOfDayInfo(0, 0, 0))) ? "" : TimeOfDayHelper.makeFormattedTimeForAOSchedules(start), newRow); TimeOfDayInfo end = sched.getEnd().isEmpty() ? null : TimeOfDayHelper.setMillis(Long.parseLong(sched.getEnd())); aoWrapper.setEndTimeDisplay((end == null || end.equals(new TimeOfDayInfo(0, 0, 0))) ? "" : TimeOfDayHelper.makeFormattedTimeForAOSchedules(end), newRow); aoWrapper.setBuildingName(sched.getBldgName(), newRow); aoWrapper.setBuildingCode(sched.getBldgCode(), newRow); aoWrapper.setBldgCodeSimple(sched.getBldgCode()); aoWrapper.setRoomName(sched.getRoomCode(), newRow); aoWrapper.setDaysDisplayName(sched.getWeekdays(), newRow); aoWrapper.setTbaDisplayName(sched.getTbaInd(), newRow); HashMap schedulingStateHash = aoWrapper.getSchedulingStateHash(); String key = aoWrapper.getAoInfo().getSchedulingStateKey(); if (StringUtils.isBlank(key)) { key = LuiServiceConstants.LUI_AO_SCHEDULING_STATE_SCHEDULED_KEY; } String schState = (String) schedulingStateHash.get(key); aoWrapper.setScheduledState(schState, newRow); newRow = true; } } else if (ao2schReq.containsKey((aoId))) { List<ScheduleRequestCalcContainer> schedList = ao2schReq.get(aoId); for (ScheduleRequestCalcContainer sched : schedList) { boolean newLine = aoWrapper.getTbaDisplayName() != null && !aoWrapper.getTbaDisplayName().isEmpty(); String cssStyle = "uif-scheduled-dl"; setRoomNameOnAoWrapper(sched, aoWrapper, newLine, cssStyle); setBuildingNameAndCodeOnAoWrapper(sched, aoWrapper, newLine, cssStyle); setTimesAndDaysAndScheduledStateOnAoWrapper(sched, aoWrapper, newLine, cssStyle); aoWrapper.setTbaDisplayName(sched.getTbaInd(), true); } } } } private void setRoomNameOnAoWrapper(ScheduleRequestCalcContainer sched, ActivityOfferingWrapper aoWrapper, boolean newline, String cssStyle) { if (sched.getRooms() == null || sched.getRooms().isEmpty()) { aoWrapper.setRoomName(StringUtils.EMPTY, newline, cssStyle); return; } for (RoomInfo room : sched.getRooms()) { String roomName = StringUtils.defaultIfEmpty(room.getRoomCode(), StringUtils.EMPTY); aoWrapper.setRoomName(roomName, newline, cssStyle); } } private void setBuildingNameAndCodeOnAoWrapper(ScheduleRequestCalcContainer sched, ActivityOfferingWrapper aoWrapper, boolean newline, String cssStyle) { if (sched.getBldgs() == null || sched.getBldgs().isEmpty()) { aoWrapper.setBuildingName(StringUtils.EMPTY, newline, cssStyle); aoWrapper.setBuildingCode(StringUtils.EMPTY, newline, cssStyle); aoWrapper.setBldgCodeSimple(StringUtils.EMPTY); return; } for (BuildingInfo bldg : sched.getBldgs()) { String bldgName = StringUtils.defaultIfEmpty(bldg.getName(), StringUtils.EMPTY); String bldgCode = StringUtils.defaultIfEmpty(bldg.getBuildingCode(), StringUtils.EMPTY); aoWrapper.setBuildingName(bldgName, newline, "uif-scheduled-dl"); aoWrapper.setBuildingCode(bldgCode, newline, "uif-scheduled-dl"); aoWrapper.setBldgCodeSimple(bldgCode, bldgName, "uif-scheduled-dl"); } } private void setTimesAndDaysAndScheduledStateOnAoWrapper(ScheduleRequestCalcContainer sched, ActivityOfferingWrapper aoWrapper, boolean newline, String cssStyle) { if (sched.getTimeSlots() == null || sched.getTimeSlots().isEmpty()) { setStartTimeOnAoWrapper(null, aoWrapper, newline, cssStyle); setEndTimeOnAoWrapper(null, aoWrapper, newline, cssStyle); setDaysOnAoWrapper(null, aoWrapper, newline, cssStyle); setScheduledStateOnAoWrapper(null, aoWrapper, newline, cssStyle); return; } for (TimeSlotInfo timeSlotInfo : sched.getTimeSlots()) { setStartTimeOnAoWrapper(timeSlotInfo, aoWrapper, newline, cssStyle); setEndTimeOnAoWrapper(timeSlotInfo, aoWrapper, newline, cssStyle); setDaysOnAoWrapper(timeSlotInfo, aoWrapper, newline, cssStyle); if (timeSlotInfo != null) { boolean timeAdded = false; if (timeSlotInfo.getStartTime() != null && timeSlotInfo.getStartTime().getHour() != null) { aoWrapper.getStartTime().add(TimeOfDayHelper.getMillis(timeSlotInfo.getStartTime()).toString()); timeAdded = true; } if (timeSlotInfo.getEndTime() != null && timeSlotInfo.getEndTime().getHour() != null) { aoWrapper.getEndTime().add(TimeOfDayHelper.getMillis(timeSlotInfo.getEndTime()).toString()); timeAdded = true; } if (timeSlotInfo.getWeekdays() != null && !timeSlotInfo.getWeekdays().isEmpty()) { aoWrapper.getWeekDays() .add(SchedulingServiceUtil.weekdaysList2WeekdaysString(timeSlotInfo.getWeekdays())); timeAdded = true; } if (timeAdded) { setScheduledStateOnAoWrapper(timeSlotInfo, aoWrapper, newline, cssStyle); } } } } private void setStartTimeOnAoWrapper(TimeSlotInfo timeSlotInfo, ActivityOfferingWrapper aoWrapper, boolean newline, String cssStyle) { if (timeSlotInfo == null || timeSlotInfo.getStartTime() == null || timeSlotInfo.getStartTime().equals(new TimeOfDayInfo(0, 0, 0))) { aoWrapper.setStartTimeDisplay(StringUtils.EMPTY, newline, cssStyle); return; } aoWrapper.setStartTimeDisplay(TimeOfDayHelper.makeFormattedTimeForAOSchedules(timeSlotInfo.getStartTime()), newline, "uif-scheduled-dl"); } private void setEndTimeOnAoWrapper(TimeSlotInfo timeSlotInfo, ActivityOfferingWrapper aoWrapper, boolean newline, String cssStyle) { if (timeSlotInfo == null || timeSlotInfo.getEndTime() == null || timeSlotInfo.getEndTime().equals(new TimeOfDayInfo(0, 0, 0))) { aoWrapper.setEndTimeDisplay(StringUtils.EMPTY, newline, cssStyle); return; } aoWrapper.setEndTimeDisplay(TimeOfDayHelper.makeFormattedTimeForAOSchedules(timeSlotInfo.getEndTime()), newline, "uif-scheduled-dl"); } private void setScheduledStateOnAoWrapper(TimeSlotInfo timeSlotInfo, ActivityOfferingWrapper aoWrapper, boolean newline, String cssStyle) { if (timeSlotInfo == null) { aoWrapper.setScheduledState(StringUtils.EMPTY, newline, cssStyle); return; } HashMap schedulingStateHash = aoWrapper.getSchedulingStateHash(); String key = aoWrapper.getAoInfo().getSchedulingStateKey(); if (StringUtils.isBlank(key)) { key = LuiServiceConstants.LUI_AO_SCHEDULING_STATE_UNSCHEDULED_KEY; } String schState = (String) schedulingStateHash.get(key); aoWrapper.setScheduledState(schState, newline, "uif-scheduled-dl"); } private void setDaysOnAoWrapper(TimeSlotInfo timeSlotInfo, ActivityOfferingWrapper aoWrapper, boolean newline, String cssStyle) { if (timeSlotInfo == null || timeSlotInfo.getWeekdays() == null || timeSlotInfo.getWeekdays().isEmpty()) { aoWrapper.setDaysDisplayName(StringUtils.EMPTY, newline, cssStyle); return; } aoWrapper.setDaysDisplayName(SchedulingServiceUtil.weekdaysList2WeekdaysString(timeSlotInfo.getWeekdays()), newline, cssStyle); } private List<RegistrationGroupWrapper> processRgData(SearchResultInfo searchResults, Map<String, ActivityOfferingClusterWrapper> clusterMap, Map<String, ActivityOfferingWrapper> aoMap) throws InvalidParameterException, MissingParameterException, DoesNotExistException, PermissionDeniedException, OperationFailedException { Map<String, RegistrationGroupWrapper> rgMap = new HashMap<String, RegistrationGroupWrapper>(); Map<String, List<ActivityOfferingWrapper>> storedAOs = new HashMap<String, List<ActivityOfferingWrapper>>(); processSearchResult(searchResults, aoMap, rgMap, storedAOs); for (Map.Entry<String, List<ActivityOfferingWrapper>> entry : storedAOs.entrySet()) { RegistrationGroupWrapper rgWrapper = rgMap.get(entry.getKey()); //Sort aoList by AO types List<ActivityOfferingWrapper> aoList = storedAOs.get(entry.getKey()); Collections.sort(aoList, new ActivityOfferingTypeComparator()); boolean newLine = false; for (ActivityOfferingWrapper aoWrapper : aoList) { rgWrapper.getRgInfo().getActivityOfferingIds().add(aoWrapper.getAoInfo().getId()); ActivityOfferingClusterWrapper clusterWrapper = clusterMap.get(aoWrapper.getAoClusterID()); if (clusterWrapper.getRgWrapperList().contains(rgWrapper)) { clusterWrapper.getRgWrapperList().remove(rgWrapper); } if (newLine) { rgWrapper.setAoCluster(clusterWrapper.getAoCluster()); rgWrapper.setAoClusterName(clusterWrapper.getClusterNameForDisplay()); } rgWrapper.setStartTime(aoWrapper.getStartTime()); rgWrapper.setEndTime(aoWrapper.getEndTime()); rgWrapper.setWeekDays(aoWrapper.getWeekDays()); //if there are more than one instructors re-arrange the rows String lineBreaksInstructors = computeLineBreaks(aoWrapper.getInstructorDisplayNames()); //if there are more than one Scheduling Information re-arrange the rows String lineBreaksDeliveries = computeLineBreaks(aoWrapper.getDaysDisplayName()); String lineBreaks; //Set different line breaks according to number of instructors and number of Scheduling Information (can it be simpler?) if (lineBreaksInstructors.length() < lineBreaksDeliveries.length()) { lineBreaks = lineBreaksDeliveries; lineBreaksDeliveries = lineBreaksDeliveries.substring(0, lineBreaksDeliveries.length() - lineBreaksInstructors.length()); lineBreaksInstructors = ""; } else { lineBreaks = lineBreaksInstructors; lineBreaksInstructors = lineBreaksInstructors.substring(0, lineBreaksInstructors.length() - lineBreaksDeliveries.length()); lineBreaksDeliveries = ""; } //Set the wrapper rgWrapper.setAoMaxEnrText(rgWrapper.getAoMaxEnrText() + (newLine ? "<br/>" : "") + (aoWrapper.getAoInfo().getMaximumEnrollment() == null ? "" : aoWrapper.getAoInfo().getMaximumEnrollment()) + lineBreaks); if (rgWrapper.getRgMaxEnrText() != null && rgWrapper.getRgMaxEnrText().length() > 1 && aoWrapper.getAoInfo().getMaximumEnrollment() != null) { Integer seats = Integer.parseInt(rgWrapper.getRgMaxEnrText()); Integer nSeats = aoWrapper.getAoInfo().getMaximumEnrollment(); if (seats.compareTo(nSeats) > 0) { rgWrapper.setRgMaxEnrText(nSeats.toString()); } } else { String rgSeats = aoWrapper.getAoInfo().getMaximumEnrollment() == null ? "" : aoWrapper.getAoInfo().getMaximumEnrollment().toString(); rgWrapper.setRgMaxEnrText(rgSeats); } rgWrapper.setAoStateNameText(rgWrapper.getAoStateNameText() + (newLine ? "<br/>" : "") + aoWrapper.getStateName() + lineBreaks); String aoCode = getAoActivityCodeText(rgWrapper, aoWrapper, lineBreaks); rgWrapper.setAoActivityCodeText( rgWrapper.getAoActivityCodeText() + (newLine ? "<br/>" : "") + aoCode); rgWrapper.setAoTypeNameText(rgWrapper.getAoTypeNameText() + (newLine ? "<br/>" : "") + aoWrapper.getTypeName() + lineBreaks); rgWrapper.setStartTimeDisplay(rgWrapper.getStartTimeDisplay() + (newLine ? "<br/>" : "") + aoWrapper.getStartTimeDisplay() + lineBreaksInstructors); rgWrapper.setEndTimeDisplay(rgWrapper.getEndTimeDisplay() + (newLine ? "<br/>" : "") + aoWrapper.getEndTimeDisplay() + lineBreaksInstructors); rgWrapper.setDaysDisplayName(rgWrapper.getDaysDisplayName() + (newLine ? "<br/>" : "") + aoWrapper.getDaysDisplayName() + lineBreaksInstructors); rgWrapper.setScheduledState(rgWrapper.getScheduledState() + (newLine ? "<br/>" : "") + aoWrapper.getScheduledState() + lineBreaksInstructors); rgWrapper.setRoomName(rgWrapper.getRoomName() + (newLine ? "<br/>" : "") + aoWrapper.getRoomName() + lineBreaksInstructors); rgWrapper.setBuildingName(rgWrapper.getBuildingName() + (newLine ? "<br/>" : "") + aoWrapper.getBuildingName() + lineBreaksInstructors); boolean isScheduled = aoWrapper.getBuildingName().contains("uif-scheduled-dl"); if (isScheduled) { rgWrapper.setBuildingCodeWithTooltip(aoWrapper.getBldgCodeSimple(), aoWrapper.getBuildingName(), "uif-scheduled-dl"); } else { rgWrapper.setBuildingCodeWithTooltip(aoWrapper.getBldgCodeSimple(), aoWrapper.getBuildingName(), (newLine ? "<br>" : "uif-scheduled-dl")); } rgWrapper.setAoInstructorText(rgWrapper.getAoInstructorText() + (newLine ? "<br/>" : "") + (aoWrapper.getInstructorDisplayNames() == null ? "" : aoWrapper.getInstructorDisplayNames()) + lineBreaksDeliveries); clusterWrapper.getRgWrapperList().add(rgWrapper); newLine = true; } } return new ArrayList<RegistrationGroupWrapper>(rgMap.values()); } private List<RegistrationGroupWrapper> processRgDataForSocView(SearchResultInfo searchResults, Map<String, ActivityOfferingClusterWrapper> clusterMap, Map<String, ActivityOfferingWrapper> aoMap) throws InvalidParameterException, MissingParameterException, DoesNotExistException, PermissionDeniedException, OperationFailedException { Map<String, RegistrationGroupWrapper> rgMap = new HashMap<String, RegistrationGroupWrapper>(); Map<String, List<ActivityOfferingWrapper>> storedAOs = new HashMap<String, List<ActivityOfferingWrapper>>(); processSearchResult(searchResults, aoMap, rgMap, storedAOs); for (Map.Entry<String, List<ActivityOfferingWrapper>> entry : storedAOs.entrySet()) { RegistrationGroupWrapper rgWrapper = rgMap.get(entry.getKey()); //Sort aoList by AO types Collections.sort(entry.getValue(), new ActivityOfferingTypeComparator()); for (ActivityOfferingWrapper aoWrapper : entry.getValue()) { RegistrationGroupWrapper socRGWrapper = (RegistrationGroupWrapper) ObjectUtils.deepCopy(rgWrapper); ActivityOfferingClusterWrapper clusterWrapper = clusterMap.get(aoWrapper.getAoClusterID()); clusterWrapper.getRgWrapperList().add(socRGWrapper); socRGWrapper.getRgInfo().getActivityOfferingIds().add(aoWrapper.getAoInfo().getId()); socRGWrapper.setAoCluster(clusterWrapper.getAoCluster()); socRGWrapper.setAoClusterName(clusterWrapper.getClusterNameForDisplay()); socRGWrapper.setStartTime(aoWrapper.getStartTime()); socRGWrapper.setEndTime(aoWrapper.getEndTime()); socRGWrapper.setWeekDays(aoWrapper.getWeekDays()); //if there are more than one instructors re-arrange the rows String lineBreaksInstructors = computeLineBreaks(aoWrapper.getInstructorDisplayNames()); //if there are more than one Scheduling Information re-arrange the rows String lineBreaksDeliveries = computeLineBreaks(aoWrapper.getDaysDisplayName()); //Set different line breaks according to number of instructors and number of Scheduling Information (can it be simpler?) String lineBreaks; if (lineBreaksInstructors.length() < lineBreaksDeliveries.length()) { lineBreaks = lineBreaksDeliveries; lineBreaksDeliveries = lineBreaksDeliveries.substring(0, lineBreaksDeliveries.length() - lineBreaksInstructors.length()); lineBreaksInstructors = ""; } else { lineBreaks = lineBreaksInstructors; lineBreaksInstructors = lineBreaksInstructors.substring(0, lineBreaksInstructors.length() - lineBreaksDeliveries.length()); lineBreaksDeliveries = ""; } //Set the wrapper socRGWrapper.setAoMaxEnrText(aoWrapper.getAoInfo().getMaximumEnrollment() == null ? "" : aoWrapper.getAoInfo().getMaximumEnrollment().toString()); socRGWrapper.setAoStateNameText(aoWrapper.getStateName()); socRGWrapper.setAoActivityCodeText(getAoActivityCodeText(rgWrapper, aoWrapper, lineBreaks)); socRGWrapper.setAoTypeNameText(aoWrapper.getTypeName() + lineBreaks); socRGWrapper.setStartTimeDisplay(aoWrapper.getStartTimeDisplay() + lineBreaksInstructors); socRGWrapper.setEndTimeDisplay(aoWrapper.getEndTimeDisplay() + lineBreaksInstructors); socRGWrapper.setDaysDisplayName(aoWrapper.getDaysDisplayName() + lineBreaksInstructors); socRGWrapper.setRoomName(aoWrapper.getRoomName() + lineBreaksInstructors); socRGWrapper.setBuildingName(aoWrapper.getBuildingName() + lineBreaksInstructors); socRGWrapper.setBuildingCodeWithTooltip(aoWrapper.getBldgCodeSimple(), aoWrapper.getBuildingName()); socRGWrapper.setAoInstructorText( (aoWrapper.getInstructorDisplayNames() == null ? "" : aoWrapper.getInstructorDisplayNames()) + lineBreaksDeliveries); } } for (Map.Entry<String, ActivityOfferingClusterWrapper> cluster : clusterMap.entrySet()) { List<RegistrationGroupWrapper> registrationGroupItems = cluster.getValue().getRgWrapperList(); for (RegistrationGroupWrapper registrationGroupWrapper : registrationGroupItems) { RegistrationGroupWrapper regWrapper = new RegistrationGroupWrapper(); for (RegistrationGroupWrapper partnerRegWrapper : registrationGroupItems) { if (registrationGroupWrapper.getRgInfo().getName() .equals(partnerRegWrapper.getRgInfo().getName()) && !registrationGroupWrapper.getAoActivityCodeText() .equals(partnerRegWrapper.getAoActivityCodeText())) { regWrapper = partnerRegWrapper; break; } } if (registrationGroupWrapper.getAoMaxEnrText() != null && registrationGroupWrapper.getAoMaxEnrText().length() > 1) { if (regWrapper.getAoMaxEnrText() != null && regWrapper.getAoMaxEnrText().length() > 1) { Integer seats = Integer.parseInt(registrationGroupWrapper.getAoMaxEnrText()); Integer nSeats = Integer.parseInt(regWrapper.getAoMaxEnrText()); if (seats.compareTo(nSeats) > 0) { registrationGroupWrapper.setRgMaxEnrText(nSeats.toString()); regWrapper.setRgMaxEnrText(nSeats.toString()); } else { registrationGroupWrapper.setRgMaxEnrText(seats.toString()); regWrapper.setRgMaxEnrText(seats.toString()); } } } } } return new ArrayList<RegistrationGroupWrapper>(rgMap.values()); } private String getAoActivityCodeText(RegistrationGroupWrapper rgWrapper, ActivityOfferingWrapper aoWrapper, String lineBreaks) { StringBuilder sb = new StringBuilder(); sb.append(aoWrapper.getAoInfo().getActivityCode()); //sub-term and honors icon and tooltip setup if (aoWrapper.getAoInfo().getIsHonorsOffering()) { sb.append(" <img src=\"../themes/ksboot/images/h.png\" title=\"Honors activity"); sb.append("\">"); sb.append(lineBreaks); } if (!aoWrapper.getSubTermName().equals("None")) { //sub-term? > icon + name and dates sb.append( " <img src=\"../themes/ksboot/images/subterm_icon.png\" title=\"This activity is in "); sb.append(aoWrapper.getSubTermName()); sb.append(" -\n"); sb.append(aoWrapper.getTermStartEndDate()); sb.append("\">"); sb.append(lineBreaks); } return sb.toString(); } private String computeLineBreaks(String displayString) { StringBuilder lineBreaksSB = new StringBuilder(); if (displayString != null && StringUtils.contains(displayString, ("<br>"))) { //more than one instructor String s = displayString; for (int k = 0; k < s.length(); k++) { //add lines according to number of Scheduling Information if (s.contains("<br>")) { lineBreaksSB.append("<br/>"); s = s.substring(s.indexOf("<br>") + 4); } else { break; } } } return lineBreaksSB.toString(); } private void processSearchResult(SearchResultInfo searchResults, Map<String, ActivityOfferingWrapper> aoMap, Map<String, RegistrationGroupWrapper> rgMap, Map<String, List<ActivityOfferingWrapper>> storedAOs) throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException { for (SearchResultRowInfo row : searchResults.getRows()) { String aoId = null; String rgId = null; String rgName = null; String rgState = null; for (SearchResultCellInfo cell : row.getCells()) { if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_ID.equals(cell.getKey())) { aoId = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.RG_ID.equals(cell.getKey())) { rgId = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.RG_NAME.equals(cell.getKey())) { rgName = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.RG_STATE.equals(cell.getKey())) { rgState = cell.getValue(); } } ActivityOfferingWrapper aoWrapper = aoMap.get(aoId); if (aoWrapper == null) { continue; } if (!rgMap.containsKey(rgId)) { storedAOs.put(rgId, new ArrayList<ActivityOfferingWrapper>()); String rgStateKey = getStateService().getState(rgState, ContextUtils.createDefaultContextInfo()) .getName(); rgMap.put(rgId, createRegistrationGroupWrapper(rgId, rgName, rgState, rgStateKey)); } storedAOs.get(rgId).add(aoWrapper); } } private RegistrationGroupWrapper createRegistrationGroupWrapper(String rgId, String rgName, String rgState, String rgStateKey) { RegistrationGroupWrapper rgWrapper = new RegistrationGroupWrapper(); rgWrapper.setStateKey(rgState, rgStateKey); rgWrapper.getRgInfo().setName(rgName); rgWrapper.getRgInfo().setId(rgId); rgWrapper.setAoMaxEnrText(""); rgWrapper.setAoStateNameText(""); rgWrapper.setAoActivityCodeText(""); rgWrapper.setAoTypeNameText(""); rgWrapper.setStartTimeDisplay(""); rgWrapper.setEndTimeDisplay(""); rgWrapper.setDaysDisplayName(""); rgWrapper.setScheduledState(""); rgWrapper.setRoomName(""); rgWrapper.setBuildingName(""); rgWrapper.setBuildingCode(""); rgWrapper.setAoInstructorText(""); return rgWrapper; } /** * After the performance improvements, the clusterMap does not contain set information. So, lets add it here. * This method will use the dto to grab a full AOC. * * @param coId Course Offering Id * @param clusterMap map of AoIds to AO cluster wrappers * @throws InvalidParameterException * @throws MissingParameterException * @throws DoesNotExistException * @throws PermissionDeniedException * @throws OperationFailedException */ protected void processAosData(String coId, Map<String, ActivityOfferingClusterWrapper> clusterMap) throws InvalidParameterException, MissingParameterException, DoesNotExistException, PermissionDeniedException, OperationFailedException { List<ActivityOfferingClusterInfo> aoClusters = CourseOfferingManagementUtil.getCourseOfferingServiceFacade() .getActivityOfferingClusterByCourseOffering(coId); //A fix for KSENROLL-8097: clusterMap was populated in processAoClusterData method. //However if one cluster does not have an AO, that cluster sometimes won't be added to clusterMap, which causes NPE error later. //The walkaround solution here is to add the missing cluster to clusterMap for (ActivityOfferingClusterInfo aoc : aoClusters) { if (clusterMap.get(aoc.getId()) != null) { clusterMap.get(aoc.getId()).setAoCluster(aoc); } else { ActivityOfferingClusterWrapper aoClusterWrapper = new ActivityOfferingClusterWrapper(); aoClusterWrapper.setAoCluster(aoc); aoClusterWrapper.setActivityOfferingClusterId(aoc.getId()); aoClusterWrapper.setClusterNameForDisplay(aoc.getName()); String formatName = CourseOfferingManagementUtil.getCourseOfferingService() .getFormatOffering(aoc.getFormatOfferingId(), ContextUtils.createDefaultContextInfo()) .getName(); aoClusterWrapper.setFormatNameForDisplay(formatName); aoClusterWrapper.setFormatOfferingId(aoc.getFormatOfferingId()); clusterMap.put(aoc.getId(), aoClusterWrapper); } } } private List<ActivityOfferingWrapper> processAoClusterData(SearchResultInfo searchResults, Map<String, List<ActivityOfferingWrapper>> sch2aoMap, Map<String, ActivityOfferingClusterWrapper> clusterMap, Map<String, ActivityOfferingWrapper> aoMap, Map<String, FormatOfferingInfo> foIds, List<String> aoIdsWithoutSch, ContextInfo contextInfo) throws InvalidParameterException, MissingParameterException, DoesNotExistException, PermissionDeniedException, OperationFailedException { List<ActivityOfferingWrapper> activityOfferingWrappers = new ArrayList<ActivityOfferingWrapper>(); ActivityOfferingWrapper aoWrapperStored = new ActivityOfferingWrapper(); //storage for sub-term only to compare for (SearchResultRowInfo row : searchResults.getRows()) { ActivityOfferingWrapper aoWrapper = new ActivityOfferingWrapper(); String aocPrivateName = null; String foId = null; String formatId = null; String foName = null; List<String> scheduleIds = new ArrayList<String>(); for (SearchResultCellInfo cell : row.getCells()) { if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_ID.equals(cell.getKey())) { aoWrapper.getAoInfo().setId(cell.getValue()); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_CODE.equals(cell.getKey())) { aoWrapper.setActivityCode(cell.getValue()); aoWrapper.getAoInfo().setActivityCode(cell.getValue()); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_MAX_SEATS .equals(cell.getKey())) { aoWrapper.getAoInfo().setMaximumEnrollment( cell.getValue() == null ? null : Integer.parseInt(cell.getValue())); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_STATE.equals(cell.getKey())) { aoWrapper.getAoInfo().setStateKey(cell.getValue()); if (cell.getValue() != null) { StateInfo stateInfo = getStateService().getState(cell.getValue(), contextInfo); aoWrapper.setStateName(stateInfo.getName()); } } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_TYPE.equals(cell.getKey())) { aoWrapper.getAoInfo().setTypeKey(cell.getValue()); if (cell.getValue() != null) { TypeInfo typeInfo = getTypeService().getType(cell.getValue(), contextInfo); aoWrapper.setTypeKey(cell.getValue()); aoWrapper.setTypeName(typeInfo.getName()); } } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.SCHEDULE_ID .equals(cell.getKey())) { if (cell.getValue() != null) { scheduleIds.add(cell.getValue()); } } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.FO_ID.equals(cell.getKey())) { aoWrapper.getAoInfo().setFormatOfferingId(cell.getValue()); foId = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.FO_NAME.equals(cell.getKey())) { aoWrapper.setFormatOfferingName(cell.getValue()); aoWrapper.getAoInfo().setFormatOfferingName(cell.getValue()); foName = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.FORMAT_ID.equals(cell.getKey())) { formatId = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AOC_ID.equals(cell.getKey())) { aoWrapper.setAoClusterID(cell.getValue()); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AOC_NAME.equals(cell.getKey())) { aoWrapper.setAoClusterName(cell.getValue()); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AOC_PRIVATE_NAME .equals(cell.getKey())) { aocPrivateName = cell.getValue(); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.ATP_ID.equals(cell.getKey())) { aoWrapper.getAoInfo().setTermId(cell.getValue()); } else if (ActivityOfferingSearchServiceImpl.SearchResultColumns.AO_ISHONORS .equals(cell.getKey())) { aoWrapper.getAoInfo().setIsHonorsOffering(Boolean.valueOf(cell.getValue())); } } aoWrapper.getAoInfo().setScheduleIds(scheduleIds); for (String scheduleId : scheduleIds) { List<ActivityOfferingWrapper> list = sch2aoMap.get(scheduleId); if (list == null) { list = new ArrayList<ActivityOfferingWrapper>(); sch2aoMap.put(scheduleId, list); } list.add(aoWrapper);//Add to schedule map } if (aoWrapper.getAoClusterID() != null) { ActivityOfferingClusterWrapper aoClusterWrapper = clusterMap.get(aoWrapper.getAoClusterID()); if (aoClusterWrapper == null) { aoClusterWrapper = new ActivityOfferingClusterWrapper(); ActivityOfferingClusterInfo activityOfferingClusterInfo = new ActivityOfferingClusterInfo(); activityOfferingClusterInfo.setFormatOfferingId(aoWrapper.getAoInfo().getFormatOfferingId()); activityOfferingClusterInfo.setId(aoWrapper.getAoClusterID()); activityOfferingClusterInfo.setName(aoWrapper.getAoClusterName()); activityOfferingClusterInfo.setPrivateName(aocPrivateName); activityOfferingClusterInfo.setTypeKey(CourseOfferingServiceConstants.AOC_ROOT_TYPE_KEY); activityOfferingClusterInfo.setStateKey(CourseOfferingServiceConstants.AOC_ACTIVE_STATE_KEY); aoClusterWrapper.setAoCluster(activityOfferingClusterInfo); aoClusterWrapper.setActivityOfferingClusterId(aoWrapper.getAoClusterID()); aoClusterWrapper.setClusterNameForDisplay(aoWrapper.getAoClusterName()); aoClusterWrapper.setFormatNameForDisplay(aoWrapper.getAoInfo().getFormatOfferingName()); aoClusterWrapper.setFormatOfferingId(aoWrapper.getAoInfo().getFormatOfferingId()); clusterMap.put(aoWrapper.getAoClusterID(), aoClusterWrapper); } if (aoWrapper.getId() != null) { aoClusterWrapper.getAoWrapperList().add(aoWrapper); aoMap.put(aoWrapper.getAoInfo().getId(), aoWrapper); // Check if there is a schedule id, if not add it to the list to get RDLs // Note that since AOs can have multiple Scheduling Information and it is possible to have a scheduleId // in the collection while at the same time having an unprocessed request. However, the POs currently // only want to see requests if there are no schedules. if (aoWrapper.getAoInfo().getScheduleIds() == null || aoWrapper.getAoInfo().getScheduleIds().isEmpty()) { aoIdsWithoutSch.add(aoWrapper.getAoInfo().getId()); } //Check for sub-term or term and populate accordingly //If no change of AO.getTermId() > avoid service calls and populate sub-term info as it has been stored in aoWrapperStored if (aoWrapper.getAoInfo().getTermId().equals(aoWrapperStored.getAoInfo().getTermId())) { aoWrapper.setHasSubTerms(aoWrapperStored.getHasSubTerms()); aoWrapper.setSubTermId(aoWrapperStored.getSubTermId()); aoWrapper.setSubTermName(aoWrapperStored.getSubTermName()); aoWrapper.setTerm(aoWrapperStored.getTerm()); aoWrapper.setTermName(aoWrapperStored.getTermName()); aoWrapper.setTermDisplayString(aoWrapperStored.getTermDisplayString()); aoWrapper.setTermStartEndDate(aoWrapperStored.getTermStartEndDate()); } else { TermInfo term; TermInfo subTerm; aoWrapper.setHasSubTerms(false); aoWrapper.setSubTermName("None"); aoWrapper.setSubTermId(""); List<TermInfo> terms = CourseOfferingManagementUtil.getAcademicCalendarService() .getContainingTerms(aoWrapper.getAoInfo().getTermId(), contextInfo); if (terms == null || terms.isEmpty()) { term = CourseOfferingManagementUtil.getAcademicCalendarService() .getTerm(aoWrapper.getAoInfo().getTermId(), contextInfo); // checking if we can have sub-terms for giving term List<TermInfo> subTerms = CourseOfferingManagementUtil.getAcademicCalendarService() .getIncludedTermsInTerm(aoWrapper.getAoInfo().getTermId(), contextInfo); if (!subTerms.isEmpty()) { aoWrapper.setHasSubTerms(true); } } else { subTerm = CourseOfferingManagementUtil.getAcademicCalendarService() .getTerm(aoWrapper.getAoInfo().getTermId(), contextInfo); term = terms.get(0); aoWrapper.setHasSubTerms(true); aoWrapper.setSubTermId(subTerm.getId()); TypeInfo subTermType = getTypeService().getType(subTerm.getTypeKey(), contextInfo); aoWrapper.setSubTermName(subTermType.getName()); aoWrapper.setTermStartEndDate( CourseOfferingManagementUtil.getTermStartEndDate(subTerm.getId(), subTerm)); } aoWrapper.setTerm(term); if (term != null) { aoWrapper.setTermName(term.getName()); } aoWrapper.setTermDisplayString(CourseOfferingManagementUtil .getTermDisplayString(aoWrapper.getAoInfo().getTermId(), term)); aoWrapperStored = aoWrapper; //update for next comparison } // end sub-terms //retrieve comment count for each AO //TODO: performance can be further optimized by using a sub-select or join query to retrieve comment count for all the AOs instead of placing the count retrieval inside this loop. https://jira.kuali.org/browse/KSENROLL-13744 aoWrapper.setCommentCount(CommentUtil.getCommentsCount(aoWrapper.getAoInfo().getId(), CourseOfferingServiceConstants.REF_OBJECT_URI_ACTIVITY_OFFERING, contextInfo)); activityOfferingWrappers.add(aoWrapper); } } FormatOfferingInfo fo = foIds.get(foId); if (fo == null) { fo = new FormatOfferingInfo(); fo.setId(foId); fo.setName(foName); fo.setFormatId(formatId); foIds.put(foId, fo); } } return activityOfferingWrappers; } protected EntityDefaultQueryResults getInstructorsInfoFromKim(List<String> entityIds) { QueryByCriteria.Builder qbcBuilder = QueryByCriteria.Builder.create(); qbcBuilder.setPredicates(PredicateFactory.in("id", entityIds.toArray())); QueryByCriteria criteria = qbcBuilder.build(); EntityDefaultQueryResults entityResults = CourseOfferingManagementUtil.getIdentityService() .findEntityDefaults(criteria); return entityResults; } /** * This method will indicate to the user if the cluster canot be generated because the AO Set does not contain * enough activities that meet the requirements of the FormatOffering * * @param aoTypeKeys list of AO Type Keys * @param aoList List Of Activity Offerings * @param aoClusterWrapper AO Cluster * @param clusterIndex Used to tack the warning message onto a particular part of the screen * @param contextInfo context of the call * @throws Exception */ protected void _performAOCompletePerClusterValidation(List<String> aoTypeKeys, List<ActivityOfferingInfo> aoList, ActivityOfferingClusterWrapper aoClusterWrapper, int clusterIndex, ContextInfo contextInfo) throws Exception { Map<String, Boolean> completeAoSet = new HashMap<String, Boolean>(); // using a map to store what's required for (String aoType : aoTypeKeys) { completeAoSet.put(aoType, false); } for (ActivityOfferingInfo aoInfo : aoList) { completeAoSet.put(aoInfo.getTypeKey(), true); // This is used to determine if the AO Set has all FO types } StringBuilder aoCompleteWarningMessageSB = new StringBuilder(); String delim = ""; for (Map.Entry<String, Boolean> completeAoEntry : completeAoSet.entrySet()) { if (!completeAoEntry.getValue()) { // type service should be cached so this shouldn't be slow aoCompleteWarningMessageSB .append(delim + getTypeService().getType(completeAoEntry.getKey(), contextInfo).getName()); delim = ", "; } } // not to show warning message for deleted cluster. if (!(aoCompleteWarningMessageSB.length() == 0) && !(aoClusterWrapper.getAoCluster().getActivityOfferingSets().isEmpty())) { aoClusterWrapper.setRgStatus(RegistrationGroupConstants.RGSTATUS_NO_RG_GENERATED); aoClusterWrapper.setRgMessageStyle(ActivityOfferingClusterWrapper.RG_MESSAGE_ALL); aoClusterWrapper.setHasAllRegGroups(true); String clusterName = aoClusterWrapper.getClusterNameForDisplay(); String formatName = aoClusterWrapper.getFormatNameForDisplay(); GlobalVariables.getMessageMap().putWarningForSectionId( "activityOfferingsPerCluster_line" + clusterIndex, CourseOfferingConstants.REGISTRATIONGROUP_INCOMPLETE_AOSET, clusterName, formatName, aoCompleteWarningMessageSB.toString()); } } /* * Perform several validations: * 1. check if All RGs have been generated given AOs in a cluster * if not, set rgStatus="Only Some Registration Groups Generated" and * set hasAllRegGroups=false, therefore "Generate Registration Group" action link will show up * if yes, set rgStatus="All Registration Groups Generated" and * set hasAllRegGroups=true, therefore "View Registration Group" action link will show up * 2. when #1 validation result is yes, need to perform max enrollment validation. * 3. when #1 validation result is yes, need to perform time conflict validation * */ private void _validateRegistrationGroupsPerCluster(List<RegistrationGroupInfo> rgInfos, List<ActivityOfferingInfo> aoList, ActivityOfferingClusterWrapper aoClusterWrapper, ActivityOfferingDisplayUI theForm, int clusterIndex, Map<String, List<ScheduleCalcContainer>> ao2sch, Map<String, List<ScheduleRequestCalcContainer>> ao2schReq, Map<String, ActivityOfferingWrapper> aoMap) throws Exception { Map<String, List<String>> activityOfferingTypeToAvailableActivityOfferingMap = _constructActivityOfferingTypeToAvailableActivityOfferingMap( aoList); List<List<String>> generatedPermutations = new ArrayList<List<String>>(); List<List<String>> foundList = new ArrayList<List<String>>(); PermutationUtils.generatePermutations( new ArrayList<String>(activityOfferingTypeToAvailableActivityOfferingMap.keySet()), new ArrayList<String>(), activityOfferingTypeToAvailableActivityOfferingMap, generatedPermutations); List<RegistrationGroupInfo> rgInfosCopy = new ArrayList<RegistrationGroupInfo>(rgInfos.size()); for (RegistrationGroupInfo rgInfo : rgInfos) { rgInfosCopy.add(rgInfo); } for (List<String> activityOfferingPermutation : generatedPermutations) { for (RegistrationGroupInfo rgInfo : rgInfosCopy) { if (_hasGeneratedRegGroup(activityOfferingPermutation, rgInfo)) { rgInfosCopy.remove(rgInfo); foundList.add(activityOfferingPermutation); break; } } } if (generatedPermutations.size() != foundList.size()) { aoClusterWrapper.setRgStatus(RegistrationGroupConstants.RGSTATUS_SOME_RG_GENERATED); aoClusterWrapper.setRgMessageStyle(ActivityOfferingClusterWrapper.RG_MESSAGE_PARTIAL); aoClusterWrapper.setHasAllRegGroups(false); } else { aoClusterWrapper.setRgStatus(RegistrationGroupConstants.RGSTATUS_ALL_RG_GENERATED); aoClusterWrapper.setRgMessageStyle(ActivityOfferingClusterWrapper.RG_MESSAGE_ALL); aoClusterWrapper.setHasAllRegGroups(true); // perform max enrollment validation _performMaxEnrollmentValidation(aoMap, aoClusterWrapper, clusterIndex); //validate AO time conflict in RG _performRGTimeConflictValidation(aoClusterWrapper.getAoCluster(), rgInfos, clusterIndex, ao2sch, ao2schReq); } _performAOCompletePerClusterValidation( theForm.getFoId2aoTypeMap().get(aoClusterWrapper.getFormatOfferingId()) .getActivityOfferingTypeKeys(), aoList, aoClusterWrapper, clusterIndex, ContextUtils.createDefaultContextInfo()); if (!rgInfosCopy.isEmpty()) { GlobalVariables.getMessageMap().putWarningForSectionId("registrationGroupsPerFormatSection", CourseOfferingConstants.REGISTRATIONGROUP_INVALID_REGGROUPS); } } private Map<String, List<String>> _constructActivityOfferingTypeToAvailableActivityOfferingMap( List<ActivityOfferingInfo> aoList) { Map<String, List<String>> activityOfferingTypeToAvailableActivityOfferingMap = new HashMap<String, List<String>>(); for (ActivityOfferingInfo info : aoList) { String activityType = info.getTypeKey(); List<String> activityList = activityOfferingTypeToAvailableActivityOfferingMap.get(activityType); if (activityList == null) { activityList = new ArrayList<String>(); activityOfferingTypeToAvailableActivityOfferingMap.put(activityType, activityList); } activityList.add(info.getId()); } return activityOfferingTypeToAvailableActivityOfferingMap; } private boolean _hasGeneratedRegGroup(List<String> activityOfferingPermutation, RegistrationGroupInfo rgInfo) { boolean isMatched = true; List<String> aoIds = rgInfo.getActivityOfferingIds(); List<String> aoIdsCopy = new ArrayList<String>(aoIds.size()); for (String aoId : aoIds) { aoIdsCopy.add(aoId); } List<String> foundList = new ArrayList<String>(); for (String activityOfferingPermutationItem : activityOfferingPermutation) { for (String aoId : aoIdsCopy) { if (activityOfferingPermutationItem.equals(aoId)) { aoIdsCopy.remove(aoId); foundList.add(activityOfferingPermutationItem); break; } } } if (activityOfferingPermutation.size() != foundList.size() || !aoIdsCopy.isEmpty()) { isMatched = false; } return isMatched; } /** * Checks if all the AOs in a cluster add up to the same max enrollment (e.g. that there are not more seats in labs then lectures) * * @param aoMap map of aoIds to ao wrappers * @param aoClusterWrapper AO cluster wrapper * @param clusterIndex index of the cluster * @throws InvalidParameterException * @throws MissingParameterException * @throws DoesNotExistException * @throws PermissionDeniedException * @throws OperationFailedException */ private void _performMaxEnrollmentValidation(Map<String, ActivityOfferingWrapper> aoMap, ActivityOfferingClusterWrapper aoClusterWrapper, int clusterIndex) throws InvalidParameterException, MissingParameterException, DoesNotExistException, PermissionDeniedException, OperationFailedException { int previousMaxEnrollments = -1; String previousAOSetTypeKey = ""; for (ActivityOfferingSetInfo aos : aoClusterWrapper.getAoCluster().getActivityOfferingSets()) { int aoSetMaxEnrollNumber = 0; //Sum the enrollment for each AO in a given set for (String aoId : aos.getActivityOfferingIds()) { ActivityOfferingWrapper aoWrapper = aoMap.get(aoId); ActivityOfferingInfo aoInfo; if ((aoWrapper != null) && ((aoInfo = aoWrapper.getAoInfo()) != null) && aoInfo.getMaximumEnrollment() != null && !(aoInfo.getStateKey().equals(LuiServiceConstants.LUI_AO_STATE_CANCELED_KEY))) { aoSetMaxEnrollNumber += aoInfo.getMaximumEnrollment(); } } //If this is not the first cluster looked at and the max enrollment differs then set a warning if (previousMaxEnrollments >= 0 && previousMaxEnrollments != aoSetMaxEnrollNumber) { String biggerAOTypeName, smallerAOTypeName; if (previousMaxEnrollments > aoSetMaxEnrollNumber) { biggerAOTypeName = CourseOfferingManagementUtil.getTypeService() .getType(previousAOSetTypeKey, ContextUtils.createDefaultContextInfo()).getName(); smallerAOTypeName = CourseOfferingManagementUtil.getTypeService() .getType(aos.getActivityOfferingType(), ContextUtils.createDefaultContextInfo()) .getName(); } else { biggerAOTypeName = CourseOfferingManagementUtil.getTypeService() .getType(aos.getActivityOfferingType(), ContextUtils.createDefaultContextInfo()) .getName(); smallerAOTypeName = CourseOfferingManagementUtil.getTypeService() .getType(previousAOSetTypeKey, ContextUtils.createDefaultContextInfo()).getName(); } GlobalVariables.getMessageMap().putWarningForSectionId( "activityOfferingsPerCluster_line" + clusterIndex, RegistrationGroupConstants.MSG_WARNING_MAX_ENROLLMENT, aoClusterWrapper.getClusterNameForDisplay(), biggerAOTypeName, smallerAOTypeName); break; } previousAOSetTypeKey = aos.getActivityOfferingType(); previousMaxEnrollments = aoSetMaxEnrollNumber; } } private List<Integer> _performRGTimeConflictValidation(ActivityOfferingClusterInfo aoCluster, List<RegistrationGroupInfo> registrationGroupInfos, int clusterIndex, Map<String, List<ScheduleCalcContainer>> ao2sch, Map<String, List<ScheduleRequestCalcContainer>> ao2schReq) throws Exception { List<Integer> rgIndexList = new ArrayList<Integer>(); rgIndexList.clear(); if (aoCluster != null && registrationGroupInfos != null && !registrationGroupInfos.isEmpty()) { int rgIndex = 0; for (RegistrationGroupInfo registrationGroupInfo : registrationGroupInfos) { List<ValidationResultInfo> validationResultInfoList = new ArrayList<ValidationResultInfo>(); // Lets build a list of all schedules that need to be compared for this registration group. List<TimeSlotInfo> shed2Check = new ArrayList<TimeSlotInfo>(); for (String aoId : registrationGroupInfo.getActivityOfferingIds()) { if (ao2sch.get(aoId) != null) { for (ScheduleCalcContainer sched : ao2sch.get(aoId)) { shed2Check.add(toTimeSlotInfo(sched)); } } if (ao2schReq.get(aoId) != null) { for (ScheduleRequestCalcContainer sched : ao2schReq.get(aoId)) { shed2Check.addAll(sched.getTimeSlots()); } } } for (TimeSlotInfo outerEntry : shed2Check) { for (TimeSlotInfo innerEntry : shed2Check) { if (outerEntry.equals(innerEntry)) { break; } if (SchedulingServiceUtil.areTimeSlotsInConflict(outerEntry, innerEntry)) { ValidationResultInfo validationResultInfo = new ValidationResultInfo(); validationResultInfo.setLevel(ValidationResult.ErrorLevel.WARN); validationResultInfo.setMessage("time conflict between AO: " + outerEntry.getId() + " and AO: " + innerEntry.getId()); validationResultInfoList.add(validationResultInfo); } } } if (!validationResultInfoList.isEmpty() && validationResultInfoList.get(0).isWarn()) { rgIndexList.add(rgIndex); } rgIndex++; } if (!rgIndexList.isEmpty()) { GlobalVariables.getMessageMap().putWarningForSectionId( "activityOfferingsPerCluster_line" + clusterIndex, RegistrationGroupConstants.MSG_WARNING_AO_TIMECONFLICT, aoCluster.getPrivateName()); } } return rgIndexList; } public TimeSlotInfo toTimeSlotInfo(ScheduleCalcContainer sched) { TimeSlotInfo info = new TimeSlotInfo(); info.setId(null); info.setTypeKey(null); info.setStateKey(null); info.setName(null); info.setWeekdays(SchedulingServiceUtil.weekdaysString2WeekdaysList(sched.getWeekdays())); info.setStartTime(TimeOfDayHelper.setMillis( ((sched.getStart() != null && !"".equals(sched.getStart())) ? Long.valueOf(sched.getStart()) : null))); info.setEndTime(TimeOfDayHelper.setMillis( ((sched.getEnd() != null && !"".equals(sched.getEnd())) ? Long.valueOf(sched.getEnd()) : null))); info.setDescr(new RichTextInfo()); info.getDescr().setFormatted(null); info.getDescr().setPlain(null); info.setMeta(null); return info; } /** * This method fetches all the course offerings for a term and course/subject code. * * @param searchRequest search request * @param form input form * @throws Exception * @see CourseOfferingManagementSearchImpl Actual CO search happens here */ protected void loadCourseOfferings(SearchRequestInfo searchRequest, CourseOfferingDisplayUI form) throws Exception { ContextInfo contextInfo = createContextInfo(); SearchResultInfo searchResult = CourseOfferingManagementUtil.getSearchService().search(searchRequest, contextInfo); if (form instanceof ScheduleOfClassesSearchForm) { ((ScheduleOfClassesSearchForm) form).getCoDisplayWrapperList().clear(); } else { ((CourseOfferingManagementForm) form).getCourseOfferingResultList().clear(); } for (SearchResultRowInfo row : searchResult.getRows()) { CourseOfferingListSectionWrapper coListWrapper = new CourseOfferingListSectionWrapper(); if (form instanceof ScheduleOfClassesSearchForm) { coListWrapper = new CourseOfferingDisplayWrapper(); ((ScheduleOfClassesSearchForm) form).getCoDisplayWrapperList() .add((CourseOfferingDisplayWrapper) coListWrapper); } else { ((CourseOfferingManagementForm) form).getCourseOfferingResultList().add(coListWrapper); } for (SearchResultCellInfo cellInfo : row.getCells()) { String value = StringUtils.EMPTY; if (cellInfo.getValue() != null) { value = cellInfo.getValue(); } if (CourseOfferingManagementSearchImpl.SearchResultColumns.CODE.equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingCode(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.DESC.equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingDesc(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.STATE.equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingStateKey(value); coListWrapper.setCourseOfferingStateDisplay(getStateInfo(value).getName()); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.CREDIT_OPTION .equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingCreditOptionKey(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.GRADING_OPTION .equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingGradingOptionKey(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.GRADING_OPTION_NAME .equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingGradingOptionDisplay(cellInfo.getValue()); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.CREDIT_OPTION_NAME .equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingCreditOptionDisplay(cellInfo.getValue()); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.DEPLOYMENT_ORG_ID .equals(cellInfo.getKey())) { coListWrapper.setAdminOrg(cellInfo.getValue()); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.CO_ID.equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingId(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.SUBJECT_AREA .equals(cellInfo.getKey())) { coListWrapper.setSubjectArea(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.IS_CROSS_LISTED .equals(cellInfo.getKey())) { coListWrapper.setCrossListed(BooleanUtils.toBoolean(value)); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.CROSS_LISTED_COURSES .equals(cellInfo.getKey())) { coListWrapper.setAlternateCOCodes(Arrays.asList(StringUtils.split(value, ","))); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.OWNER_CODE .equals(cellInfo.getKey())) { coListWrapper.setOwnerCode(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.OWNER_ALIASES .equals(cellInfo.getKey())) { coListWrapper.setOwnerAliases(Arrays.asList(StringUtils.split(value, ","))); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.DESC_FORMATTED .equals(cellInfo.getKey())) { coListWrapper.setCourseOfferingFormatedDesc(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.HAS_STUDENT_SELECTABLE_PASSFAIL .equals(cellInfo.getKey())) { coListWrapper.setStudentSelectablePassFail(BooleanUtils.toBoolean(value)); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.CAN_AUDIT_COURSE .equals(cellInfo.getKey())) { coListWrapper.setAuditCourse(BooleanUtils.toBoolean(value)); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.IS_HONORS_COURSE .equals(cellInfo.getKey())) { coListWrapper.setHonorsCourse(BooleanUtils.toBoolean(value)); } } } } /** * This method loads the previous and next course offerings for navigation purpose. * * @param form input form */ public void loadPreviousAndNextCourseOffering(CourseOfferingManagementForm form) { try { ContextInfo contextInfo = createContextInfo(); /** * Get all the course offerings for a term and subject area. */ SearchRequestInfo searchRequest = new SearchRequestInfo( CourseOfferingManagementSearchImpl.CO_MANAGEMENT_SEARCH.getKey()); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.SUBJECT_AREA, form.getSubjectCode()); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.ATP_ID, form.getTermInfo().getId()); searchRequest.addParam(CourseOfferingManagementSearchImpl.SearchParameters.CROSS_LIST_SEARCH_ENABLED, BooleanUtils.toStringTrueFalse(true)); SearchResultInfo searchResult = CourseOfferingManagementUtil.getSearchService().search(searchRequest, contextInfo); List<CourseOfferingWrapper> availableCOs = new ArrayList<CourseOfferingWrapper>(); for (SearchResultRowInfo row : searchResult.getRows()) { String courseOfferingCode = ""; String courseOfferingId = ""; String courseOfferingDesc = ""; boolean isCrossListed = false; List<String> alternateCodes = null; String ownerCode = ""; for (SearchResultCellInfo cellInfo : row.getCells()) { String value = StringUtils.EMPTY; if (cellInfo.getValue() != null) { value = cellInfo.getValue(); } if (CourseOfferingManagementSearchImpl.SearchResultColumns.CODE.equals(cellInfo.getKey())) { courseOfferingCode = value; } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.CO_ID .equals(cellInfo.getKey())) { courseOfferingId = value; } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.DESC .equals(cellInfo.getKey())) { courseOfferingDesc = value; } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.IS_CROSS_LISTED .equals(cellInfo.getKey())) { isCrossListed = BooleanUtils.toBoolean(value); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.CROSS_LISTED_COURSES .equals(cellInfo.getKey())) { alternateCodes = Arrays.asList(StringUtils.split(value, ",")); } else if (CourseOfferingManagementSearchImpl.SearchResultColumns.OWNER_CODE .equals(cellInfo.getKey())) { ownerCode = value; } } CourseOfferingWrapper coWrapper = new CourseOfferingWrapper(isCrossListed, courseOfferingCode, courseOfferingDesc, alternateCodes, courseOfferingId); coWrapper.setOwnerCode(ownerCode); availableCOs.add(coWrapper); } /** * Find the current course offering index and set the previous and next course offerings if exists. */ for (CourseOfferingWrapper coWrapper : availableCOs) { if (StringUtils.equals(coWrapper.getCourseOfferingCode(), form.getCurrentCourseOfferingWrapper().getCourseOfferingCode())) { int currentIndex = availableCOs.indexOf(coWrapper); form.setInputCode(coWrapper.getCourseOfferingCode()); if (currentIndex > 0) { form.setPreviousCourseOfferingWrapper(availableCOs.get(currentIndex - 1)); } else { form.setPreviousCourseOfferingWrapper(null); } if (currentIndex < availableCOs.size() - 1) { form.setNextCourseOfferingWrapper(availableCOs.get(currentIndex + 1)); } else { form.setNextCourseOfferingWrapper(null); } break; } } } catch (Exception e) { throw new RuntimeException(e); } } /** * This method is a custom method to bulk create AO's via the UI. * <p/> * It has some code that will automatically create clusters if they don't exist plus extra validation on the * types. * <p/> * It eventually calls the business adapter class to create the AO. * * @param formatOfferingId * @param activityId * @param noOfActivityOfferings * @param form */ public void createActivityOfferings(String formatOfferingId, String activityId, int noOfActivityOfferings, CourseOfferingManagementForm form) { String termcode; FormatOfferingInfo formatOfferingInfo; TypeInfo activityOfferingType = null; CourseInfo course; String clusterId = form.getClusterIdForNewAO(); ContextInfo contextInfo = createContextInfo(); ActivityOfferingClusterInfo defaultCluster; //create default cluster if there is no cluster for the FO yet try { int clusterCount = CourseOfferingManagementUtil.getCourseOfferingServiceFacade() .getAoClusterCountByFoId(formatOfferingId, contextInfo); if (clusterCount == 0) { defaultCluster = CourseOfferingManagementUtil.getCourseOfferingServiceFacade() .createDefaultCluster(formatOfferingId, contextInfo); if (defaultCluster != null) { clusterId = defaultCluster.getId(); } } } catch (Exception e) { throw new RuntimeException(e); } //the AO clusters associated with the given FO CourseOfferingInfo courseOffering = form.getCurrentCourseOfferingWrapper().getCourseOfferingInfo(); // find the Activity object that matches the activity id selected ActivityInfo activity = null; // Get the format object for the id selected try { formatOfferingInfo = CourseOfferingManagementUtil.getCourseOfferingService() .getFormatOffering(formatOfferingId, contextInfo); course = CourseOfferingManagementUtil.getCourseService().getCourse(courseOffering.getCourseId(), contextInfo); for (FormatInfo f : course.getFormats()) { if (f.getId().equals(formatOfferingInfo.getFormatId())) { for (ActivityInfo info : f.getActivities()) { if (StringUtils.equals(activityId, info.getId())) { activity = info; } } break; } } } catch (Exception e) { throw new RuntimeException(e); } // Get the matching activity offering type for the selected activity try { for (String aoTypeKey : formatOfferingInfo.getActivityOfferingTypeKeys()) { List<TypeTypeRelationInfo> typeTypeRelationInfos = getTypeService() .getTypeTypeRelationsByRelatedTypeAndType(aoTypeKey, TypeServiceConstants.TYPE_TYPE_RELATION_ALLOWED_TYPE_KEY, ContextUtils.getContextInfo()); if (typeTypeRelationInfos != null && typeTypeRelationInfos.size() > 0) { if (StringUtils.equals(activity.getTypeKey(), typeTypeRelationInfos.get(0).getOwnerTypeKey())) { activityOfferingType = getTypeService().getType(aoTypeKey, contextInfo); } } } } catch (Exception e) { throw new RuntimeException(e); } try { AtpInfo termAtp = CourseOfferingManagementUtil.getAtpService().getAtp(courseOffering.getTermId(), contextInfo); termcode = termAtp.getCode(); } catch (Exception e) { throw new RuntimeException(e); } //create and persist AO for (int i = 0; i < noOfActivityOfferings; i++) { ActivityOfferingInfo aoInfo = new ActivityOfferingInfo(); aoInfo.setActivityId(activityId); aoInfo.setFormatOfferingId(formatOfferingId); aoInfo.setTypeKey(activityOfferingType.getKey()); aoInfo.setCourseOfferingId(courseOffering.getId()); aoInfo.setStateKey(LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY); aoInfo.setTermId(courseOffering.getTermId()); aoInfo.setTermCode(termcode); aoInfo.setFormatOfferingName(formatOfferingInfo.getName()); aoInfo.setCourseOfferingTitle(courseOffering.getCourseOfferingTitle()); aoInfo.setCourseOfferingCode(courseOffering.getCourseOfferingCode()); try { ActivityOfferingInfo activityOfferingInfo; CourseWaitListInfo theWaitListInfo; // This is the "business" type call that will create the AO and link the appropiate objects. // This will also create + add any needed Waitlists ActivityOfferingResult aoResult = CourseOfferingManagementUtil.getCourseOfferingServiceFacade() .createActivityOffering(aoInfo, clusterId, contextInfo); activityOfferingInfo = aoResult.getCreatedActivityOffering(); theWaitListInfo = aoResult.getWaitListInfo(); ActivityOfferingWrapper wrapper = new ActivityOfferingWrapper(activityOfferingInfo); StateInfo state = getStateService().getState(wrapper.getAoInfo().getStateKey(), contextInfo); wrapper.setStateName(state.getName()); TypeInfo typeInfo = getTypeInfo(wrapper.getAoInfo().getTypeKey()); wrapper.setTypeName(typeInfo.getName()); wrapper.setCourseWaitListInfo(theWaitListInfo); form.getActivityWrapperList().add(wrapper); //generate final exam offerings if the exam period exists ExamOfferingContext examOfferingContext = ExamOfferingManagementUtil .createExamOfferingContext(courseOffering, activityOfferingInfo); ExamOfferingResult eoresult = ExamOfferingManagementUtil.getExamOfferingServiceFacade() .generateFinalExamOffering(examOfferingContext, new ArrayList<String>(), contextInfo); ExamOfferingManagementUtil.processExamOfferingResultSet(eoresult); } catch (Exception e) { throw new RuntimeException(e); } } CourseOfferingManagementToolbarUtil.processAoToolbarForUser(form.getActivityWrapperList(), form); if (noOfActivityOfferings == 1) { KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_ADD_1_SUCCESS); } else { KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_ADD_N_SUCCESS); } KSUifUtils.getMessengerFromUserSession().publishMessages(); } public void loadActivityOfferingsByCourseOffering(CourseOfferingInfo theCourseOfferingInfo, CourseOfferingManagementForm form) throws Exception { String courseOfferingId = theCourseOfferingInfo.getId(); List<ActivityOfferingInfo> activityOfferingInfoList; List<ActivityOfferingWrapper> activityOfferingWrapperList; try { activityOfferingInfoList = CourseOfferingManagementUtil.getCourseOfferingService() .getActivityOfferingsByCourseOffering(courseOfferingId, createContextInfo()); activityOfferingWrapperList = new ArrayList<ActivityOfferingWrapper>(activityOfferingInfoList.size()); for (ActivityOfferingInfo info : activityOfferingInfoList) { ActivityOfferingWrapper aoWrapper = convertAOInfoToWrapper(info); activityOfferingWrapperList.add(aoWrapper); } } catch (Exception e) { throw new RuntimeException( String.format("Could not load AOs for course offering [%s].", courseOfferingId), e); } form.setActivityWrapperList(activityOfferingWrapperList); } public List<ActivityOfferingWrapper> getActivityOfferingsByCourseOfferingId(String courseOfferingId, CourseOfferingManagementForm form) throws Exception { List<ActivityOfferingInfo> activityOfferingInfoList; List<ActivityOfferingWrapper> activityOfferingWrapperList; try { activityOfferingInfoList = CourseOfferingManagementUtil.getCourseOfferingService() .getActivityOfferingsByCourseOffering(courseOfferingId, createContextInfo()); activityOfferingWrapperList = new ArrayList<ActivityOfferingWrapper>(activityOfferingInfoList.size()); for (ActivityOfferingInfo info : activityOfferingInfoList) { ActivityOfferingWrapper aoWrapper = new ActivityOfferingWrapper(info); activityOfferingWrapperList.add(aoWrapper); } } catch (Exception e) { throw new RuntimeException( String.format("Could not load AOs for course offering [%s].", courseOfferingId), e); } return activityOfferingWrapperList; } public void approveCourseOfferings(CourseOfferingManagementForm form) throws Exception { List<CourseOfferingListSectionWrapper> coList = form.getCourseOfferingResultList(); ContextInfo contextInfo = createContextInfo(); int checked = 0; int enabled = 0; for (CourseOfferingListSectionWrapper co : coList) { if (co.getIsChecked()) { checked++; if (co.isEnableApproveButton()) { enabled++; List<ActivityOfferingWrapper> aos = getActivityOfferingsByCourseOfferingId( co.getCourseOfferingId(), form); if (aos != null && !aos.isEmpty()) { form.setAdminOrg(co.getAdminOrg()); CourseOfferingManagementToolbarUtil.processAoToolbarForUser(aos, form); for (ActivityOfferingWrapper ao : aos) { if (ao.isEnableApproveButton()) { CourseOfferingManagementUtil.getCourseOfferingService().changeActivityOfferingState( ao.getAoInfo().getId(), LuiServiceConstants.LUI_AO_STATE_APPROVED_KEY, contextInfo); } } } } } } if (checked > enabled) { KSUifUtils.addGrowlMessageIcon(GrowlIcon.WARNING, CourseOfferingConstants.COURSEOFFERING_TOOLBAR_APPROVED); } else { if (enabled == 1) { KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, CourseOfferingConstants.COURSEOFFERING_TOOLBAR_APPROVED_1_SUCCESS); } else { KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, CourseOfferingConstants.COURSEOFFERING_TOOLBAR_APPROVED_N_SUCCESS); } } } public void deleteCourseOfferings(CourseOfferingManagementForm form) throws Exception { List<CourseOfferingListSectionWrapper> coList = form.getCourseOfferingResultList(); int totalCosToDelete = 0; int totalColocatedCos = 0; int totalColocatedAos = 0; boolean iscolocated; int totalCrossListedCosToDelete = 0; int totalJointDefinedCosToDelete = 0; form.setNumOfColocatedCosToDelete(0); form.setNumOfColocatedAosToDelete(0); form.setNumOfCrossListedCosToDelete(0); form.setNumOfJointDefinedCosToDelete(0); List<CourseOfferingListSectionWrapper> qualifiedToDeleteList = form.getSelectedCoToDeleteList(); qualifiedToDeleteList.clear(); ContextInfo contextInfo = ContextUtils.createDefaultContextInfo(); int totalAos = 0; form.setCrossListedCO(false); form.setColocatedCO(false); for (CourseOfferingListSectionWrapper co : coList) { if (co.getIsChecked()) { totalCosToDelete++; iscolocated = false; List<ActivityOfferingDisplayInfo> aoDisplayInfoList = CourseOfferingManagementUtil .getCourseOfferingService() .getActivityOfferingDisplaysForCourseOffering(co.getCourseOfferingId(), contextInfo); List<ActivityOfferingInfo> aoInfoList = CourseOfferingManagementUtil.getCourseOfferingService() .getActivityOfferingsByCourseOffering(co.getCourseOfferingId(), contextInfo); co.setCoHasAoToDelete(false); co.setColocated(false); if (aoDisplayInfoList != null && !aoDisplayInfoList.isEmpty()) { co.setCoHasAoToDelete(true); for (ActivityOfferingDisplayInfo aoDisplayInfo : aoDisplayInfoList) { ActivityOfferingDisplayWrapper aoDisplayWrapper = new ActivityOfferingDisplayWrapper(); aoDisplayWrapper.setAoDisplayInfo(aoDisplayInfo); // term stuff List<TermInfo> terms = CourseOfferingManagementUtil.getAcademicCalendarService() .getContainingTerms(aoDisplayInfo.getTermId(), contextInfo); if (terms == null || terms.isEmpty()) { // has no sub-terms aoDisplayWrapper.setSubTermName("None"); aoDisplayWrapper.setTermStartEndDate(""); } else { // has sub-terms TermInfo subTerm = CourseOfferingManagementUtil.getAcademicCalendarService() .getTerm(aoDisplayInfo.getTermId(), contextInfo); TypeInfo subTermType = getTypeService().getType(subTerm.getTypeKey(), contextInfo); aoDisplayWrapper.setSubTermName(subTermType.getName()); aoDisplayWrapper.setTermStartEndDate( CourseOfferingManagementUtil.getTermStartEndDate(subTerm.getId(), subTerm)); } // Adding Information (icons) String information = ""; if (aoDisplayInfo.getIsHonorsOffering() != null && aoDisplayInfo.getIsHonorsOffering()) { information = "<img src=" + ScheduleOfClassesConstants.SOC_RESULT_PAGE_HONORS_COURSE_IMG + " title=\"" + ScheduleOfClassesConstants.SOC_RESULT_PAGE_HELP_HONORS_ACTIVITY + "\"> "; } aoDisplayWrapper.setInformation(information); if (aoDisplayInfo.getScheduleDisplay() != null && !aoDisplayInfo.getScheduleDisplay().getScheduleComponentDisplays().isEmpty()) { //TODO handle TBA state List<? extends ScheduleComponentDisplay> scheduleComponentDisplays = aoDisplayInfo .getScheduleDisplay().getScheduleComponentDisplays(); for (ScheduleComponentDisplay scheduleComponentDisplay : scheduleComponentDisplays) { if (scheduleComponentDisplay.getBuilding() != null) { aoDisplayWrapper.setBuildingName( scheduleComponentDisplay.getBuilding().getBuildingCode(), true); aoDisplayWrapper.setBuildingCode( scheduleComponentDisplay.getBuilding().getBuildingCode(), true); } if (scheduleComponentDisplay.getRoom() != null) { aoDisplayWrapper.setRoomName(scheduleComponentDisplay.getRoom().getRoomCode(), true); } if (!scheduleComponentDisplay.getTimeSlots().isEmpty()) { TimeSlot timeSlot = KSCollectionUtils .getRequiredZeroElement(scheduleComponentDisplay.getTimeSlots()); if (timeSlot.getStartTime() != null && (timeSlot.getStartTime().getHour() != null)) { aoDisplayWrapper.setStartTimeDisplay( timeOfDayToTime(timeSlot.getStartTime()), true); } if (timeSlot.getEndTime() != null && (timeSlot.getEndTime().getHour() != null)) { aoDisplayWrapper.setEndTimeDisplay(timeOfDayToTime(timeSlot.getEndTime()), true); } aoDisplayWrapper.setDaysDisplayName(getDays(timeSlot.getWeekdays()), true); } } } // if ao is colocated AO add colocated info if (isColocatedAo(aoDisplayInfo.getActivityOfferingCode(), aoInfoList)) { String colocateInfo = CourseOfferingViewHelperUtil.createColocatedDisplayData( getAoInfo(aoDisplayInfo.getActivityOfferingCode(), aoInfoList), contextInfo); aoDisplayWrapper.setColocatedAoInfo(colocateInfo); co.setColocated(true); co.setColocatedCoCode(colocateInfo); form.setColocatedCO(true); totalColocatedAos++; iscolocated = true; } co.getAoToBeDeletedList().add(aoDisplayWrapper); } totalAos = totalAos + co.getAoToBeDeletedList().size(); co.setCrossListed(false); if (co.getAlternateCOCodes() != null && co.getAlternateCOCodes().size() > 0) { co.setCrossListed(true); form.setCrossListedCO(true); totalCrossListedCosToDelete++; } } co.setJointDefined(false); if (iscolocated) { totalColocatedCos++; } else { // verify whether this CO is joint-defined or not String jointDefinedCodes = getJointDefinedInfo(co); if (!jointDefinedCodes.isEmpty()) { co.setJointDefinedCoCode(jointDefinedCodes); co.setJointDefined(true); totalJointDefinedCosToDelete++; } } qualifiedToDeleteList.add(co); } } form.setNumOfCrossListedCosToDelete(totalCrossListedCosToDelete); form.setNumOfJointDefinedCosToDelete(totalJointDefinedCosToDelete); if (totalColocatedCos == totalCosToDelete) { form.setColocatedCoOnly(true); form.setNumOfColocatedCosToDelete(totalColocatedCos); } if (totalJointDefinedCosToDelete >= 1) { form.setJointDefinedCo(true); } form.setNumOfColocatedAosToDelete(totalColocatedAos); form.setTotalAOsToBeDeleted(totalAos); } public void approveActivityOfferings(CourseOfferingManagementForm form) throws Exception { List<ActivityOfferingWrapper> aoList = form.getActivityWrapperList(); ContextInfo contextInfo = createContextInfo(); int checked = 0; int enabled = 0; for (ActivityOfferingWrapper ao : aoList) { if ((!"0".equals(form.getSelectedTabId())) && ao.getIsChecked() || ("0".equals(form.getSelectedTabId())) && ao.getIsCheckedByCluster()) { checked++; if (ao.isEnableApproveButton()) { enabled++; CourseOfferingManagementUtil.getCourseOfferingService().changeActivityOfferingState( ao.getAoInfo().getId(), LuiServiceConstants.LUI_AO_STATE_APPROVED_KEY, contextInfo); } } } if (checked > enabled) { KSUifUtils.addGrowlMessageIcon(GrowlIcon.WARNING, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_APPROVED); } else { if (enabled == 1) { KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_APPROVED_1_SUCCESS); } else { KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_APPROVED_N_SUCCESS); } } } public void draftActivityOfferings(CourseOfferingManagementForm form) throws Exception { List<ActivityOfferingWrapper> aoList = form.getActivityWrapperList(); ContextInfo contextInfo = createContextInfo(); int checked = 0; int enabled = 0; for (ActivityOfferingWrapper ao : aoList) { if ((!"0".equals(form.getSelectedTabId())) && ao.getIsChecked() || ("0".equals(form.getSelectedTabId())) && ao.getIsCheckedByCluster()) { checked++; if (ao.isEnableDraftButton()) { enabled++; CourseOfferingManagementUtil.getCourseOfferingService().changeActivityOfferingState( ao.getAoInfo().getId(), LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY, contextInfo); } } } if (checked > enabled) { KSUifUtils.addGrowlMessageIcon(GrowlIcon.WARNING, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_DRAFT); } else { if (enabled == 1) { KSUifUtils.addGrowlMessageIcon(GrowlIcon.INFORMATION, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_DRAFT_1_SUCCESS); } else { KSUifUtils.addGrowlMessageIcon(GrowlIcon.INFORMATION, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_DRAFT_N_SUCCESS); } } } /** * Notes by Bonnie: The following implementation tries to support "Approve for Scheduling" in two cases historically: * 1)when some COs are checked and approve for scheduling link or button is clicked * vs. * 2)when a user simply click "Approve Subject Code for Scheduling" link with/without selecting any CO * case 1) has been implemented by approveCourseOfferings method -- invoked by Approve button in toolbar * case 2) is the only use case when markCourseOfferingsForScheduling is invoked. Therefore the parameter * checkedOnly and related checking for each CO seem not needed anymore... * TODO: code cleanup?? * <p/> * Examines a List of CourseOffering wrappers and changes the state of each "checked" AO (meaning the * CO was selected on the UI) from "Draft" to "Approved". If the AO has a state other than "Draft" the AO is ignored. * Also, changes the state of the CourseOffering if appropriate. * * @param coWrappers, viewId, socStateKey provides list of CourseOfferings, viewId, socState. * @param checkedOnly True if the CO wrapper isChecked() flag should be respected. */ public void markCourseOfferingsForScheduling(List<CourseOfferingListSectionWrapper> coWrappers, String viewId, String socStateKey, boolean checkedOnly) throws Exception { boolean hasAOWarning = false, hasStateChangedAO = false, hasOrgWarning = false; ContextInfo contextInfo = createContextInfo(); for (CourseOfferingListSectionWrapper coWrapper : coWrappers) { if (coWrapper.getIsChecked() || !checkedOnly) { // Checking if the person is authorized to approve Map<String, String> permissionDetails = new HashMap<String, String>(); Map<String, String> roleQualifications = new HashMap<String, String>(); CourseOfferingInfo coInfo = CourseOfferingManagementUtil.getCourseOfferingService() .getCourseOffering(coWrapper.getCourseOfferingId(), contextInfo); List<String> orgIds = coInfo.getUnitsDeploymentOrgIds(); StringBuilder orgIDs = new StringBuilder(); if (orgIds != null && !orgIds.isEmpty()) { for (String orgId : orgIds) { orgIDs.append(orgId + ","); } } boolean canApproveAOs = true; if (orgIDs.length() > 0) { String principalId = GlobalVariables.getUserSession().getPerson().getPrincipalId(); roleQualifications.put("offeringAdminOrgId", orgIDs.substring(0, orgIDs.length() - 1)); permissionDetails.put(KimConstants.AttributeConstants.VIEW_ID, viewId); permissionDetails.put(KimConstants.AttributeConstants.ACTION_EVENT, "approveSubj"); String socState = socStateKey == null ? null : socStateKey.substring(socStateKey.lastIndexOf('.') + 1); permissionDetails.put("socState", socState); canApproveAOs = CourseOfferingManagementUtil.getPermissionService().isAuthorizedByTemplate( principalId, "KS-ENR", KimConstants.PermissionTemplateNames.PERFORM_ACTION, permissionDetails, roleQualifications); } if (!canApproveAOs) { // if can't approve AOs for all COs (because they are in a different org) if (!hasOrgWarning) hasOrgWarning = true; continue; } else { List<ActivityOfferingInfo> activityOfferingInfos = CourseOfferingManagementUtil .getCourseOfferingService() .getActivityOfferingsByCourseOffering(coWrapper.getCourseOfferingId(), contextInfo); if (activityOfferingInfos.size() == 0) { if (!hasAOWarning) hasAOWarning = true; continue; } // Iterate through the AOs and state change Draft -> Approved. for (ActivityOfferingInfo activityOfferingInfo : activityOfferingInfos) { boolean isAOStateDraft = StringUtils.equals(activityOfferingInfo.getStateKey(), LuiServiceConstants.LUI_AO_STATE_DRAFT_KEY); if (isAOStateDraft) { StatusInfo statusInfo = CourseOfferingManagementUtil.getCourseOfferingService() .changeActivityOfferingState(activityOfferingInfo.getId(), LuiServiceConstants.LUI_AO_STATE_APPROVED_KEY, contextInfo); if (!statusInfo.getIsSuccess()) { GlobalVariables.getMessageMap().putError("manageCourseOfferingsPage", CourseOfferingConstants.COURSE_OFFERING_STATE_CHANGE_ERROR, coWrapper.getCourseOfferingCode(), statusInfo.getMessage()); } // Flag if any AOs can be state changed. This affects the error message whi. if (statusInfo.getIsSuccess()) { hasStateChangedAO = true; } } else { // Flag if any AOs are not in a valid state for approval. if (!hasAOWarning) hasAOWarning = true; } } } } } // Set feedback messages. if (!hasStateChangedAO) { GlobalVariables.getMessageMap().putError("manageCourseOfferingsPage", CourseOfferingConstants.COURSEOFFERING_NONE_APPROVED); } else { if (hasAOWarning) { GlobalVariables.getMessageMap().putWarning("manageCourseOfferingsPage", CourseOfferingConstants.COURSEOFFERING_WITH_AO_DRAFT_APPROVED_ONLY); } if (hasOrgWarning) { GlobalVariables.getMessageMap().putWarning("manageCourseOfferingsPage", CourseOfferingConstants.COURSEOFFERING_WITH_AO_ORG_APPROVED_ONLY); } } } private void setSocStateKeys(CourseOfferingManagementForm form, SocInfo soc) throws Exception { if (soc != null) { form.setSocStateKey(soc.getStateKey()); form.setSocSchedulingStateKey(soc.getSchedulingStateKey()); //TODO: Set SOC State - temporary display, to be removed after testing is finished if (StringUtils.isNotBlank(soc.getStateKey())) { String socState = getStateService().getState(soc.getStateKey(), createContextInfo()).getName(); socState = (socState.substring(0, 1)).toUpperCase() + socState.substring(1, socState.length()); form.setSocState(socState); } return; } } private boolean isColocatedAo(String aoCode, List<ActivityOfferingInfo> aoList) { for (ActivityOfferingInfo ao : aoList) { if (StringUtils.equals(aoCode, ao.getActivityCode())) { if (ao.getIsColocated()) { return true; } } } return false; } private ActivityOfferingInfo getAoInfo(String aoCode, List<ActivityOfferingInfo> aoList) { for (ActivityOfferingInfo ao : aoList) { if (StringUtils.equals(aoCode, ao.getActivityCode())) { if (ao.getIsColocated()) { return ao; } } } return null; } private String getJointDefinedInfo(CourseOfferingListSectionWrapper co) { if (co == null) return null; List<CourseInfo> coInfoList = CourseOfferingViewHelperUtil .getMatchingCoursesFromClu(co.getCourseOfferingCode()); StringBuilder jointDefinedCodes = new StringBuilder(); for (CourseInfo coInfo : coInfoList) { List<CourseJointInfo> jointList = coInfo.getJoints(); if (!jointList.isEmpty() && jointList.size() >= 1) { for (CourseJointInfo jointInfo : jointList) { jointDefinedCodes.append(jointInfo.getSubjectArea()); jointDefinedCodes.append(jointInfo.getCourseNumberSuffix()); jointDefinedCodes.append(" "); } } } return jointDefinedCodes.toString(); } public void setupRuleIndicator(List<ActivityOfferingWrapper> wrappers) { //Get the list of ao ids. List<String> aoIds = new ArrayList<String>(); for (ActivityOfferingWrapper aoWrapper : wrappers) { if (aoWrapper.getAoInfo().getId() != null) { aoIds.add(aoWrapper.getAoInfo().getId()); } } //Retrieve all reference object bindings for list of ao ids. List<ReferenceObjectBinding> refs = CourseOfferingManagementUtil.getRuleManagementService() .findReferenceObjectBindingsByReferenceObjectIds( CourseOfferingServiceConstants.REF_OBJECT_URI_ACTIVITY_OFFERING, aoIds); for (ActivityOfferingWrapper aoWrapper : wrappers) { aoWrapper.setHasRule(false); for (ReferenceObjectBinding ref : refs) { if (ref.getReferenceObjectId().equals(aoWrapper.getAoInfo().getId())) { aoWrapper.setHasRule(true); break; } } } } public void loadExamOfferingRelations(CourseOfferingManagementForm theForm) throws Exception { List<ExamOfferingRelationInfo> eoRelations = CourseOfferingManagementUtil.getExamOfferingServiceFacade() .getExamOfferingRelationsByCourseOffering(theForm.getCourseOfferingId(), ContextUtils.createDefaultContextInfo()); theForm.setEoRelations(eoRelations); } public void loadExamOfferings(CourseOfferingManagementForm theForm) throws Exception { Set<String> examOfferingIds = new HashSet<String>(); Map<String, ExamOfferingRelationInfo> eoToRln = new HashMap<String, ExamOfferingRelationInfo>(); for (ExamOfferingRelationInfo examOfferingRelationInfo : theForm.getEoRelations()) { examOfferingIds.add(examOfferingRelationInfo.getExamOfferingId()); eoToRln.put(examOfferingRelationInfo.getExamOfferingId(), examOfferingRelationInfo); } //Retrieve a list of all the unique examofferings. List<ExamOfferingInfo> examOfferingInfos = CourseOfferingManagementUtil.getExamOfferingService() .getExamOfferingsByIds(new ArrayList<String>(examOfferingIds), ContextUtils.createDefaultContextInfo()); //set the EO matrix RSI Overidable flag for the current CO wrapper setExamOfferingMatrixRSIOveridability(theForm); //reset wrapper lists before adding back eoWrappers theForm.getExamOfferingWrapperList().clear(); if (theForm.getEoClusterResultList().size() > 0) { for (ExamOfferingClusterWrapper eoCluster : theForm.getEoClusterResultList()) { eoCluster.getEoWrapperList().clear(); } } theForm.getExamOfferingCancelledList().clear(); if (theForm.getEoCancelClusterList().size() > 0) { for (ExamOfferingClusterWrapper eoCancelCluster : theForm.getEoCancelClusterList()) { eoCancelCluster.getEoWrapperList().clear(); } } for (ExamOfferingInfo examOfferingInfo : examOfferingInfos) { ExamOfferingWrapper examOfferingWrapper = createWrapperFromExamOffering(examOfferingInfo, theForm); if (isDriverPerAO(examOfferingInfo)) { ExamOfferingRelationInfo eor = eoToRln.get(examOfferingInfo.getId()); examOfferingWrapper.setTypeName(this.getActivityDriver(examOfferingInfo)); setExamOfferingPerAO(theForm, examOfferingWrapper, eor); } else { if (ExamOfferingServiceConstants.EXAM_OFFERING_CANCELED_STATE_KEY .equals(examOfferingInfo.getStateKey())) { theForm.getExamOfferingCancelledList().add(examOfferingWrapper); } else { theForm.getExamOfferingWrapperList().add(examOfferingWrapper); } } } //Sort EO Clusters in sync with AO Clusters List<ExamOfferingClusterWrapper> clusterWrapperList = theForm.getEoClusterResultList(); if (clusterWrapperList.size() > 1) { Collections.sort(clusterWrapperList, new Comparator<ExamOfferingClusterWrapper>() { @Override public int compare(ExamOfferingClusterWrapper o1, ExamOfferingClusterWrapper o2) { int formatComparison = o1.getFormatNameForDisplay() .compareToIgnoreCase(o2.getFormatNameForDisplay()); int nameComparison = o1.getClusterNameForDisplay() .compareToIgnoreCase(o2.getClusterNameForDisplay()); if (formatComparison == 0) { return nameComparison; } else { return formatComparison; } } }); } } private boolean isDriverPerAO(ExamOfferingInfo eo) { for (AttributeInfo attribute : eo.getAttributes()) { if (attribute.getKey().equals(ExamOfferingServiceConstants.FINAL_EXAM_DRIVER_ATTR) && attribute.getValue().equals("PER_AO")) { return true; } } return false; } private String getActivityDriver(ExamOfferingInfo eo) throws PermissionDeniedException, MissingParameterException, InvalidParameterException, OperationFailedException, DoesNotExistException { for (AttributeInfo attribute : eo.getAttributes()) { if (attribute.getKey().equals(ExamOfferingServiceConstants.FINAL_EXAM_ACTIVITY_DRIVER_ATTR)) { TypeInfo type = CourseOfferingManagementUtil.getTypeService().getType(attribute.getValue(), ContextUtils.createDefaultContextInfo()); return type.getName(); } } return StringUtils.EMPTY; } private void setExamOfferingPerAO(CourseOfferingManagementForm theForm, ExamOfferingWrapper examOfferingWrapper, ExamOfferingRelationInfo eoRelation) throws PermissionDeniedException, MissingParameterException, InvalidParameterException, OperationFailedException, DoesNotExistException { for (ActivityOfferingClusterWrapper aoClusterWrapper : theForm.getClusterResultList()) { for (ActivityOfferingWrapper wrapper : aoClusterWrapper.getAoWrapperList()) { if (eoRelation.getActivityOfferingIds().contains(wrapper.getId())) { ExamOfferingClusterWrapper eoClusterWrapper = null; if (ExamOfferingServiceConstants.EXAM_OFFERING_CANCELED_STATE_KEY .equals(examOfferingWrapper.getEoInfo().getStateKey())) { eoClusterWrapper = getExamOfferingClusterWrapper(aoClusterWrapper, theForm.getEoCancelClusterList()); } else { eoClusterWrapper = getExamOfferingClusterWrapper(aoClusterWrapper, theForm.getEoClusterResultList()); } examOfferingWrapper.setAoInfo(wrapper.getAoInfo()); examOfferingWrapper.setActivityCode(wrapper.getActivityCode()); examOfferingWrapper.setDriverPerAO(true); eoClusterWrapper.getEoWrapperList().add(examOfferingWrapper); return; } } } } private ExamOfferingClusterWrapper getExamOfferingClusterWrapper( ActivityOfferingClusterWrapper aoClusterWrapper, List<ExamOfferingClusterWrapper> wrapperList) { for (ExamOfferingClusterWrapper eoClusterWrap : wrapperList) { if (eoClusterWrap.getActivityOfferingClusterId() .equals(aoClusterWrapper.getActivityOfferingClusterId())) { return eoClusterWrap; } } ExamOfferingClusterWrapper eoClusterWrapper = new ExamOfferingClusterWrapper(); eoClusterWrapper.setActivityOfferingClusterId(aoClusterWrapper.getActivityOfferingClusterId()); eoClusterWrapper.setFormatNameForDisplay(aoClusterWrapper.getFormatNameForDisplay()); eoClusterWrapper.setClusterNameForDisplay(aoClusterWrapper.getClusterNameForDisplay()); wrapperList.add(eoClusterWrapper); return eoClusterWrapper; } private ExamOfferingWrapper createWrapperFromExamOffering(ExamOfferingInfo examOfferingInfo, CourseOfferingManagementForm theForm) throws Exception { ExamOfferingWrapper eoWrapper = new ExamOfferingWrapper(); eoWrapper.setEoInfo(examOfferingInfo); StateInfo state = getStateService().getState(examOfferingInfo.getStateKey(), ContextUtils.createDefaultContextInfo()); eoWrapper.setStateName(state.getName()); CourseOfferingManagementUtil.getExamOfferingScheduleHelper().loadSchedules(eoWrapper, theForm, ContextUtils.createDefaultContextInfo()); //retrieve the EO matrix overriding attribute AttributeInfo attributeInfo = ExamOfferingManagementUtil.getAttributeForKey( examOfferingInfo.getAttributes(), ExamOfferingServiceConstants.EXAM_OFFERING_MATRIX_OVERRIDE_ATTR); if (attributeInfo != null) { eoWrapper.setOverrideMatrix(Boolean.valueOf(attributeInfo.getValue())); } return eoWrapper; } private String timeOfDayToTime(TimeOfDayInfo tod) { return TimeOfDayHelper.makeFormattedTimeForAOSchedules(tod); } private String convertIntoDaysDisplay(int day) { String dayOfWeek; switch (day) { case 1: dayOfWeek = SchedulingServiceConstants.SUNDAY_TIMESLOT_DISPLAY_DAY_CODE; break; case 2: dayOfWeek = SchedulingServiceConstants.MONDAY_TIMESLOT_DISPLAY_DAY_CODE; break; case 3: dayOfWeek = SchedulingServiceConstants.TUESDAY_TIMESLOT_DISPLAY_DAY_CODE; break; case 4: dayOfWeek = SchedulingServiceConstants.WEDNESDAY_TIMESLOT_DISPLAY_DAY_CODE; break; case 5: dayOfWeek = SchedulingServiceConstants.THURSDAY_TIMESLOT_DISPLAY_DAY_CODE; break; case 6: dayOfWeek = SchedulingServiceConstants.FRIDAY_TIMESLOT_DISPLAY_DAY_CODE; break; case 7: dayOfWeek = SchedulingServiceConstants.SATURDAY_TIMESLOT_DISPLAY_DAY_CODE; break; default: dayOfWeek = StringUtils.EMPTY; } // TODO implement TBA when service stores it. return dayOfWeek; } private String getDays(List<Integer> intList) { StringBuilder sb = new StringBuilder(); if (intList == null) { return sb.toString(); } for (Integer d : intList) { sb.append(convertIntoDaysDisplay(d)); } return sb.toString(); } public static String examPeriodDaysDisplay(List<Integer> weekdaysList, Date startTime, Date endTime, boolean excludeSaturdays, boolean excludeSundays) { StringBuilder result = new StringBuilder(); List<Date> dates = new ArrayList<Date>(); dates.addAll(getExamPeriodDates(startTime, endTime, excludeSaturdays, excludeSundays)); for (Integer weekday : weekdaysList) { result.append("Day " + weekday); result.append(" - "); result.append( DateFormatters.EXAM_OFFERING_VIEW_EXAM_OFFERING_DATE_FORMATTER.format(dates.get(weekday - 1))); } return result.toString(); } public static List<Date> getExamPeriodDates(Date fechInitial, Date fechFinal, boolean excludeSaturdays, boolean excludeSundays) { List<Date> dates = new ArrayList<Date>(); Calendar calendar = Calendar.getInstance(); calendar.setTime(fechInitial); while (calendar.getTime().before(fechFinal)) { Date resultado = calendar.getTime(); Calendar cal = Calendar.getInstance(); cal.setTime(resultado); int weekday = cal.get(Calendar.DAY_OF_WEEK); if ((weekday == Calendar.SATURDAY && !excludeSaturdays) || (weekday == Calendar.SUNDAY && !excludeSundays)) { dates.add(resultado); } else if ((weekday != Calendar.SATURDAY) && (weekday != Calendar.SUNDAY)) { dates.add(resultado); } calendar.add(Calendar.DATE, 1); } calendar.setTime(fechFinal); Date finalDate = calendar.getTime(); dates.add(finalDate); return dates; } /** * A pass-thru to the building info search in the schedule helper. */ public List<BuildingInfo> retrieveBuildingInfoByCode(String buildingCode) throws Exception { return CourseOfferingManagementUtil.getScheduleHelper().retrieveBuildingInfoByCode(buildingCode, false); } /** * This method set the EO matrix RSI Overidable flag for the current CO wrapper * * @param theForm CourseOfferingManagementForm */ private void setExamOfferingMatrixRSIOveridability(CourseOfferingManagementForm theForm) { AttributeInfo attributeInfo = ExamOfferingManagementUtil.getAttributeForKey( theForm.getCurrentCourseOfferingWrapper().getCourseOfferingInfo().getAttributes(), CourseOfferingServiceConstants.FINAL_EXAM_USE_MATRIX); if ((attributeInfo == null) || !Boolean.valueOf(attributeInfo.getValue())) { theForm.getCurrentCourseOfferingWrapper().setMatrixOveridableAODriven(false); theForm.getCurrentCourseOfferingWrapper().setMatrixOveridableCODriven(false); return; } if (theForm.getTermInfo() != null && StringUtils.isNotBlank(theForm.getTermInfo().getTypeKey())) { KrmsTypeDefinition typeDefinitionAODriven = CourseOfferingManagementUtil.getKrmsTypeRepositoryService() .getTypeByName(PermissionServiceConstants.KS_SYS_NAMESPACE, KSKRMSServiceConstants.AGENDA_TYPE_FINAL_EXAM_AO_DRIVEN); if (typeDefinitionAODriven != null) { Agenda agendaAODriven = getAgendaForRefObjectId(theForm.getTermInfo().getTypeKey(), typeDefinitionAODriven); if (agendaAODriven != null) { theForm.getCurrentCourseOfferingWrapper().setMatrixOveridableAODriven(true); theForm.getCurrentCourseOfferingWrapper().setMatrixExists(true); } else { theForm.getCurrentCourseOfferingWrapper().setMatrixOveridableAODriven(false); theForm.getCurrentCourseOfferingWrapper().setMatrixExists(false); } } KrmsTypeDefinition typeDefinitionCODriven = CourseOfferingManagementUtil.getKrmsTypeRepositoryService() .getTypeByName(PermissionServiceConstants.KS_SYS_NAMESPACE, KSKRMSServiceConstants.AGENDA_TYPE_FINAL_EXAM_CO_DRIVEN); if (typeDefinitionCODriven != null) { Agenda agendaCODriven = getAgendaForRefObjectId(theForm.getTermInfo().getTypeKey(), typeDefinitionCODriven); if (agendaCODriven != null) { theForm.getCurrentCourseOfferingWrapper().setMatrixOveridableCODriven(true); theForm.getCurrentCourseOfferingWrapper().setMatrixExists(true); } else { theForm.getCurrentCourseOfferingWrapper().setMatrixOveridableAODriven(false); theForm.getCurrentCourseOfferingWrapper().setMatrixExists(false); } } } } private Agenda getAgendaForRefObjectId(String refObjectId, KrmsTypeDefinition typeDefinition) { //Retrieve bindings for this reference object id. List<ReferenceObjectBinding> referenceObjectBindings = CourseOfferingManagementUtil .getRuleManagementService().findReferenceObjectBindingsByReferenceObject( TypeServiceConstants.REF_OBJECT_URI_TYPE, refObjectId); for (ReferenceObjectBinding referenceObjectBinding : referenceObjectBindings) { //Retrieve the agenda and check the type. AgendaDefinition agendaDefinition = CourseOfferingManagementUtil.getRuleManagementService() .getAgenda(referenceObjectBinding.getKrmsObjectId()); if (agendaDefinition.getTypeId().equals(typeDefinition.getId())) { //Only a single agenda for a specific type should exist in the matrix. return KrmsRepositoryServiceLocator.getKrmsRepositoryToEngineTranslator() .translateAgendaDefinition(agendaDefinition); } } return null; } }