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