Coverage Report - org.kuali.student.lum.workflow.CourseStateChangeServiceImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
CourseStateChangeServiceImpl
0%
0/80
0%
0/56
5.143
 
 1  
 package org.kuali.student.lum.workflow;
 2  
 
 3  
 import java.util.Iterator;
 4  
 import java.util.List;
 5  
 
 6  
 import org.kuali.student.common.dto.DtoConstants;
 7  
 import org.kuali.student.common.dto.StatusInfo;
 8  
 import org.kuali.student.common.exceptions.CircularReferenceException;
 9  
 import org.kuali.student.common.exceptions.DataValidationErrorException;
 10  
 import org.kuali.student.common.exceptions.DoesNotExistException;
 11  
 import org.kuali.student.common.exceptions.InvalidParameterException;
 12  
 import org.kuali.student.common.exceptions.MissingParameterException;
 13  
 import org.kuali.student.common.exceptions.OperationFailedException;
 14  
 import org.kuali.student.common.exceptions.PermissionDeniedException;
 15  
 import org.kuali.student.common.exceptions.VersionMismatchException;
 16  
 import org.kuali.student.common.versionmanagement.dto.VersionDisplayInfo;
 17  
 import org.kuali.student.core.statement.dto.StatementTreeViewInfo;
 18  
 import org.kuali.student.lum.course.dto.CourseInfo;
 19  
 import org.kuali.student.lum.course.service.CourseService;
 20  
 import org.kuali.student.lum.course.service.CourseServiceConstants;
 21  
 import org.springframework.transaction.annotation.Transactional;
 22  
 
 23  
 @Transactional(noRollbackFor = { DoesNotExistException.class }, rollbackFor = { Throwable.class })
 24  0
 public class CourseStateChangeServiceImpl {
 25  
         private CourseService courseService;
 26  
 
 27  
         /**
 28  
          * Change the state of a course to a new state
 29  
          * 
 30  
          * @param courseId id of course
 31  
          * @param newState the new state for the course
 32  
          * @param prevEndTermAtpId the current version end date of course
 33  
          * @return
 34  
          * @throws Exception
 35  
          */
 36  
         public StatusInfo changeState(String courseId, String newState,        String prevEndTermAtpId) throws Exception {
 37  
 
 38  0
                 CourseInfo courseInfo = courseService.getCourse(courseId);
 39  
 
 40  0
                 StatusInfo ret = new StatusInfo();
 41  
                 try {
 42  0
                         if (newState.equals(DtoConstants.STATE_ACTIVE)) {
 43  0
                                 if(courseInfo.isPilotCourse()){
 44  
                                         //Pilot courses get Retired
 45  
                                         //Add required fields for Retired State
 46  0
                                         courseInfo.getAttributes().put("retirementRationale", "Pilot Course");
 47  0
                                         courseInfo.getAttributes().put("lastTermOffered", courseInfo.getEndTerm());
 48  0
                                         courseInfo.setState(DtoConstants.STATE_ACTIVE);
 49  0
                                         retireCourse(courseInfo);
 50  
                                 }else{
 51  0
                                         activateCourse(courseInfo, prevEndTermAtpId);
 52  
                                 }
 53  0
                         } else if (newState.equals(DtoConstants.STATE_RETIRED)) {
 54  0
                                 retireCourse(courseInfo);
 55  
                         }
 56  
 
 57  0
                         ret.setSuccess(new Boolean(true));
 58  0
                 } catch (Exception e) {
 59  0
                         ret.setSuccess(new Boolean(false));
 60  0
                         ret.setMessage(e.getMessage());
 61  0
                 }
 62  
 
 63  0
                 return ret;
 64  
         }
 65  
 
 66  
         /**
 67  
          * Activate a course version. Only course with a state of "Approved" can be activated.
 68  
          * 
 69  
          * @param courseToActivate
 70  
          * @param prevEndTermAtpId the end term we set on the current version
 71  
          */
 72  
         protected void activateCourse(CourseInfo courseToActivate, String prevEndTermAtpId) throws Exception{
 73  0
             CourseInfo currVerCourse = getCurrentVersionOfCourse(courseToActivate);
 74  0
             String existingState = courseToActivate.getState();
 75  0
                 String currVerState = currVerCourse.getState();
 76  0
                 boolean isCurrVer = (courseToActivate.getId().equals(currVerCourse.getId()));
 77  
                 
 78  0
                 if (existingState.equals(DtoConstants.STATE_DRAFT)) {
 79  
                         // since this is approved if isCurrVer we can assume there are no previously active versions to deal with
 80  0
                         if (isCurrVer) {
 81  
                                 // setstate for thisVerCourse and setCurrentVersion(courseId)
 82  0
                                 updateCourseVersionStates(courseToActivate, DtoConstants.STATE_ACTIVE, currVerCourse, null, true, prevEndTermAtpId);
 83  0
                         } else if (currVerState.equals(DtoConstants.STATE_ACTIVE) ||
 84  
                                         currVerState.equals(DtoConstants.STATE_SUSPENDED)) {
 85  0
                                 updateCourseVersionStates(courseToActivate, DtoConstants.STATE_ACTIVE, currVerCourse, DtoConstants.STATE_SUPERSEDED, true, prevEndTermAtpId);
 86  
                         }
 87  
                 }
 88  0
         }
 89  
         
 90  
         /**
 91  
          * Retire a course version. Only course with a state of "Active" or "Suspended" can be retired
 92  
          * 
 93  
          * @param courseToRetire the course to retire
 94  
          */
 95  
         protected void retireCourse(CourseInfo courseToRetire) throws Exception{
 96  0
             String existingState = courseToRetire.getState();                
 97  
                 
 98  0
             if (existingState.equals(DtoConstants.STATE_ACTIVE) || existingState.equals(DtoConstants.STATE_SUSPENDED)){
 99  0
                     courseToRetire.setState(DtoConstants.STATE_RETIRED);
 100  
                     
 101  0
                     courseService.updateCourse(courseToRetire);
 102  0
                         updateStatementTreeViewInfoState(courseToRetire);                    
 103  
             }
 104  0
         }
 105  
         
 106  
         /**
 107  
          * Get the current version of course from another version of course
 108  
          * 
 109  
          * @param verIndId
 110  
          */
 111  
         protected CourseInfo getCurrentVersionOfCourse(CourseInfo course)
 112  
                         throws Exception {
 113  
                 // Get version independent id of course
 114  0
                 String verIndId = course.getVersionInfo().getVersionIndId();
 115  
 
 116  
                 // Get id of current version of course given the versionindependen id
 117  0
                 VersionDisplayInfo curVerDisplayInfo = courseService.getCurrentVersion(
 118  
                                 CourseServiceConstants.COURSE_NAMESPACE_URI, verIndId);
 119  0
                 String curVerId = curVerDisplayInfo.getId();
 120  
 
 121  
                 // Return the current version of the course
 122  0
                 CourseInfo currVerCourse = courseService.getCourse(curVerId);
 123  
 
 124  0
                 return currVerCourse;
 125  
         }
 126  
 
 127  
         /**
 128  
          * Based on null values, updates states of thisVerCourse and currVerCourse
 129  
          * and sets thisVerCourse as the current version. Attempts to rollback
 130  
          * transaction on exception.
 131  
          * 
 132  
          * @param thisVerCourse
 133  
          *            this is the version that the user selected to change the state
 134  
          * @param thisVerNewState
 135  
          *            this is state that the user selected to change thisVerCourse
 136  
          *            to
 137  
          * @param currVerCourse
 138  
          *            this is the current version of the course
 139  
          *            (currentVersionStartDt <= now && currentVersionEndDt > now)
 140  
          * @param currVerNewState
 141  
          *            this is the state that we need to set the current version to.
 142  
          *            Set to null to not update the currVerCourse state.
 143  
          * @param makeCurrent
 144  
          *            if true we'll set thisVerCourse as the current version.
 145  
          * @param prevEndTermAtpId
 146  
          *            the end term for the previous version to end on
 147  
          * @throws Exception
 148  
          */
 149  
         @Transactional(readOnly = false)
 150  
         private void updateCourseVersionStates(CourseInfo thisVerCourse,
 151  
                         String thisVerNewState, CourseInfo currVerCourse,
 152  
                         String currVerNewState, boolean makeCurrent,
 153  
                         String prevEndTermAtpId) throws Exception {
 154  0
                 String thisVerPrevState = thisVerCourse.getState();
 155  
 
 156  
                 // if already current, will throw error if you try to make the current
 157  
                 // version the current version.
 158  0
                 boolean isCurrent = thisVerCourse.getId().equals(currVerCourse.getId());
 159  0
                 if(!makeCurrent || !isCurrent || !thisVerCourse.getVersionInfo().getSequenceNumber().equals(1)){
 160  0
                         makeCurrent &= !isCurrent;
 161  
                 }
 162  
 
 163  0
                 if (thisVerNewState == null) {
 164  0
                         throw new InvalidParameterException("new state cannot be null");
 165  
                 } else {
 166  0
                         thisVerCourse.setState(thisVerNewState);
 167  0
                         courseService.updateCourse(thisVerCourse);
 168  0
                         updateStatementTreeViewInfoState(thisVerCourse);
 169  
                 }
 170  
 
 171  
                 // won't get called if previous exception was thrown
 172  0
                 if (currVerNewState != null) {
 173  0
                         currVerCourse.setState(currVerNewState);
 174  0
                         if(currVerCourse.getEndTerm()==null){
 175  0
                                 currVerCourse.setEndTerm(prevEndTermAtpId);
 176  
                         }
 177  0
                         courseService.updateCourse(currVerCourse);
 178  0
                         updateStatementTreeViewInfoState(currVerCourse);
 179  
                 }
 180  
 
 181  0
                 if (makeCurrent == true) {
 182  0
                         courseService.setCurrentCourseVersion(thisVerCourse.getId(),
 183  
                                         null);
 184  
                 }
 185  
 
 186  
                 // for all draft and approved courses set the state to superseded.
 187  
                 // we should only need to evaluated versions with sequence number
 188  
                 // higher than previous active course. If the course you're
 189  
                 // activating is the current course check all versions.
 190  0
                 if (thisVerPrevState.equals(DtoConstants.STATE_APPROVED)
 191  
                                 && thisVerNewState.equals(DtoConstants.STATE_ACTIVE)) {
 192  
 
 193  0
                         List<VersionDisplayInfo> versions = courseService.getVersions(
 194  
                                         CourseServiceConstants.COURSE_NAMESPACE_URI, thisVerCourse
 195  
                                                         .getVersionInfo().getVersionIndId());
 196  0
                         Long startSeq = new Long(1);
 197  
 
 198  0
                         if (!isCurrent && (currVerCourse.getId() != thisVerCourse.getId())) {
 199  0
                                 startSeq = currVerCourse.getVersionInfo().getSequenceNumber() + 1;
 200  
                         }
 201  
 
 202  0
                         for (VersionDisplayInfo versionInfo : versions) {
 203  0
                                 if (versionInfo.getSequenceNumber() >= startSeq) {
 204  0
                                         CourseInfo otherCourse = courseService
 205  
                                                         .getCourse(versionInfo.getId());
 206  0
                                         if (otherCourse.getState().equals(
 207  
                                                         DtoConstants.STATE_APPROVED)
 208  
                                                         || otherCourse.getState().equals(
 209  
                                                                         DtoConstants.STATE_SUBMITTED)
 210  
                                                         || otherCourse.getState().equals(
 211  
                                                                         DtoConstants.STATE_DRAFT)) {
 212  0
                                                 otherCourse.setState(DtoConstants.STATE_SUPERSEDED);
 213  0
                                                 courseService.updateCourse(otherCourse);
 214  0
                                                 updateStatementTreeViewInfoState(otherCourse);
 215  
                                         }
 216  0
                                 }
 217  
                         }
 218  
                 }
 219  
 
 220  0
         }
 221  
 
 222  
         public void setCourseService(CourseService courseService) {
 223  0
                 this.courseService = courseService;
 224  0
         }
 225  
 
 226  
         /**
 227  
          * This method will load all the statements in a course from the course web
 228  
          * service, recursively update the state of each statement in the statement
 229  
          * tree, and save the update statements back to the web service.
 230  
          * 
 231  
          * 
 232  
          * @param courseInfo
 233  
          *            The course to update (call setState() in this object to set
 234  
          *            the state)
 235  
          * @throws DoesNotExistException
 236  
          * @throws InvalidParameterException
 237  
          * @throws MissingParameterException
 238  
          * @throws OperationFailedException
 239  
          * @throws PermissionDeniedException
 240  
          * @throws DataValidationErrorException
 241  
          * @throws CircularReferenceException
 242  
          * @throws VersionMismatchException
 243  
          */
 244  
         public void updateStatementTreeViewInfoState(CourseInfo courseInfo)
 245  
                         throws DoesNotExistException, InvalidParameterException,
 246  
                         MissingParameterException, OperationFailedException,
 247  
                         PermissionDeniedException, DataValidationErrorException,
 248  
                         CircularReferenceException, VersionMismatchException {
 249  
 
 250  
                 // Call course web service to get all requirements/statements for this
 251  
                 // course
 252  0
                 List<StatementTreeViewInfo> statementTreeViewInfos = courseService
 253  
                                 .getCourseStatements(courseInfo.getId(), null, null);
 254  
 
 255  
                 // Recursively update state on all requirements/statements in the tree
 256  0
                 for (Iterator<StatementTreeViewInfo> it = statementTreeViewInfos
 257  0
                                 .iterator(); it.hasNext();)
 258  0
                         StatementUtil.updateStatementTreeViewInfoState(courseInfo
 259  
                                         .getState(), it.next());
 260  
 
 261  
                 // Call the course web service and update the requirement/statement tree
 262  
                 // with the new state
 263  0
                 for (Iterator<StatementTreeViewInfo> it = statementTreeViewInfos
 264  0
                                 .iterator(); it.hasNext();)
 265  0
                         courseService.updateCourseStatement(courseInfo.getId(), it.next());
 266  0
         }
 267  
 
 268  
 }