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 }