1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.student.lum.workflow;
17 import java.util.List;
18
19 import javax.xml.namespace.QName;
20
21 import org.apache.commons.lang.StringUtils;
22 import org.kuali.rice.core.resourceloader.GlobalResourceLoader;
23 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
24 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
25 import org.kuali.rice.kew.dto.ActionRequestDTO;
26 import org.kuali.rice.kew.postprocessor.ActionTakenEvent;
27 import org.kuali.rice.kew.postprocessor.AfterProcessEvent;
28 import org.kuali.rice.kew.postprocessor.BeforeProcessEvent;
29 import org.kuali.rice.kew.postprocessor.DeleteEvent;
30 import org.kuali.rice.kew.postprocessor.DocumentLockingEvent;
31 import org.kuali.rice.kew.postprocessor.DocumentRouteLevelChange;
32 import org.kuali.rice.kew.postprocessor.DocumentRouteStatusChange;
33 import org.kuali.rice.kew.postprocessor.IDocumentEvent;
34 import org.kuali.rice.kew.postprocessor.PostProcessor;
35 import org.kuali.rice.kew.postprocessor.ProcessDocReport;
36 import org.kuali.rice.kew.service.KEWServiceLocator;
37 import org.kuali.rice.kew.service.WorkflowDocument;
38 import org.kuali.rice.kew.util.KEWConstants;
39 import org.kuali.rice.kim.bo.entity.dto.KimPrincipalInfo;
40 import org.kuali.rice.kim.bo.types.dto.AttributeSet;
41 import org.kuali.rice.kim.service.KIMServiceLocator;
42 import org.kuali.rice.student.StudentWorkflowConstants;
43 import org.kuali.rice.student.bo.KualiStudentKimAttributes;
44 import org.kuali.student.common.exceptions.OperationFailedException;
45 import org.kuali.student.common.rice.StudentIdentityConstants;
46 import org.kuali.student.core.proposal.ProposalConstants;
47 import org.kuali.student.core.proposal.dto.ProposalInfo;
48 import org.kuali.student.core.proposal.service.ProposalService;
49 public class KualiStudentPostProcessorBase implements PostProcessor{
50 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiStudentPostProcessorBase.class);
51
52 private ProposalService proposalService;
53
54 public ProcessDocReport afterProcess(AfterProcessEvent arg0) throws Exception {
55 return new ProcessDocReport(true);
56 }
57
58 public ProcessDocReport beforeProcess(BeforeProcessEvent arg0) throws Exception {
59 return new ProcessDocReport(true);
60 }
61
62 public ProcessDocReport doActionTaken(ActionTakenEvent actionTakenEvent) throws Exception {
63 ActionTakenValue actionTaken = KEWServiceLocator.getActionTakenService().findByActionTakenId(actionTakenEvent.getActionTaken().getActionTakenId());
64 if (actionTaken == null) {
65 if (LOG.isInfoEnabled()) {
66 LOG.info("Could not find valid ActionTakenValue for doc id '" + actionTakenEvent.getRouteHeaderId() + "'" +
67 ((actionTakenEvent.getActionTaken() == null) ? "" : " for action: " + actionTakenEvent.getActionTaken().getActionTakenLabel()));
68 }
69 actionTaken = actionTakenEvent.getActionTaken();
70 }
71 boolean success = true;
72
73 if (!StringUtils.equals(KEWConstants.ROUTE_HEADER_SAVED_CD, actionTaken.getActionTaken())) {
74 ProposalInfo proposalInfo = getProposalService().getProposalByWorkflowId(actionTakenEvent.getRouteHeaderId().toString());
75 if (actionTaken == null) {
76 throw new OperationFailedException("No action taken found for document id " + actionTakenEvent.getRouteHeaderId());
77 }
78 if (StringUtils.equals(KEWConstants.ACTION_TAKEN_SU_DISAPPROVED_CD, actionTaken.getActionTaken())) {
79
80 processSuperUserDisapproveActionTaken(actionTakenEvent, actionTaken, proposalInfo);
81 }
82
83 else if (!StringUtils.equals(KEWConstants.ACTION_TAKEN_ADHOC_REVOKED_CD, actionTaken.getActionTaken())) {
84 for (ActionRequestValue actionRequest : actionTaken.getActionRequests()) {
85 if (actionRequest.isAdHocRequest() && actionRequest.isUserRequest()) {
86 processActionTakenOnAdhocRequest(actionTakenEvent, actionRequest);
87 }
88 }
89 }
90 success = processCustomActionTaken(actionTakenEvent, actionTaken, proposalInfo);
91 } else {
92 success = processCustomSaveActionTaken(actionTakenEvent, actionTaken);
93 }
94 return new ProcessDocReport(success);
95 }
96
97 protected boolean processCustomActionTaken(ActionTakenEvent actionTakenEvent, ActionTakenValue actionTaken, ProposalInfo proposalInfo) throws Exception {
98
99 return true;
100 }
101
102 protected boolean processCustomSaveActionTaken(ActionTakenEvent actionTakenEvent, ActionTakenValue actionTaken) throws Exception {
103
104 return true;
105 }
106
107 protected void processActionTakenOnAdhocRequest(ActionTakenEvent actionTakenEvent, ActionRequestValue actionRequestValue) throws Exception {
108 WorkflowDocument doc = new WorkflowDocument(getPrincipalIdForSystemUser(), actionTakenEvent.getRouteHeaderId());
109 LOG.info("Clearing EDIT permissions added via adhoc requests to principal id: " + actionRequestValue.getPrincipalId());
110 removeEditAdhocPermissions(actionRequestValue.getPrincipalId(), doc);
111 }
112
113 protected void processSuperUserDisapproveActionTaken(ActionTakenEvent actionTakenEvent, ActionTakenValue actionTaken, ProposalInfo proposalInfo) throws Exception {
114 LOG.info("Action taken was 'Super User Disapprove' which is a 'Withdraw' in Kuali Student");
115 LOG.info("Will set proposal state to '" + ProposalConstants.PROPOSAL_STATE_WITHDRAWN + "'");
116 updateProposal(actionTakenEvent, ProposalConstants.PROPOSAL_STATE_WITHDRAWN, proposalInfo);
117 processWithdrawActionTaken(actionTakenEvent, proposalInfo);
118 }
119
120 protected void processWithdrawActionTaken(ActionTakenEvent actionTakenEvent, ProposalInfo proposalInfo) throws Exception {
121
122 }
123
124 public ProcessDocReport doDeleteRouteHeader(DeleteEvent arg0) throws Exception {
125 return new ProcessDocReport(true);
126 }
127
128 public ProcessDocReport doRouteLevelChange(DocumentRouteLevelChange documentRouteLevelChange) throws Exception {
129 ProposalInfo proposalInfo = getProposalService().getProposalByWorkflowId(documentRouteLevelChange.getRouteHeaderId().toString());
130
131
132 if (StringUtils.equals(StudentWorkflowConstants.DEFAULT_WORKFLOW_DOCUMENT_START_NODE_NAME,documentRouteLevelChange.getOldNodeName())) {
133
134 WorkflowDocument doc = new WorkflowDocument(getPrincipalIdForSystemUser(), documentRouteLevelChange.getRouteHeaderId());
135 for (ActionRequestDTO actionRequestDTO : doc.getActionRequests()) {
136 if (actionRequestDTO.isAdHocRequest() && actionRequestDTO.isUserRequest() &&
137 StringUtils.equals(documentRouteLevelChange.getOldNodeName(),actionRequestDTO.getNodeName())) {
138 LOG.info("Clearing EDIT permissions added via adhoc requests to principal id: " + actionRequestDTO.getPrincipalId());
139 removeEditAdhocPermissions(actionRequestDTO.getPrincipalId(), doc);
140 }
141 }
142 }
143 else {
144 LOG.warn("Will not clear any permissions added via adhoc requests");
145 }
146 boolean success = processCustomRouteLevelChange(documentRouteLevelChange, proposalInfo);
147 return new ProcessDocReport(success);
148 }
149
150 protected boolean processCustomRouteLevelChange(DocumentRouteLevelChange documentRouteLevelChange, ProposalInfo proposalInfo) throws Exception {
151
152 return true;
153 }
154
155 public ProcessDocReport doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) throws Exception {
156 boolean success = true;
157
158 if (StringUtils.equals(KEWConstants.ROUTE_HEADER_INITIATED_CD, statusChangeEvent.getOldRouteStatus()) &&
159 StringUtils.equals(KEWConstants.ROUTE_HEADER_SAVED_CD, statusChangeEvent.getNewRouteStatus())) {
160
161 success = processCustomRouteStatusSavedStatusChange(statusChangeEvent);
162 } else {
163 ProposalInfo proposalInfo = getProposalService().getProposalByWorkflowId(statusChangeEvent.getRouteHeaderId().toString());
164
165
166 String proposalState = getProposalStateForRouteStatus(proposalInfo.getState(), statusChangeEvent.getNewRouteStatus());
167 updateProposal(statusChangeEvent, proposalState, proposalInfo);
168 success = processCustomRouteStatusChange(statusChangeEvent, proposalInfo);
169 }
170 return new ProcessDocReport(success);
171 }
172
173 protected boolean processCustomRouteStatusChange(DocumentRouteStatusChange statusChangeEvent, ProposalInfo proposalInfo) throws Exception {
174
175 return true;
176 }
177
178 protected boolean processCustomRouteStatusSavedStatusChange(DocumentRouteStatusChange statusChangeEvent) throws Exception {
179
180 return true;
181 }
182
183 public List<Long> getDocumentIdsToLock(DocumentLockingEvent arg0) throws Exception {
184 return null;
185 }
186
187
188
189
190
191
192 protected String getProposalStateForRouteStatus(String currentProposalState, String newWorkflowStatusCode) {
193 if (StringUtils.equals(ProposalConstants.PROPOSAL_STATE_WITHDRAWN, currentProposalState)) {
194
195 return null;
196 }
197 if (StringUtils.equals(KEWConstants.ROUTE_HEADER_SAVED_CD, newWorkflowStatusCode)) {
198 return getProposalStateFromNewState(currentProposalState, ProposalConstants.PROPOSAL_STATE_SAVED);
199 } else if (KEWConstants.ROUTE_HEADER_ENROUTE_CD.equals(newWorkflowStatusCode)) {
200 return getProposalStateFromNewState(currentProposalState, ProposalConstants.PROPOSAL_STATE_ENROUTE);
201 } else if (KEWConstants.ROUTE_HEADER_CANCEL_CD .equals(newWorkflowStatusCode)) {
202 return getProposalStateFromNewState(currentProposalState, ProposalConstants.PROPOSAL_STATE_CANCELLED);
203 } else if (KEWConstants.ROUTE_HEADER_DISAPPROVED_CD.equals(newWorkflowStatusCode)) {
204 return getProposalStateFromNewState(currentProposalState, ProposalConstants.PROPOSAL_STATE_REJECTED);
205 } else if (KEWConstants.ROUTE_HEADER_PROCESSED_CD.equals(newWorkflowStatusCode)) {
206 return getProposalStateFromNewState(currentProposalState, ProposalConstants.PROPOSAL_STATE_APPROVED);
207 } else if (KEWConstants.ROUTE_HEADER_EXCEPTION_CD.equals(newWorkflowStatusCode)) {
208 return getProposalStateFromNewState(currentProposalState, ProposalConstants.PROPOSAL_STATE_EXCEPTION);
209 } else {
210
211 return null;
212 }
213 }
214
215
216
217
218
219 protected String getProposalStateFromNewState(String currentProposalState, String newProposalState) {
220 if (LOG.isInfoEnabled()) {
221 LOG.info("current proposal state is '" + currentProposalState + "' and new proposal state will be '" + newProposalState + "'");
222 }
223 return getStateFromNewState(currentProposalState, newProposalState);
224 }
225
226
227
228
229
230 protected String getStateFromNewState(String currentState, String newState) {
231 if (StringUtils.equals(currentState, newState)) {
232 if (LOG.isInfoEnabled()) {
233 LOG.info("returning null as current state and new state are both '" + currentState + "'");
234 }
235 return null;
236 }
237 return newState;
238 }
239
240 protected void removeEditAdhocPermissions(String principalId, WorkflowDocument doc) {
241 AttributeSet qualifications = new AttributeSet();
242 qualifications.put(KualiStudentKimAttributes.DOCUMENT_TYPE_NAME,doc.getDocumentType());
243 qualifications.put(KualiStudentKimAttributes.QUALIFICATION_DATA_ID,doc.getAppDocId());
244 KIMServiceLocator.getRoleManagementService().removePrincipalFromRole(principalId, StudentWorkflowConstants.ROLE_NAME_ADHOC_EDIT_PERMISSIONS_ROLE_NAMESPACE, StudentWorkflowConstants.ROLE_NAME_ADHOC_EDIT_PERMISSIONS_ROLE_NAME, qualifications);
245 }
246
247 protected void removeCommentAdhocPermissions(String roleNamespace, String roleName, String principalId, WorkflowDocument doc) {
248 AttributeSet qualifications = new AttributeSet();
249 qualifications.put(KualiStudentKimAttributes.DOCUMENT_TYPE_NAME,doc.getDocumentType());
250 qualifications.put(KualiStudentKimAttributes.QUALIFICATION_DATA_ID,doc.getAppDocId());
251 KIMServiceLocator.getRoleManagementService().removePrincipalFromRole(principalId, StudentWorkflowConstants.ROLE_NAME_ADHOC_ADD_COMMENT_PERMISSIONS_ROLE_NAMESPACE, StudentWorkflowConstants.ROLE_NAME_ADHOC_ADD_COMMENT_PERMISSIONS_ROLE_NAME, qualifications);
252 }
253
254 protected String getPrincipalIdForSystemUser() {
255 KimPrincipalInfo principal = KIMServiceLocator.getIdentityManagementService().getPrincipalByPrincipalName(StudentIdentityConstants.SYSTEM_USER_PRINCIPAL_NAME);
256 if (principal == null) {
257 throw new RuntimeException("Cannot find Principal for principal name: " + StudentIdentityConstants.SYSTEM_USER_PRINCIPAL_NAME);
258 }
259 return principal.getPrincipalId();
260 }
261
262 protected void updateProposal(IDocumentEvent iDocumentEvent, String proposalState, ProposalInfo proposalInfo) throws Exception {
263 if (LOG.isInfoEnabled()) {
264 LOG.info("Setting state '" + proposalState + "' on Proposal with docId='" + proposalInfo.getWorkflowId() + "' and proposalId='" + proposalInfo.getId() + "'");
265 }
266 boolean requiresSave = false;
267 if (proposalState != null) {
268 proposalInfo.setState(proposalState);
269 requiresSave = true;
270 }
271 requiresSave |= preProcessProposalSave(iDocumentEvent, proposalInfo);
272 if (requiresSave) {
273 getProposalService().updateProposal(proposalInfo.getId(), proposalInfo);
274 }
275 }
276
277 protected boolean preProcessProposalSave(IDocumentEvent iDocumentEvent, ProposalInfo proposalInfo) {
278 return false;
279 }
280
281 protected ProposalService getProposalService() {
282 if (this.proposalService == null) {
283 this.proposalService = (ProposalService) GlobalResourceLoader.getService(new QName("http://student.kuali.org/wsdl/proposal","ProposalService"));
284 }
285 return this.proposalService;
286 }
287
288 }