Coverage Report - org.kuali.student.lum.workflow.CoursePostProcessorBase
 
Classes in this File Line Coverage Branch Coverage Complexity
CoursePostProcessorBase
0%
0/77
0%
0/42
3.333
 
 1  
 /**
 2  
  * 
 3  
  */
 4  
 package org.kuali.student.lum.workflow;
 5  
 
 6  
 import java.util.Iterator;
 7  
 import java.util.List;
 8  
 
 9  
 import javax.xml.namespace.QName;
 10  
 
 11  
 import org.apache.commons.lang.StringUtils;
 12  
 import org.kuali.rice.core.resourceloader.GlobalResourceLoader;
 13  
 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
 14  
 import org.kuali.rice.kew.postprocessor.ActionTakenEvent;
 15  
 import org.kuali.rice.kew.postprocessor.DocumentRouteLevelChange;
 16  
 import org.kuali.rice.kew.postprocessor.DocumentRouteStatusChange;
 17  
 import org.kuali.rice.kew.postprocessor.IDocumentEvent;
 18  
 import org.kuali.rice.kew.util.KEWConstants;
 19  
 import org.kuali.student.common.dto.DtoConstants;
 20  
 import org.kuali.student.common.exceptions.OperationFailedException;
 21  
 import org.kuali.student.core.proposal.dto.ProposalInfo;
 22  
 import org.kuali.student.core.statement.dto.ReqComponentInfo;
 23  
 import org.kuali.student.core.statement.dto.StatementTreeViewInfo;
 24  
 import org.kuali.student.lum.course.dto.CourseInfo;
 25  
 import org.kuali.student.lum.course.service.CourseService;
 26  
 import org.springframework.transaction.annotation.Transactional;
 27  
 
 28  
 /**
 29  
  * A base post processor class for Course document types in Workflow.
 30  
  *
 31  
  */
 32  
 @Transactional(readOnly=true, rollbackFor={Throwable.class})
 33  0
 public class CoursePostProcessorBase extends KualiStudentPostProcessorBase {
 34  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(CoursePostProcessorBase.class);
 35  
 
 36  
     private CourseService courseService;
 37  
     private CourseStateChangeServiceImpl courseStateChangeService;
 38  
     
 39  
     @Override
 40  
     protected void processWithdrawActionTaken(ActionTakenEvent actionTakenEvent, ProposalInfo proposalInfo) throws Exception {
 41  0
         LOG.info("Will set CLU state to '" + DtoConstants.STATE_SUBMITTED + "'");
 42  0
         CourseInfo courseInfo = getCourseService().getCourse(getCourseId(proposalInfo));
 43  0
         updateCourse(actionTakenEvent, DtoConstants.STATE_SUBMITTED, courseInfo);
 44  0
     }
 45  
 
 46  
     @Override
 47  
     protected boolean processCustomActionTaken(ActionTakenEvent actionTakenEvent, ActionTakenValue actionTaken, ProposalInfo proposalInfo) throws Exception {
 48  0
         String cluId = getCourseId(proposalInfo);
 49  0
         CourseInfo courseInfo = getCourseService().getCourse(cluId);
 50  
         
 51  0
         updateCourse(actionTakenEvent, null, courseInfo);
 52  0
         return true;
 53  
     }
 54  
 
 55  
     @Override
 56  
     protected boolean processCustomRouteStatusChange(DocumentRouteStatusChange statusChangeEvent, ProposalInfo proposalInfo) throws Exception {
 57  
         // update the course state if the cluState value is not null (allows for clearing of the state)
 58  0
         String courseId = getCourseId(proposalInfo);
 59  0
         String prevEndTermAtpId = proposalInfo.getAttributes().get("prevEndTerm");
 60  0
         CourseInfo courseInfo = getCourseService().getCourse(courseId);
 61  0
         String courseState = getCluStateForRouteStatus(courseInfo.getState(), statusChangeEvent.getNewRouteStatus());
 62  
         //Use the state change service to update to active and update preceding versions  
 63  0
         if(DtoConstants.STATE_ACTIVE.equals(courseState)){
 64  
                 //Change the state using the effective date as the version start date
 65  0
                 getCourseStateChangeService().changeState(courseId, courseState, prevEndTermAtpId);
 66  
         }else{
 67  0
                 updateCourse(statusChangeEvent, courseState, courseInfo);
 68  
         }
 69  0
         return true;
 70  
     }
 71  
 
 72  
     protected String getCourseId(ProposalInfo proposalInfo) throws OperationFailedException {
 73  0
         if (proposalInfo.getProposalReference().size() != 1) {
 74  0
             LOG.error("Found " + proposalInfo.getProposalReference().size() + " CLU objects linked to proposal with proposalId='" + proposalInfo.getId() + "'. Must have exactly 1 linked.");
 75  0
             throw new OperationFailedException("Found " + proposalInfo.getProposalReference().size() + " CLU objects linked to proposal with docId='" + proposalInfo.getWorkflowId() + "' and proposalId='" + proposalInfo.getId() + "'. Must have exactly 1 linked.");
 76  
         }
 77  0
         return proposalInfo.getProposalReference().get(0);
 78  
     }
 79  
 
 80  
     /**
 81  
      * @param currentCluState - the current state set on the CLU
 82  
      * @param newWorkflowStatusCode - the new route status code that is getting set on the workflow document
 83  
      * @return the CLU state to set or null if the CLU does not need it's state changed
 84  
      */
 85  
     protected String getCluStateForRouteStatus(String currentCluState, String newWorkflowStatusCode) {
 86  0
         if (StringUtils.equals(KEWConstants.ROUTE_HEADER_SAVED_CD, newWorkflowStatusCode)) {
 87  0
             return getCourseStateFromNewState(currentCluState, DtoConstants.STATE_DRAFT);
 88  0
         } else if (KEWConstants.ROUTE_HEADER_CANCEL_CD .equals(newWorkflowStatusCode)) {
 89  0
             return getCourseStateFromNewState(currentCluState, DtoConstants.STATE_NOT_APPROVED);
 90  0
         } else if (KEWConstants.ROUTE_HEADER_ENROUTE_CD.equals(newWorkflowStatusCode)) {
 91  0
             return getCourseStateFromNewState(currentCluState, DtoConstants.STATE_DRAFT);
 92  0
         } else if (KEWConstants.ROUTE_HEADER_DISAPPROVED_CD.equals(newWorkflowStatusCode)) {
 93  
             /* current requirements state that on a Withdraw (which is a KEW Disapproval) the 
 94  
              * CLU state should be submitted so no special handling required here
 95  
              */
 96  0
             return getCourseStateFromNewState(currentCluState, DtoConstants.STATE_NOT_APPROVED);
 97  0
         } else if (KEWConstants.ROUTE_HEADER_PROCESSED_CD.equals(newWorkflowStatusCode)) {
 98  0
             return getCourseStateFromNewState(currentCluState, DtoConstants.STATE_ACTIVE);
 99  0
         } else if (KEWConstants.ROUTE_HEADER_EXCEPTION_CD.equals(newWorkflowStatusCode)) {
 100  0
             return getCourseStateFromNewState(currentCluState, DtoConstants.STATE_DRAFT);
 101  
         } else {
 102  
             // no status to set
 103  0
             return null;
 104  
         }
 105  
     }
 106  
 
 107  
     /**
 108  
      * Default behavior is to return the <code>newCluState</code> variable only if it differs from the
 109  
      * <code>currentCluState</code> value. Otherwise <code>null</code> will be returned.
 110  
      */
 111  
     protected String getCourseStateFromNewState(String currentCourseState, String newCourseState) {
 112  0
         if (LOG.isInfoEnabled()) {
 113  0
             LOG.info("current CLU state is '" + currentCourseState + "' and new CLU state will be '" + newCourseState + "'");
 114  
         }
 115  0
         return getStateFromNewState(currentCourseState, newCourseState);
 116  
     }
 117  
 
 118  
     @Transactional(readOnly=false)
 119  
     protected void updateCourse(IDocumentEvent iDocumentEvent, String courseState, CourseInfo courseInfo) throws Exception {
 120  
         // only change the state if the course is not currently set to that state
 121  0
         boolean requiresSave = false;
 122  0
         if (courseState != null) {
 123  0
             if (LOG.isInfoEnabled()) {
 124  0
                 LOG.info("Setting state '" + courseState + "' on CLU with cluId='" + courseInfo.getId() + "'");
 125  
             }
 126  0
             courseInfo.setState(courseState);
 127  0
             requiresSave = true;
 128  
         }
 129  0
         if (LOG.isInfoEnabled()) {
 130  0
             LOG.info("Running preProcessCluSave with cluId='" + courseInfo.getId() + "'");
 131  
         }
 132  0
         requiresSave |= preProcessCourseSave(iDocumentEvent, courseInfo);
 133  
 
 134  0
         if (requiresSave) {
 135  0
             getCourseService().updateCourse(courseInfo);
 136  
             
 137  
             //For a newly approved course (w/no prior active versions), make the new course the current version.
 138  0
             if (DtoConstants.STATE_ACTIVE.equals(courseState) && courseInfo.getVersionInfo().getCurrentVersionStart() == null){
 139  
                     // TODO: set states of other approved courses to superseded                
 140  
                 
 141  
                     // if current version's state is not active then we can set this course as the active course
 142  
                     //if (!DtoConstants.STATE_ACTIVE.equals(getCourseService().getCourse(getCourseService().getCurrentVersion(CourseServiceConstants.COURSE_NAMESPACE_URI, courseInfo.getVersionInfo().getVersionIndId()).getId()).getState())) { 
 143  0
                             getCourseService().setCurrentCourseVersion(courseInfo.getId(), null);
 144  
                     //}
 145  
             }
 146  
             
 147  0
             List<StatementTreeViewInfo> statementTreeViewInfos = courseService.getCourseStatements(courseInfo.getId(), null, null);
 148  0
             if(statementTreeViewInfos!=null){
 149  0
                     statementTreeViewInfoStateSetter(courseInfo.getState(), statementTreeViewInfos.iterator());
 150  
                     
 151  0
                     for(Iterator<StatementTreeViewInfo> it = statementTreeViewInfos.iterator(); it.hasNext();)
 152  0
                                 courseService.updateCourseStatement(courseInfo.getId(), it.next());
 153  
             }
 154  
         }
 155  
         
 156  0
     }
 157  
 
 158  
     protected boolean preProcessCourseSave(IDocumentEvent iDocumentEvent, CourseInfo courseInfo) {
 159  0
         return false;
 160  
     }
 161  
 
 162  
     protected CourseService getCourseService() {
 163  0
         if (this.courseService == null) {
 164  0
             this.courseService = (CourseService) GlobalResourceLoader.getService(new QName("http://student.kuali.org/wsdl/course","CourseService")); 
 165  
         }
 166  0
         return this.courseService;
 167  
     }
 168  
     protected CourseStateChangeServiceImpl getCourseStateChangeService() {
 169  0
         if (this.courseStateChangeService == null) {
 170  0
             this.courseStateChangeService = new CourseStateChangeServiceImpl();
 171  0
             this.courseStateChangeService.setCourseService(getCourseService());
 172  
         }
 173  0
         return this.courseStateChangeService;
 174  
     }    
 175  
     /*
 176  
      * Recursively set state for StatementTreeViewInfo
 177  
      * TODO: We are not able to reuse the code in CourseStateUtil for dependency reason.
 178  
      */   
 179  
     public void statementTreeViewInfoStateSetter(String courseState, Iterator<StatementTreeViewInfo> itr) {
 180  0
             while(itr.hasNext()) {
 181  0
                 StatementTreeViewInfo statementTreeViewInfo = (StatementTreeViewInfo)itr.next();
 182  0
                 statementTreeViewInfo.setState(courseState);
 183  0
                 List<ReqComponentInfo> reqComponents = statementTreeViewInfo.getReqComponents();
 184  0
                 for(Iterator<ReqComponentInfo> it = reqComponents.iterator(); it.hasNext();)
 185  0
                         it.next().setState(courseState);
 186  
 
 187  0
                 statementTreeViewInfoStateSetter(courseState, statementTreeViewInfo.getStatements().iterator());
 188  0
         }
 189  0
     }
 190  
 
 191  
         @Override
 192  
         protected boolean processCustomRouteLevelChange(
 193  
                         DocumentRouteLevelChange documentRouteLevelChange,
 194  
                         ProposalInfo proposalInfo) throws Exception {
 195  
                 //Update the proposal with the new node name
 196  0
                 proposalInfo.getAttributes().put("workflowNode", documentRouteLevelChange.getNewNodeName());
 197  0
                 getProposalService().updateProposal(proposalInfo.getId(), proposalInfo);
 198  0
                 return true;
 199  
         }
 200  
 
 201  
   
 202  
     
 203  
 
 204  
 }