1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.postprocessor;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.custommonkey.xmlunit.XMLAssert;
20 import org.custommonkey.xmlunit.XMLUnit;
21 import org.junit.Test;
22 import org.kuali.rice.kew.api.KewApiConstants;
23 import org.kuali.rice.kew.api.WorkflowDocument;
24 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
25 import org.kuali.rice.kew.api.action.ActionRequestType;
26 import org.kuali.rice.kew.doctype.bo.DocumentType;
27 import org.kuali.rice.kew.framework.postprocessor.AfterProcessEvent;
28 import org.kuali.rice.kew.framework.postprocessor.DocumentLockingEvent;
29 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteLevelChange;
30 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
31 import org.kuali.rice.kew.framework.postprocessor.ProcessDocReport;
32 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
33 import org.kuali.rice.kew.service.KEWServiceLocator;
34 import org.kuali.rice.kew.test.KEWTestCase;
35 import org.kuali.rice.test.BaselineTestCase;
36 import org.springframework.transaction.TransactionStatus;
37 import org.springframework.transaction.support.TransactionCallback;
38 import org.springframework.transaction.support.TransactionTemplate;
39
40 import java.util.ArrayList;
41 import java.util.List;
42
43 import static org.junit.Assert.assertEquals;
44 import static org.junit.Assert.assertNotNull;
45 import static org.junit.Assert.assertTrue;
46 import static org.junit.Assert.fail;
47
48 @BaselineTestCase.BaselineMode(BaselineTestCase.Mode.NONE)
49 public class PostProcessorTest extends KEWTestCase {
50
51 private static final String APPLICATION_CONTENT = "<some><application>content</application></some>";
52 private static final String DOC_TITLE = "The Doc Title";
53
54 protected void loadTestData() throws Exception {
55 loadXmlFile("PostProcessorConfig.xml");
56 }
57
58
59
60
61
62
63
64
65
66
67
68 @Test public void testModifyDocumentInPostProcessor() throws Exception {
69 XMLUnit.setIgnoreWhitespace(true);
70 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "testModifyDocumentInPostProcessor");
71 document.saveDocument("");
72 assertEquals("application content should be empty initially", "", document.getApplicationContent());
73 assertTrue("Doc title should be empty initially", StringUtils.isBlank(document.getTitle()));
74
75 document.adHocToPrincipal(ActionRequestType.APPROVE, "AdHoc", "", "2002", "", true);
76 document.complete("");
77 document = WorkflowDocumentFactory.loadDocument("2002", document.getDocumentId());
78
79
80 document.approve("");
81
82 assertEquals("Should have transitioned nodes twice", 2, DocumentModifyingPostProcessor.levelChanges);
83 assertTrue("SHould have called the processed status change", DocumentModifyingPostProcessor.processedChange);
84 assertTrue("Document should be final.", document.isFinal());
85 XMLAssert.assertXMLEqual("Application content should have been sucessfully modified.", APPLICATION_CONTENT, document.getApplicationContent());
86
87
88 assertEquals("Wrong doc title", DOC_TITLE, document.getTitle());
89
90
91 assertNotNull("SHould have routed a document from the post processor.", DocumentModifyingPostProcessor.routedDocumentId);
92 document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), DocumentModifyingPostProcessor.routedDocumentId);
93 assertTrue("document should be enroute", document.isEnroute());
94 assertEquals("Document should have 1 pending request.", 1, KEWServiceLocator.getActionRequestService().findPendingByDoc(document.getDocumentId()).size());
95 assertTrue("ewestfal should have an approve request.", document.isApprovalRequested());
96 document.approve("");
97 assertTrue("Document should be final.", document.isFinal());
98 }
99
100
101
102
103
104
105
106
107
108
109 @Test public void testEmptyPostProcessor() throws Exception {
110 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "testEmptyPostProcessor");
111 document.saveDocument("");
112 assertEquals("application content should be empty initially", "", document.getApplicationContent());
113 assertTrue("Doc title should be empty initially", StringUtils.isBlank(document.getTitle()));
114
115 assertTrue("Document should be final.", document.isFinal());
116
117 DocumentType testEmptyDocType = KEWServiceLocator.getDocumentTypeService().findByName("testEmptyPostProcessor");
118 assertTrue("Post Processor should be set to 'none'", StringUtils.equals("none", testEmptyDocType.getPostProcessorName()));
119 assertTrue("Post Processor should be of type DefaultPostProcessor", testEmptyDocType.getPostProcessor() instanceof org.kuali.rice.kew.postprocessor.DefaultPostProcessor);
120 }
121
122 private static boolean shouldReturnDocumentIdsToLock = false;
123 private static String documentAId = null;
124 private static String documentBId = null;
125 private static UpdateDocumentThread updateDocumentThread = null;
126
127 protected String getPrincipalIdForName(String principalName) {
128 return KEWServiceLocator.getIdentityHelperService()
129 .getIdForPrincipalName(principalName);
130 }
131
132
133
134
135
136 @Test public void RtestGetDocumentIdsToLock() throws Exception {
137
138
139
140
141
142
143
144
145
146
147 WorkflowDocument documentB = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "TestDocumentType");
148 documentB.saveDocument("");
149 documentBId = documentB.getDocumentId();
150 updateDocumentThread = new UpdateDocumentThread(documentBId);
151
152
153 WorkflowDocument documentA = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "testGetDocumentIdsToLock");
154 documentA.adHocToPrincipal(ActionRequestType.APPROVE, "", getPrincipalIdForName("rkirkend"), "", true);
155
156 try {
157 documentA.route("");
158 fail("An exception should have been thrown as the result of an optimistic lock!");
159 } catch (Exception e) {
160 e.printStackTrace();
161 }
162
163
164
165
166
167 shouldReturnDocumentIdsToLock = true;
168
169 documentB = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "TestDocumentType");
170 documentB.saveDocument("");
171 documentBId = documentB.getDocumentId();
172 updateDocumentThread = new UpdateDocumentThread(documentBId);
173
174
175 documentA = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"), "testGetDocumentIdsToLock");
176 documentA.adHocToPrincipal(ActionRequestType.APPROVE, "", getPrincipalIdForName("rkirkend"), "", true);
177
178 documentA.route("");
179 documentA = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("rkirkend"), documentA.getDocumentId());
180 assertTrue("rkirkend should have approve request", documentA.isApprovalRequested());
181
182 }
183
184 public static class DocumentModifyingPostProcessor extends DefaultPostProcessor {
185
186 public static boolean processedChange = false;
187 public static int levelChanges = 0;
188 public static String routedDocumentId;
189
190 protected String getPrincipalIdForName(String principalName) {
191 return KEWServiceLocator.getIdentityHelperService()
192 .getIdForPrincipalName(principalName);
193 }
194
195 public ProcessDocReport doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) throws Exception {
196 if (KewApiConstants.ROUTE_HEADER_PROCESSED_CD.equals(statusChangeEvent.getNewRouteStatus())) {
197 WorkflowDocument document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), statusChangeEvent.getDocumentId());
198 document.setApplicationContent(APPLICATION_CONTENT);
199 document.setTitle(DOC_TITLE);
200 document.saveDocumentData();
201
202 WorkflowDocument ppDocument = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("user1"), "testModifyDocumentInPostProcessor");
203 routedDocumentId = ppDocument.getDocumentId();
204
205 ppDocument.adHocToPrincipal(ActionRequestType.APPROVE, "AdHoc", "", "2001", "", true);
206 ppDocument.route("");
207 processedChange = true;
208 }
209 return new ProcessDocReport(true);
210 }
211
212 public ProcessDocReport doRouteLevelChange(DocumentRouteLevelChange levelChangeEvent) throws Exception {
213 levelChanges++;
214 WorkflowDocument document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), levelChangeEvent.getDocumentId());
215 document.setTitle("Current level change: " + levelChanges);
216 document.saveDocumentData();
217 return new ProcessDocReport(true);
218 }
219
220 }
221
222 public static class GetDocumentIdsToLockPostProcessor extends DefaultPostProcessor {
223
224 protected String getPrincipalIdForName(String principalName) {
225 return KEWServiceLocator.getIdentityHelperService()
226 .getIdForPrincipalName(principalName);
227 }
228
229 @Override
230 public List<String> getDocumentIdsToLock(DocumentLockingEvent lockingEvent) throws Exception {
231 WorkflowDocument document = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), lockingEvent.getDocumentId());
232 if (shouldReturnDocumentIdsToLock) {
233 List<String> docIds = new ArrayList<String>();
234 docIds.add(documentBId);
235 return docIds;
236 }
237 return null;
238 }
239
240 @Override
241 public ProcessDocReport afterProcess(AfterProcessEvent event) throws Exception {
242 WorkflowDocument wfDocument = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("ewestfal"), event.getDocumentId());
243 if (wfDocument.isEnroute()) {
244
245 DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentBId);
246
247 new Thread(updateDocumentThread).start();
248
249 Thread.sleep(5000);
250
251 document.setDocTitle(document.getDocTitle() + "...making a change...");
252 KEWServiceLocator.getRouteHeaderService().saveRouteHeader(document);
253 }
254 return super.afterProcess(event);
255 }
256
257
258
259 }
260
261
262
263
264
265
266 private class UpdateDocumentThread implements Runnable {
267 private String documentId;
268 public UpdateDocumentThread(String documentId) {
269 this.documentId = documentId;
270 }
271 public void run() {
272 TransactionTemplate template = new TransactionTemplate(KEWServiceLocator.getPlatformTransactionManager());
273 template.execute(new TransactionCallback() {
274 public Object doInTransaction(TransactionStatus status) {
275 KEWServiceLocator.getRouteHeaderService().lockRouteHeader(documentId);
276 DocumentRouteHeaderValue document = KEWServiceLocator.getRouteHeaderService().getRouteHeader(documentId);
277
278 document.setDocTitle(document.getDocTitle() + "UDT");
279 KEWServiceLocator.getRouteHeaderService().saveRouteHeader(document);
280 return null;
281 }
282 });
283 }
284 }
285
286 }