1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.actions;
17
18 import org.apache.log4j.Logger;
19 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
20 import org.kuali.rice.kew.actionrequest.KimGroupRecipient;
21 import org.kuali.rice.kew.actionrequest.KimPrincipalRecipient;
22 import org.kuali.rice.kew.actionrequest.Recipient;
23 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
24 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
25 import org.kuali.rice.kew.api.KewApiServiceLocator;
26 import org.kuali.rice.kew.api.WorkflowRuntimeException;
27 import org.kuali.rice.kew.api.document.DocumentProcessingOptions;
28 import org.kuali.rice.kew.api.document.DocumentProcessingQueue;
29 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeIndexingQueue;
30 import org.kuali.rice.kew.api.exception.InvalidActionTakenException;
31 import org.kuali.rice.kew.engine.RouteContext;
32 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
33 import org.kuali.rice.kew.framework.postprocessor.PostProcessor;
34 import org.kuali.rice.kew.framework.postprocessor.ProcessDocReport;
35 import org.kuali.rice.kew.messaging.MessageServiceNames;
36 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
37 import org.kuali.rice.kew.service.KEWServiceLocator;
38 import org.kuali.rice.kim.api.identity.principal.PrincipalContract;
39 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
40
41 import java.util.List;
42
43
44
45
46
47
48
49
50
51
52 public abstract class ActionTakenEvent {
53
54 private static final Logger LOG = Logger.getLogger(ActionTakenEvent.class);
55
56
57
58
59 private String actionTakenCode;
60
61 protected final String annotation;
62
63 protected DocumentRouteHeaderValue routeHeader;
64
65 private final PrincipalContract principal;
66
67 private final boolean runPostProcessorLogic;
68
69 private List<String> groupIdsForPrincipal;
70
71
72 private boolean queueDocumentAfterAction = true;
73
74
75 public ActionTakenEvent(String actionTakenCode, DocumentRouteHeaderValue routeHeader, PrincipalContract principal) {
76 this(actionTakenCode, routeHeader, principal, null, true);
77 }
78
79 public ActionTakenEvent(String actionTakenCode, DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String annotation) {
80 this(actionTakenCode, routeHeader, principal, annotation, true);
81 }
82
83 public ActionTakenEvent(String actionTakenCode, DocumentRouteHeaderValue routeHeader, PrincipalContract principal, String annotation, boolean runPostProcessorLogic) {
84 this.actionTakenCode = actionTakenCode;
85 this.routeHeader = routeHeader;
86 this.principal = principal;
87 this.annotation = annotation == null ? "" : annotation;
88 this.runPostProcessorLogic = runPostProcessorLogic;
89 this.queueDocumentAfterAction = true;
90 }
91
92 public ActionRequestService getActionRequestService() {
93 return (ActionRequestService) KEWServiceLocator.getService(KEWServiceLocator.ACTION_REQUEST_SRV);
94 }
95
96 public DocumentRouteHeaderValue getRouteHeader() {
97 return routeHeader;
98 }
99
100 public void setRouteHeader(DocumentRouteHeaderValue routeHeader) {
101 this.routeHeader = routeHeader;
102 }
103
104 public PrincipalContract getPrincipal() {
105 return principal;
106 }
107
108
109
110
111
112
113
114
115 protected String getActionPerformedCode() {
116 return getActionTakenCode();
117 }
118
119
120
121
122
123 protected boolean isActionValid() {
124 return org.apache.commons.lang.StringUtils.isEmpty(validateActionRules());
125 }
126
127
128
129
130
131
132 public abstract String validateActionRules();
133 public abstract String validateActionRules(List<ActionRequestValue> actionRequests);
134
135
136
137
138
139
140
141
142 public List<ActionRequestValue> filterActionRequestsByCode(List<ActionRequestValue> actionRequests, String requestCode) {
143 return getActionRequestService().filterActionRequestsByCode(actionRequests, getPrincipal().getPrincipalId(), getGroupIdsForPrincipal(), requestCode);
144 }
145
146 protected boolean isActionCompatibleRequest(List<ActionRequestValue> requests) {
147 LOG.debug("isActionCompatibleRequest() Default method = returning true");
148 return true;
149 }
150
151 public void performAction() throws InvalidActionTakenException {
152 recordAction();
153 if (queueDocumentAfterAction) {
154 queueDocumentProcessing();
155 }
156
157 }
158
159 protected abstract void recordAction() throws InvalidActionTakenException;
160
161 public void performDeferredAction() {
162
163 }
164
165 protected void updateSearchableAttributesIfPossible() {
166
167
168 RouteContext routeContext = RouteContext.getCurrentRouteContext();
169 if (routeHeader.getDocumentType().hasSearchableAttributes() && !routeContext.isSearchIndexingRequestedForContext()) {
170 routeContext.requestSearchIndexingForContext();
171 DocumentAttributeIndexingQueue queue = KewApiServiceLocator.getDocumentAttributeIndexingQueue(routeHeader.getDocumentType().getApplicationId());
172 queue.indexDocument(getDocumentId());
173 }
174 }
175
176 protected void notifyActionTaken(ActionTakenValue actionTaken) {
177 if (!isRunPostProcessorLogic()) {
178 return;
179 }
180 if (actionTaken == null) {
181 return;
182 }
183 try {
184 LOG.debug("Notifying post processor of action taken");
185 PostProcessor postProcessor = routeHeader.getDocumentType().getPostProcessor();
186 ProcessDocReport report = postProcessor.doActionTaken(new org.kuali.rice.kew.framework.postprocessor.ActionTakenEvent(routeHeader.getDocumentId(), routeHeader.getAppDocId(), ActionTakenValue.to(actionTaken)));
187 if (!report.isSuccess()) {
188 LOG.warn(report.getMessage(), report.getProcessException());
189 throw new InvalidActionTakenException(report.getMessage());
190 }
191
192 } catch (Exception ex) {
193 processPostProcessorException(ex);
194 }
195 }
196
197 protected void notifyStatusChange(String newStatusCode, String oldStatusCode) throws InvalidActionTakenException {
198 if (!isRunPostProcessorLogic()) {
199 return;
200 }
201 DocumentRouteStatusChange statusChangeEvent = new DocumentRouteStatusChange(routeHeader.getDocumentId(), routeHeader.getAppDocId(), oldStatusCode, newStatusCode);
202 try {
203 LOG.debug("Notifying post processor of status change " + oldStatusCode + "->" + newStatusCode);
204 PostProcessor postProcessor = routeHeader.getDocumentType().getPostProcessor();
205 ProcessDocReport report = postProcessor.doRouteStatusChange(statusChangeEvent);
206 if (!report.isSuccess()) {
207 LOG.warn(report.getMessage(), report.getProcessException());
208 throw new InvalidActionTakenException(report.getMessage());
209 }
210 } catch (Exception ex) {
211 processPostProcessorException(ex);
212 }
213 }
214
215
216
217
218 protected void queueDocumentProcessing() {
219 DocumentProcessingQueue documentProcessingQueue = (DocumentProcessingQueue) MessageServiceNames.getDocumentProcessingQueue(getRouteHeader());
220 DocumentProcessingOptions options = DocumentProcessingOptions.create(isRunPostProcessorLogic(), RouteContext.getCurrentRouteContext().isSearchIndexingRequestedForContext());
221 documentProcessingQueue.processWithOptions(getDocumentId(), options);
222 }
223
224 protected ActionTakenValue saveActionTaken() {
225 return saveActionTaken(Boolean.TRUE);
226 }
227
228 protected ActionTakenValue saveActionTaken(Boolean currentInd) {
229 return saveActionTaken(currentInd, null);
230 }
231
232 protected ActionTakenValue saveActionTaken(Recipient delegator) {
233 return saveActionTaken(Boolean.TRUE, delegator);
234 }
235
236 protected ActionTakenValue saveActionTaken(Boolean currentInd, Recipient delegator) {
237 ActionTakenValue val = new ActionTakenValue();
238 val.setActionTaken(getActionTakenCode());
239 val.setAnnotation(annotation);
240 val.setDocVersion(routeHeader.getDocVersion());
241 val.setDocumentId(routeHeader.getDocumentId());
242 val.setPrincipalId(principal.getPrincipalId());
243 if (delegator instanceof KimPrincipalRecipient) {
244 val.setDelegatorPrincipalId(((KimPrincipalRecipient)delegator).getPrincipalId());
245 } else if (delegator instanceof KimGroupRecipient) {
246 val.setDelegatorGroupId(((KimGroupRecipient) delegator).getGroupId());
247 }
248
249 val.setCurrentIndicator(currentInd);
250 KEWServiceLocator.getActionTakenService().saveActionTaken(val);
251 return val;
252 }
253
254
255
256
257 protected Recipient findDelegatorForActionRequests(List actionRequests) {
258 return getActionRequestService().findDelegator(actionRequests);
259 }
260
261 public String getActionTakenCode() {
262 return actionTakenCode;
263 }
264
265 protected void setActionTakenCode(String string) {
266 actionTakenCode = string;
267 }
268
269 protected String getDocumentId() {
270 return this.routeHeader.getDocumentId();
271 }
272
273
274
275
276
277 protected boolean isRunPostProcessorLogic() {
278 return this.runPostProcessorLogic;
279 }
280
281 protected List<String> getGroupIdsForPrincipal() {
282 if (groupIdsForPrincipal == null) {
283 groupIdsForPrincipal = KimApiServiceLocator.getGroupService().getGroupIdsByPrincipalId(
284 getPrincipal().getPrincipalId());
285 }
286 return groupIdsForPrincipal;
287 }
288
289
290 public void setQueueDocumentAfterAction(boolean queueDocumentAfterAction) {
291 this.queueDocumentAfterAction = queueDocumentAfterAction;
292 }
293
294 private void processPostProcessorException(Exception e) {
295 if (e instanceof RuntimeException) {
296 throw (RuntimeException)e;
297 }
298 throw new WorkflowRuntimeException(e);
299 }
300
301
302 }