001 /** 002 * Copyright 2012 The Kuali Foundation Licensed under the 003 * Educational Community License, Version 2.0 (the "License"); you may 004 * not use this file except in compliance with the License. You may 005 * obtain a copy of the License at 006 * 007 * http://www.osedu.org/licenses/ECL-2.0 008 * 009 * Unless required by applicable law or agreed to in writing, 010 * software distributed under the License is distributed on an "AS IS" 011 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express 012 * or implied. See the License for the specific language governing 013 * permissions and limitations under the License. 014 * 015 * @author Kuali Student Team 016 */ 017 package org.kuali.student.enrollment.class2.courseoffering.service.impl; 018 019 020 import org.apache.commons.lang.StringUtils; 021 import org.kuali.rice.core.api.util.ConcreteKeyValue; 022 import org.kuali.rice.core.api.util.KeyValue; 023 import org.kuali.rice.krad.maintenance.MaintainableImpl; 024 import org.kuali.rice.krad.uif.UifConstants; 025 import org.kuali.rice.krad.uif.control.CheckboxGroupControl; 026 import org.kuali.rice.krad.uif.control.SelectControl; 027 import org.kuali.rice.krad.uif.field.InputField; 028 import org.kuali.rice.krad.web.form.MaintenanceDocumentForm; 029 import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingCreateWrapper; 030 import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingEditWrapper; 031 import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingWrapper; 032 import org.kuali.student.enrollment.class2.courseoffering.dto.FormatOfferingWrapper; 033 import org.kuali.student.enrollment.class2.courseoffering.service.CourseOfferingMaintainable; 034 import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingResourceLoader; 035 import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingCrossListingInfo; 036 import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo; 037 import org.kuali.student.enrollment.courseoffering.dto.FormatOfferingInfo; 038 import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService; 039 import org.kuali.student.r2.common.dto.ContextInfo; 040 import org.kuali.student.r2.common.util.ContextUtils; 041 import org.kuali.student.r2.common.util.constants.LuiServiceConstants; 042 import org.kuali.student.r2.core.class1.state.service.StateService; 043 import org.kuali.student.r2.core.class1.type.dto.TypeInfo; 044 import org.kuali.student.r2.core.class1.type.service.TypeService; 045 import org.kuali.student.r2.lum.course.dto.ActivityInfo; 046 import org.kuali.student.r2.lum.course.dto.CourseCrossListingInfo; 047 import org.kuali.student.r2.lum.course.dto.CourseInfo; 048 import org.kuali.student.r2.lum.course.dto.FormatInfo; 049 import org.kuali.student.r2.lum.course.service.CourseService; 050 051 import java.util.ArrayList; 052 import java.util.HashSet; 053 import java.util.List; 054 import java.util.Set; 055 056 /** 057 * Base view helper service for both create and edit course offering presentations. 058 * 059 */ 060 public abstract class CourseOfferingMaintainableImpl extends MaintainableImpl implements CourseOfferingMaintainable { 061 062 private transient CourseOfferingService courseOfferingService; 063 private transient TypeService typeService; 064 private transient StateService stateService; 065 private transient CourseService courseService; 066 067 /** 068 * This method is being called by KRAD to populate grade roster level types drop down. 069 * 070 * <p> 071 * In 'Create CO', we use a wrapper around <code>FormatOfferingInfo</code> to handle joint formats. 072 * In 'Edit CO', it's just <code>FormatOfferingInfo</code> at the collection 073 * </p> 074 * 075 * <p>There would be no reference for this method in the code as it has it's references at the following view xmls</p> 076 * <ul> 077 * <li>CourseOfferingCreateMaintenanceView.xml</li> 078 * <li>CourseOfferingEditMaintenanceView.xml</li> 079 * </ul> 080 * 081 * @param field grade roster level field 082 * @param form maintenace form 083 * @see #populateFinalExamDriverTypes 084 */ 085 @SuppressWarnings("unused") 086 public void populateGradeRosterLevelTypes(InputField field, MaintenanceDocumentForm form){ 087 088 if (field.isReadOnly()){ 089 return; 090 } 091 092 FormatOfferingInfo formatOfferingInfo; 093 CourseOfferingWrapper wrapper = (CourseOfferingWrapper)form.getDocument().getNewMaintainableObject().getDataObject(); 094 CourseInfo courseInfo = wrapper.getCourse(); 095 096 if (wrapper instanceof CourseOfferingCreateWrapper) { 097 /** 098 * If the call is from create co, then there are two places from where this method is being called. From the 'Add format' section 099 * and from the format offering collections. For the 'add format' section, we're checking the property name to get the FO Wrapper 100 */ 101 if (StringUtils.equals(field.getPropertyName(),"addLineFormatWrapper.gradeRosterLevelTypeKey")){ 102 formatOfferingInfo = ((CourseOfferingCreateWrapper)wrapper).getAddLineFormatWrapper().getFormatOfferingInfo(); 103 } else { 104 //This else is for the format offering collection. 105 FormatOfferingWrapper foWrapper = (FormatOfferingWrapper)field.getContext().get(UifConstants.ContextVariableNames.LINE); 106 formatOfferingInfo = foWrapper.getFormatOfferingInfo(); 107 if (foWrapper.isJointOffering()){ 108 courseInfo = foWrapper.getJointCreateWrapper().getCourseInfo(); 109 } 110 } 111 } else { 112 formatOfferingInfo = (FormatOfferingInfo)field.getContext().get(UifConstants.ContextVariableNames.LINE); 113 } 114 115 SelectControl control = (SelectControl)field.getControl(); 116 117 List<KeyValue> gradeKeyValues = new ArrayList<KeyValue>(); 118 119 if (StringUtils.isNotBlank(formatOfferingInfo.getFormatId())){ 120 // Always include an option for Course 121 gradeKeyValues.add(new ConcreteKeyValue(LuiServiceConstants.COURSE_OFFERING_TYPE_KEY, getTypeName(LuiServiceConstants.COURSE_OFFERING_TYPE_KEY))); 122 gradeKeyValues.addAll(collectActivityTypeKeyValues(courseInfo, formatOfferingInfo.getFormatId(), getTypeService(), ContextUtils.createDefaultContextInfo())); 123 control.setDisabled(false); 124 } else { 125 control.setDisabled(true); 126 } 127 128 control.setOptions(gradeKeyValues); 129 130 } 131 132 /** 133 * This method is being called by KRAD to populate final exam driver types drop down. 134 * 135 * <p> 136 * In 'Create CO', we use a wrapper around <code>FormatOfferingInfo</code> to handle joint formats. 137 * In 'Edit CO', it's just <code>FormatOfferingInfo</code> at the collection 138 * </p> 139 * 140 * <p>There would be no reference for this method in the code as it has it's references at the following view xmls</p> 141 * <ul> 142 * <li>CourseOfferingCreateMaintenanceView.xml</li> 143 * <li>CourseOfferingEditMaintenanceView.xml</li> 144 * </ul> 145 * 146 * @param field grade roster level field 147 * @param form maintenace form 148 * @see #populateGradeRosterLevelTypes 149 */ 150 @SuppressWarnings("unused") 151 public void populateFinalExamDriverTypes(InputField field, MaintenanceDocumentForm form){ 152 153 if (field.isReadOnly()){ 154 return; 155 } 156 157 FormatOfferingInfo formatOfferingInfo; 158 CourseOfferingWrapper wrapper = (CourseOfferingWrapper)form.getDocument().getNewMaintainableObject().getDataObject(); 159 CourseInfo courseInfo = wrapper.getCourse(); 160 161 if (wrapper instanceof CourseOfferingCreateWrapper) { 162 /** 163 * If the call is from create co, then there are two places from where this method is being called. From the 'Add format' section 164 * and from the format offering collections. For the 'add format' section, we're checking the property name to get the FO Wrapper 165 */ 166 if (StringUtils.equals(field.getPropertyName(),"addLineFormatWrapper.finalExamLevelTypeKey")){ 167 formatOfferingInfo = ((CourseOfferingCreateWrapper)wrapper).getAddLineFormatWrapper().getFormatOfferingInfo(); 168 } else { 169 //This else is for the format offering collection. 170 FormatOfferingWrapper foWrapper = (FormatOfferingWrapper)field.getContext().get(UifConstants.ContextVariableNames.LINE); 171 formatOfferingInfo = foWrapper.getFormatOfferingInfo(); 172 if (foWrapper.isJointOffering()){ 173 courseInfo = foWrapper.getJointCreateWrapper().getCourseInfo(); 174 } 175 } 176 } else { 177 formatOfferingInfo = (FormatOfferingInfo)field.getContext().get(UifConstants.ContextVariableNames.LINE); 178 } 179 180 SelectControl control = (SelectControl)field.getControl(); 181 182 List<KeyValue> keyValues = new ArrayList<KeyValue>(); 183 184 if (StringUtils.isNotBlank(formatOfferingInfo.getFormatId()) && courseInfo != null){ 185 keyValues.addAll(collectActivityTypeKeyValues(courseInfo, formatOfferingInfo.getFormatId(), getTypeService(), ContextUtils.createDefaultContextInfo())); 186 control.setDisabled(false); 187 } else { 188 control.setDisabled(true); 189 } 190 191 control.setOptions(keyValues); 192 193 } 194 195 protected List<KeyValue> collectActivityTypeKeyValues(CourseInfo course, String formatId, TypeService typeService, ContextInfo contextInfo) { 196 197 List<KeyValue> results = new ArrayList<KeyValue>(); 198 199 Set<String> activityTypes = new HashSet<String>(); 200 for(FormatInfo format : course.getFormats()) { 201 if (StringUtils.isBlank(formatId) || (StringUtils.isNotBlank(formatId) && StringUtils.equals(format.getId(),formatId))){ 202 for (ActivityInfo activity : format.getActivities()) { 203 // if we haven't added a value for this activity type yet 204 if(activityTypes.add(activity.getTypeKey())) { 205 try { 206 TypeInfo type = typeService.getType(activity.getTypeKey(), contextInfo); 207 results.add(new ConcreteKeyValue(type.getKey(), type.getName())); 208 } catch (Exception e) { 209 throw new RuntimeException(e); 210 } 211 } 212 } 213 } 214 } 215 216 return results; 217 } 218 219 public void populateCrossCourseList(InputField field, MaintenanceDocumentForm form){ 220 221 CourseOfferingCreateWrapper wrapper = (CourseOfferingCreateWrapper)form.getDocument().getNewMaintainableObject().getDataObject(); 222 223 CheckboxGroupControl control = (CheckboxGroupControl)field.getControl(); 224 225 List<KeyValue> crossListedCos = new ArrayList<KeyValue>(); 226 227 if (wrapper.getCourseOfferingInfo().getCrossListings() != null && wrapper.getCourseOfferingInfo().getCrossListings().size() > 0){ 228 // Always include an option for Course 229 for(CourseOfferingCrossListingInfo courseInfo : wrapper.getCourseOfferingInfo().getCrossListings()) { 230 crossListedCos.add(new ConcreteKeyValue(courseInfo.getId(), courseInfo.getCode())); 231 } 232 } 233 234 crossListedCos.add(new ConcreteKeyValue("1", "A")); 235 control.setOptions(crossListedCos); 236 237 } 238 239 /** 240 * This method populates {@link CourseCrossListingInfo} in to the {@link CourseOfferingInfo} 241 * based on the user selection at create or edit CO. Note: If the <code>kuali.ks.enrollment.options.selective-crosslisting-allowed</code> 242 * property is enabled, this method creates cross listing dtos for all the alternate course codes. 243 * 244 * @param wrapper either {@link CourseOfferingCreateWrapper} or {@link org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingEditWrapper} 245 * @param coInfo course offering dto 246 */ 247 protected void loadCrossListedCOs(CourseOfferingWrapper wrapper, CourseOfferingInfo coInfo) { 248 coInfo.getCrossListings().clear(); 249 if (wrapper.isSelectCrossListingAllowed()) { 250 List<String> alternateCodes = null; 251 if (wrapper instanceof CourseOfferingCreateWrapper){ 252 alternateCodes = wrapper.getAlternateCOCodes(); 253 } else if (wrapper instanceof CourseOfferingEditWrapper){ 254 alternateCodes = ((CourseOfferingEditWrapper)wrapper).getAlternateCourseCodesSuffixStripped(); 255 } 256 for (String alternateCode : alternateCodes) { 257 for (CourseCrossListingInfo crossInfo : wrapper.getCourse().getCrossListings()) { 258 if (StringUtils.equals(crossInfo.getCode(),alternateCode)) { 259 CourseOfferingCrossListingInfo crossListingInfo = new CourseOfferingCrossListingInfo(); 260 crossListingInfo.setCode(crossInfo.getCode()); 261 crossListingInfo.setCourseNumberSuffix(crossInfo.getCourseNumberSuffix()); 262 crossListingInfo.setSubjectOrgId(crossInfo.getSubjectOrgId()); 263 crossListingInfo.setSubjectArea(crossInfo.getSubjectArea()); 264 crossListingInfo.setStateKey(LuiServiceConstants.LUI_CO_STATE_DRAFT_KEY); 265 crossListingInfo.setTypeKey(LuiServiceConstants.LUI_IDENTIFIER_CROSSLISTED_TYPE_KEY); 266 coInfo.getCrossListings().add(crossListingInfo); 267 } 268 } 269 } 270 } else { 271 // get all the crosslisted COs 272 CourseInfo courseInfo = wrapper.getCourse(); 273 for (CourseCrossListingInfo crossInfo : courseInfo.getCrossListings()) { 274 CourseOfferingCrossListingInfo crossListingInfo = new CourseOfferingCrossListingInfo(); 275 crossListingInfo.setCode(crossInfo.getCode()); 276 crossListingInfo.setCourseNumberSuffix(crossInfo.getCourseNumberSuffix()); 277 crossListingInfo.setSubjectOrgId(crossInfo.getSubjectOrgId()); 278 crossListingInfo.setSubjectArea(crossInfo.getSubjectArea()); 279 crossListingInfo.setStateKey(LuiServiceConstants.LUI_CO_STATE_DRAFT_KEY); 280 crossListingInfo.setTypeKey(LuiServiceConstants.LUI_IDENTIFIER_CROSSLISTED_TYPE_KEY); 281 coInfo.getCrossListings().add(crossListingInfo); 282 } 283 } 284 } 285 286 protected TypeService getTypeService() { 287 if(typeService == null) { 288 typeService = CourseOfferingResourceLoader.loadTypeService(); 289 } 290 return this.typeService; 291 } 292 293 protected StateService getStateService() { 294 if(stateService == null) { 295 stateService = CourseOfferingResourceLoader.loadStateService(); 296 } 297 return stateService; 298 } 299 300 protected CourseOfferingService getCourseOfferingService() { 301 if (courseOfferingService == null) { 302 courseOfferingService = CourseOfferingResourceLoader.loadCourseOfferingService(); 303 } 304 return courseOfferingService; 305 } 306 307 protected CourseService getCourseService() { 308 if(courseService == null) { 309 courseService = CourseOfferingResourceLoader.loadCourseService(); 310 } 311 return this.courseService; 312 } 313 314 /** 315 * Returns the Name for a type key. 316 * 317 * @param typeKey 318 * @return 319 */ 320 protected String getTypeName(String typeKey){ 321 try{ 322 TypeInfo typeInfo = getTypeService().getType(typeKey,ContextUtils.createDefaultContextInfo()); 323 return typeInfo.getName(); 324 } catch (Exception e){ 325 //Throwing a runtime as we use this method to get the type name only for the ui purpose.. 326 throw new RuntimeException(e); 327 } 328 } 329 330 331 }