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