View Javadoc

1   /**
2    * Copyright 2013 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   *
15   * Created by David Yin on 3/4/13
16   */
17  package org.kuali.student.enrollment.class2.autogen.controller;
18  
19  import org.apache.commons.lang.BooleanUtils;
20  import org.apache.commons.lang.StringUtils;
21  import org.kuali.rice.krad.uif.UifConstants;
22  import org.kuali.rice.krad.uif.UifParameters;
23  import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
24  import org.kuali.rice.krad.util.GlobalVariables;
25  import org.kuali.rice.krad.util.KRADConstants;
26  import org.kuali.student.common.uif.util.GrowlIcon;
27  import org.kuali.student.common.uif.util.KSUifUtils;
28  import org.kuali.student.enrollment.class1.krms.dto.AORuleManagementWrapper;
29  import org.kuali.student.enrollment.class2.autogen.form.ARGCourseOfferingManagementForm;
30  import org.kuali.student.enrollment.class2.courseoffering.dto.ActivityOfferingClusterWrapper;
31  import org.kuali.student.enrollment.class2.courseoffering.dto.ActivityOfferingWrapper;
32  import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingListSectionWrapper;
33  import org.kuali.student.enrollment.class2.courseoffering.dto.CourseOfferingWrapper;
34  import org.kuali.student.enrollment.class2.courseoffering.util.ActivityOfferingConstants;
35  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingConstants;
36  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingResourceLoader;
37  import org.kuali.student.enrollment.class2.courseoffering.util.CourseOfferingViewHelperUtil;
38  import org.kuali.student.enrollment.class2.courseoffering.util.FormatOfferingConstants;
39  import org.kuali.student.enrollment.class2.courseoffering.util.RegistrationGroupConstants;
40  import org.kuali.student.common.util.ContextBuilder;
41  import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingClusterInfo;
42  import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingInfo;
43  import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo;
44  import org.kuali.student.enrollment.courseoffering.dto.FormatOfferingInfo;
45  import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService;
46  import org.kuali.student.r2.common.dto.ContextInfo;
47  import org.kuali.student.r2.common.util.ContextUtils;
48  import org.kuali.student.r2.core.class1.search.CourseOfferingManagementSearchImpl;
49  
50  import java.util.Collection;
51  import java.util.Collections;
52  import java.util.Comparator;
53  import java.util.List;
54  import java.util.Properties;
55  
56  
57  /**
58   * This class is used by the ARGCourseOfferingManagementController to handle AO Cluster operations
59   *
60   * @author Kuali Student Team
61   */
62  public class ARGActivityOfferingClusterHandler {
63  
64      private static boolean createAOCFromMove = false;
65  
66      public static boolean loadAOs_RGs_AOCs(ARGCourseOfferingManagementForm form) throws Exception {
67  
68          Object selectedObject = ARGUtil.getSelectedObject(form, "Manage");
69  
70          if (selectedObject instanceof CourseOfferingListSectionWrapper) {
71              CourseOfferingListSectionWrapper coWrapper = (CourseOfferingListSectionWrapper) selectedObject;
72              CourseOfferingInfo courseOffering = ARGUtil.getCourseOfferingService().getCourseOffering(coWrapper.getCourseOfferingId(), ContextUtils.createDefaultContextInfo());
73              CourseOfferingWrapper currentCOWrapper = new CourseOfferingWrapper(courseOffering);
74              form.setInputCode(coWrapper.getCourseOfferingCode());
75              form.setCurrentCourseOfferingWrapper(currentCOWrapper);
76  
77              ARGUtil.prepareManageAOsModelAndView(form, coWrapper);
78              return true;
79          } else {
80              return false;
81          }
82      }
83  
84      public static void selectAllActivityOfferings(ARGCourseOfferingManagementForm theForm) throws Exception {
85          List<ActivityOfferingWrapper> list = theForm.getActivityWrapperList();
86          for (ActivityOfferingWrapper listElement : list) {
87              listElement.setIsChecked(true);
88          }
89      }
90  
91      public static void copyAO(ARGCourseOfferingManagementForm form) {
92          ActivityOfferingWrapper selectedAO = (ActivityOfferingWrapper) ARGUtil.getSelectedObject(form, "copy");
93          try {
94              String aoIdToCopy = selectedAO.getAoInfo().getId(); // Create a copy of this AO
95              String clusterId = selectedAO.getAoClusterID();
96              ARGUtil.getArgServiceAdapter().copyActivityOfferingToCluster(aoIdToCopy, clusterId, ContextBuilder.loadContextInfo());
97  
98              // reload AOs including the new one just created
99              ARGUtil.reloadTheCourseOfferingWithAOs_RGs_Clusters(form);
100         } catch (Exception e) {
101             throw new RuntimeException(e);
102         }
103     }
104 
105     public static void deleteSelectedAoList(ARGCourseOfferingManagementForm theForm) throws Exception {
106 
107         List<ActivityOfferingWrapper> selectedAolist = theForm.getSelectedToDeleteList();
108 
109         try {
110             for (ActivityOfferingWrapper ao : selectedAolist) {
111                 // The adapter does not technically need an AOC ID, so I'm setting it to null
112                 ARGUtil.getArgServiceAdapter().deleteActivityOfferingCascaded(ao.getAoInfo().getId(), null, ContextBuilder.loadContextInfo());
113             }
114 
115             // check for changes to states in CO and related FOs
116             CourseOfferingViewHelperUtil.updateCourseOfferingStateFromActivityOfferingStateChange(theForm.getCurrentCourseOfferingWrapper().getCourseOfferingInfo(), ContextBuilder.loadContextInfo());
117 
118         } catch (Exception e) {
119             throw new RuntimeException(e);
120         }
121 
122         ARGUtil.reloadTheCourseOfferingWithAOs_RGs_Clusters(theForm);
123 
124         if (selectedAolist.size() > 0 && theForm.isSelectedIllegalAOInDeletion()) {
125             GlobalVariables.getMessageMap().putWarningForSectionId("manageActivityOfferingsPage",
126                     CourseOfferingConstants.COURSEOFFERING_MSG_ERROR_SELECTED_AO_TO_DELETE);
127         }
128 
129         if (selectedAolist.size() > 1) {
130             KSUifUtils.addGrowlMessageIcon(GrowlIcon.INFORMATION, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_DELETE_N_SUCCESS);
131         } else {
132             KSUifUtils.addGrowlMessageIcon(GrowlIcon.INFORMATION, CourseOfferingConstants.ACTIVITYOFFERING_TOOLBAR_DELETE_1_SUCCESS);
133         }
134     }
135 
136     public static Properties editAO(ARGCourseOfferingManagementForm theForm, String aoId) throws Exception {
137         Properties urlParameters = new Properties();
138         urlParameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.Maintenance.METHOD_TO_CALL_EDIT);
139         urlParameters.put(ActivityOfferingConstants.ACTIVITY_OFFERING_WRAPPER_ID, aoId);
140         urlParameters.put(ActivityOfferingConstants.ACTIVITYOFFERING_COURSE_OFFERING_ID, theForm.getCurrentCourseOfferingWrapper().getCourseOfferingInfo().getId());
141         urlParameters.put(KRADConstants.DATA_OBJECT_CLASS_ATTRIBUTE, ActivityOfferingWrapper.class.getName());
142         urlParameters.put(UifConstants.UrlParams.SHOW_HOME, BooleanUtils.toStringTrueFalse(false));
143 
144         return urlParameters;
145     }
146 
147     public static boolean confirmDelete(ARGCourseOfferingManagementForm theForm) throws Exception {
148         Collection<Object> collection;
149         Object selectedObject;
150         List<ActivityOfferingWrapper> aoList = theForm.getActivityWrapperList();
151         List<ActivityOfferingWrapper> selectedIndexList = theForm.getSelectedToDeleteList();
152         boolean bEncounteredNonDraftAOInDeletion = false;
153 
154         // clear the list
155         selectedIndexList.clear();
156 
157         String selectedCollectionPath = theForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
158         if (StringUtils.isNotBlank(selectedCollectionPath)) {
159             // select the single AO
160             int selectedLineIndex = -1;
161             String selectedLine = theForm.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
162             if (StringUtils.isNotBlank(selectedLine)) {
163                 selectedLineIndex = Integer.parseInt(selectedLine);
164             }
165 
166             if (selectedLineIndex == -1) {
167                 throw new RuntimeException("Selected line index was not set");
168             }
169 
170             collection = ObjectPropertyUtils.getPropertyValue(theForm, selectedCollectionPath);
171 
172             selectedObject = ((List<Object>) collection).get(selectedLineIndex);
173             // Record the selected AO IsChecked
174             selectedIndexList.add((ActivityOfferingWrapper) selectedObject);
175         } else {
176             // check if there is Draft AO selected
177             selectedIndexList.clear();
178             for (ActivityOfferingWrapper ao : aoList) {
179                 if (ao.isLegalToDelete() && ((!"0".equals(theForm.getSelectedTabId()))&& ao.getIsChecked()||
180                                              ( "0".equals(theForm.getSelectedTabId()))&& ao.getIsCheckedByCluster())) {
181                     selectedIndexList.add(ao);
182                 } else if ((!"0".equals(theForm.getSelectedTabId()))&& ao.getIsChecked()||
183                         ( "0".equals(theForm.getSelectedTabId()))&& ao.getIsCheckedByCluster()) {
184                     if (!bEncounteredNonDraftAOInDeletion) {
185                         bEncounteredNonDraftAOInDeletion = true;
186                     }
187                 }
188             }
189         }
190 
191         if (selectedIndexList.isEmpty()) {
192             if (bEncounteredNonDraftAOInDeletion) {
193                 GlobalVariables.getMessageMap().putError("manageActivityOfferingsPage",
194                         CourseOfferingConstants.AO_NOT_DRAFT_FOR_DELETION_ERROR);
195             } else {
196                 GlobalVariables.getMessageMap().putError("manageActivityOfferingsPage",
197                         CourseOfferingConstants.COURSEOFFERING_MSG_ERROR_FOUND_NO_DRAFT_AO_SELECTED);
198             }
199             return false;
200         } else {
201             theForm.setSelectedIllegalAOInDeletion(false);
202             if (bEncounteredNonDraftAOInDeletion) {
203                 theForm.setSelectedIllegalAOInDeletion(true);
204             }
205         }
206 
207         return true;
208     }
209 
210     public static Properties view(@SuppressWarnings("unused") ARGCourseOfferingManagementForm theForm, ActivityOfferingWrapper aoWrapper) throws Exception {
211         Properties urlParameters = new Properties();
212         urlParameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.START_METHOD);
213         urlParameters.put(ActivityOfferingConstants.ACTIVITYOFFERING_ID, aoWrapper.getAoInfo().getId());
214         urlParameters.put(KRADConstants.DATA_OBJECT_CLASS_ATTRIBUTE, ActivityOfferingInfo.class.getName());
215         return urlParameters;
216     }
217 
218     public static void addActivityOfferings(ARGCourseOfferingManagementForm theForm) throws Exception {
219 
220         String activityId = theForm.getActivityIdForNewAO();
221         String formatOfferingId = theForm.getFormatOfferingIdForNewAO();
222         int aoCount = Integer.parseInt(theForm.getNoOfActivityOfferings());
223 
224         ARGUtil.getViewHelperService(theForm).createActivityOfferings(formatOfferingId, activityId, aoCount, theForm);
225         ARGUtil.reloadTheCourseOfferingWithAOs_RGs_Clusters(theForm);
226 
227         theForm.setFormatIdForNewAO(null);
228         theForm.setFormatOfferingIdForNewAO(null);
229         theForm.setActivityIdForNewAO(null);
230         theForm.setNoOfActivityOfferings(null);
231     }
232 
233     public static ARGCourseOfferingManagementForm createNewCluster(ARGCourseOfferingManagementForm theForm) throws Exception {
234 
235         /* Indicate that the search used to redraw the page after this operation completes should use an exact
236          * match of the course code rather than the usual "like" criteria. Otherwise, if the course code matches multiple
237          * items (e.g. CHEM100, CHEM100A, CHEM100B) then the Manage multiple COs page will be displayed rather than Manage
238          * individual CO page. */
239         theForm.getViewRequestParameters().put(CourseOfferingManagementSearchImpl.SearchParameters.IS_EXACT_MATCH_CO_CODE_SEARCH, Boolean.TRUE.toString());
240 
241         String growlPrivateName;
242         String growlPublicName;
243 
244         if (createAOCFromMove) {  //where is the call coming from
245             if (theForm.getPrivateClusterNameForMovePopover().isEmpty()) {
246                 GlobalVariables.getMessageMap().putError("privateClusterNameForMovePopover", RegistrationGroupConstants.MSG_ERROR_CLUSTER_PRIVATE_NAME_IS_NULL);
247                 createAOCFromMove = false;
248                 return theForm;
249             }
250 
251             growlPrivateName = theForm.getPrivateClusterNameForMovePopover();
252             growlPublicName = theForm.getPublishedClusterNameForMovePopover();
253         } else {
254             if (theForm.getPrivateClusterNamePopover().isEmpty()) {
255                 GlobalVariables.getMessageMap().putError("privateClusterNamePopover", RegistrationGroupConstants.MSG_ERROR_CLUSTER_PRIVATE_NAME_IS_NULL);
256                 return theForm;
257             }
258 
259             growlPrivateName = theForm.getPrivateClusterNamePopover();
260             growlPublicName = theForm.getPublishedClusterNamePopover();
261         }
262 
263         String formatOfferingId = theForm.getFormatOfferingIdForViewRG();
264         ContextInfo context = ContextUtils.createDefaultContextInfo();
265         FormatOfferingInfo formatOfferingInfo = getCourseOfferingService().getFormatOffering(formatOfferingId, context);
266 
267         //validate if the given FO is allowed to create multiple clusters
268         //FO has multiple AO types: it can have multiple clusters
269         //FO has single AO type: it can only have one cluster
270         if (!ARGUtil._clusterForFormatOfferingValidation(formatOfferingInfo, context)) {
271             GlobalVariables.getMessageMap().putError("privateClusterName", FormatOfferingConstants.MSG_ERROR_FORMAT_OFFERING_CLUSTER_OVERLIMIT, formatOfferingInfo.getName());
272             return theForm;
273         }
274 
275         if (ARGUtil._isClusterUniqueWithinCO(theForm, theForm.getCurrentCourseOfferingWrapper().getCourseOfferingId(), growlPrivateName)){
276 
277             //build a new empty cluster
278             ActivityOfferingClusterInfo emptyCluster = ARGUtil._buildEmptyAOCluster(formatOfferingId,
279                     growlPrivateName, growlPublicName);
280 
281             //persist it in DB , comment out for now since it does not work for now
282             emptyCluster = ARGUtil.getCourseOfferingService().createActivityOfferingCluster(formatOfferingId,
283                     emptyCluster.getTypeKey(), emptyCluster, context);
284 
285 
286 
287             List<ActivityOfferingClusterWrapper> aoClusterWrapperList = theForm.getClusterResultList();
288             ActivityOfferingClusterWrapper aoClusterWrapper = new ActivityOfferingClusterWrapper();
289             aoClusterWrapper.setActivityOfferingClusterId(emptyCluster.getId());
290             aoClusterWrapper.setAoCluster(emptyCluster);
291             aoClusterWrapper.setClusterNameForDisplay("Forget to set cluster?");
292 
293             aoClusterWrapperList.add(aoClusterWrapper);
294             // KSENROLL-6506 Added below, the sorting on FormatOfferingID and Private name of the Cluster.
295             if(aoClusterWrapperList.size() > 1){
296                 Collections.sort(aoClusterWrapperList, new Comparator<ActivityOfferingClusterWrapper>() {
297                     @Override
298                     public int compare(ActivityOfferingClusterWrapper obj1, ActivityOfferingClusterWrapper obj2) {
299 
300                         int formatOfferingComparison = obj1.getAoCluster().getFormatOfferingId().compareTo(obj2.getAoCluster().getFormatOfferingId());
301                         if (formatOfferingComparison == 0)
302                         {
303                             int nameComparison = obj1.getAoCluster().getPrivateName().compareToIgnoreCase(obj2.getAoCluster().getPrivateName());
304                             int formatComparison = obj1.getFormatNameForDisplay().compareToIgnoreCase(obj2.getFormatNameForDisplay());
305                             if(formatComparison==0){
306                                 return nameComparison;
307                             } else {
308                                 return formatComparison;
309                             }
310                         } else{
311                             return formatOfferingComparison;
312                         }
313 
314                     }
315                 });
316             }
317 
318             theForm.setClusterResultList(aoClusterWrapperList);
319             theForm.setPrivateClusterNamePopover("");
320             theForm.setPublishedClusterNamePopover("");
321             theForm.setPrivateClusterNameForMovePopover("");
322             theForm.setPublishedClusterNameForMovePopover("");
323             createAOCFromMove = false;
324         }else{
325             GlobalVariables.getMessageMap().putError("privateClusterName", RegistrationGroupConstants.MSG_ERROR_INVALID_CLUSTER_NAME);
326             return theForm;
327         }
328 
329         GlobalVariables.getMessageMap().addGrowlMessage("", CourseOfferingConstants.CLUSTER_CREATE_SUCCESS, growlPrivateName, growlPublicName );
330 
331         return theForm;
332     }
333 
334     public static ARGCourseOfferingManagementForm moveAOToACluster (ARGCourseOfferingManagementForm theForm) throws Exception {
335 
336         ContextInfo context = ContextUtils.createDefaultContextInfo();
337         boolean aoChecked = false;
338         String aocId;
339 
340         //get selected AOC info
341         if (theForm.getClusterIdForAOMove().equals("")){
342             GlobalVariables.getMessageMap().putError("AOCselectionError", RegistrationGroupConstants.MSG_ERROR_INVALID_CLUSTER_SELECTION);
343             return theForm;
344         }
345 
346         aocId = theForm.getClusterIdForAOMove();
347 
348         //move AO
349         for (ActivityOfferingWrapper aoWrapper : theForm.getActivityWrapperList()) {
350             if ((!"0".equals(theForm.getSelectedTabId())&& aoWrapper.getIsChecked())||
351                 ( "0".equals(theForm.getSelectedTabId())&& aoWrapper.getIsCheckedByCluster())) {
352                 if("createNewCluster".equals(aocId)){
353                     // create cluster and set aocId to the id of the cluster
354                     theForm.setPublishedClusterNameForRenamePopover(theForm.getPublishedClusterNamePopover());
355                     if(!StringUtils.isEmpty(theForm.getFormatOfferingIdForViewRG())) {
356                         theForm.setFormatOfferingIdForViewRG(theForm.getSelectedFOIDForAOMove());
357                     }
358                     createAOCFromMove = true;
359                     theForm = createNewCluster(theForm);
360                     if(GlobalVariables.getMessageMap().hasErrors()){
361                         return theForm;
362                     }
363 
364                     aocId = theForm.getClusterResultList().get(theForm.getClusterResultList().size() - 1).getActivityOfferingClusterId();
365 
366                 }
367                 ARGUtil.getArgServiceAdapter().moveActivityOffering(aoWrapper.getAoInfo().getId(), aoWrapper.getAoClusterID(), aocId, context);
368                 aoChecked = true;
369             }
370         }
371 
372         //at least one AO must be checked
373         if (!aoChecked) {
374             GlobalVariables.getMessageMap().putError("AOCselectionError", RegistrationGroupConstants.MSG_ERROR_INVALID_AO_SELECTION);
375             return theForm;
376         }
377 
378         KSUifUtils.addGrowlMessageIcon(GrowlIcon.SUCCESS, ActivityOfferingConstants.MSG_INFO_AO_MOVED);
379 
380         return theForm;
381     }
382 
383 
384     public static CourseOfferingService getCourseOfferingService() {
385         return CourseOfferingResourceLoader.loadCourseOfferingService();
386     }
387 
388     public static void showDeleteClusterConfirmPage(ARGCourseOfferingManagementForm theForm) throws Exception {
389 
390         Object selectedObject = ARGUtil.getSelectedObject(theForm, "Delete");
391         if (selectedObject instanceof ActivityOfferingClusterWrapper) {
392             ActivityOfferingClusterWrapper clusterWrapper = (ActivityOfferingClusterWrapper)selectedObject;
393             theForm.setSelectedCluster(clusterWrapper);
394             theForm.setSelectedToDeleteList(clusterWrapper.getAoWrapperList());
395             theForm.setTotalAOsToBeDeleted(clusterWrapper.getAoWrapperList().size());
396         }
397     }
398 
399     public static void renameAClusterThroughDialog(ARGCourseOfferingManagementForm theForm) throws Exception {
400         Object selectedObject = ARGUtil.getSelectedObject(theForm, "Rename");
401         if (selectedObject instanceof ActivityOfferingClusterWrapper) {
402             ActivityOfferingClusterWrapper clusterWrapper = (ActivityOfferingClusterWrapper)selectedObject;
403             theForm.setSelectedCluster(clusterWrapper);
404         }
405     }
406 
407     public static void deleteClusterCascaded(ARGCourseOfferingManagementForm theForm) throws Exception {
408         ActivityOfferingClusterWrapper aoWrapper = theForm.getSelectedCluster();
409         ARGUtil.getArgServiceAdapter().deleteActivityOfferingCluster(aoWrapper.getActivityOfferingClusterId(), ContextBuilder.loadContextInfo());
410         CourseOfferingViewHelperUtil.updateCourseOfferingStateFromActivityOfferingStateChange(theForm.getCurrentCourseOfferingWrapper().getCourseOfferingInfo(), ContextBuilder.loadContextInfo());
411         ARGUtil.reloadTheCourseOfferingWithAOs_RGs_Clusters(theForm);
412     }
413 
414     public static Properties manageAO(ARGCourseOfferingManagementForm theForm, String aoId) throws Exception {
415         Properties urlParameters = new Properties();
416         urlParameters.put(KRADConstants.DISPATCH_REQUEST_PARAMETER, KRADConstants.Maintenance.METHOD_TO_CALL_EDIT);
417         urlParameters.put(ActivityOfferingConstants.ACTIVITY_OFFERING_WRAPPER_ID, aoId);
418         urlParameters.put(ActivityOfferingConstants.ACTIVITYOFFERING_COURSE_OFFERING_ID, theForm.getCurrentCourseOfferingWrapper().getCourseOfferingInfo().getId());
419         urlParameters.put(KRADConstants.DATA_OBJECT_CLASS_ATTRIBUTE, AORuleManagementWrapper.class.getName());
420         urlParameters.put(UifConstants.UrlParams.SHOW_HOME, BooleanUtils.toStringTrueFalse(false));
421         urlParameters.put("viewName", "AOAgendaManagementView");
422         urlParameters.put("refObjectId", aoId);
423 
424         return urlParameters;
425     }
426 }