001 /**
002 * Copyright 2005-2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.kew.engine.node.hierarchyrouting;
017
018 import static org.junit.Assert.assertEquals;
019 import static org.junit.Assert.assertNotNull;
020 import static org.junit.Assert.assertNull;
021 import static org.junit.Assert.assertTrue;
022
023 import java.io.StringReader;
024 import java.util.List;
025
026 import javax.xml.parsers.DocumentBuilderFactory;
027
028 import org.junit.Test;
029 import org.kuali.rice.kew.api.WorkflowDocument;
030 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
031 import org.kuali.rice.kew.api.exception.WorkflowException;
032 import org.kuali.rice.kew.engine.node.hierarchyrouting.HierarchyProvider.Stop;
033 import org.kuali.rice.kew.engine.node.hierarchyrouting.SimpleHierarchyProvider.SimpleStop;
034 import org.kuali.rice.kew.service.KEWServiceLocator;
035 import org.kuali.rice.kew.test.KEWTestCase;
036 import org.kuali.rice.kew.test.TestUtilities;
037 import org.w3c.dom.Document;
038 import org.xml.sax.InputSource;
039
040 /**
041 * Tests HeirarchyRoutingNode
042 * @author Kuali Rice Team (rice.collab@kuali.org)
043 *
044 */
045 public class HierarchyRoutingNodeTest extends KEWTestCase {
046
047 private static final String HIERARCHY =
048 "<stop id=\"root\" type=\"user\" recipient=\"dewey\">" +
049 "<stop id=\"child1\" type=\"user\" recipient=\"user3\">" +
050 "<stop id=\"child1-1\" type=\"user\" recipient=\"user2\"/>" +
051 "<stop id=\"child1-2\" type=\"user\" recipient=\"user1\"/>" +
052 "</stop>" +
053 "<stop id=\"child2\" type=\"user\" recipient=\"quickstart\">" +
054 "<stop id=\"child2-1\" type=\"user\" recipient=\"temay\"/>" +
055 "<stop id=\"child2-2\" type=\"user\" recipient=\"jhopf\"/>" +
056 "</stop>" +
057 "</stop>";
058 private static final String HIERARCHY_UPDATED =
059 "<stop id=\"root\" type=\"user\" recipient=\"dewey\">" +
060 "<stop id=\"child1\" type=\"user\" recipient=\"user3\">" +
061 "<stop id=\"child1-1\" type=\"user\" recipient=\"user2\"/>" +
062 "<stop id=\"child1-2\" type=\"user\" recipient=\"user1\"/>" +
063 "<stop id=\"child1-3\" type=\"user\" recipient=\"delyea\"/>" +
064 "</stop>" +
065 "<stop id=\"child2\" type=\"user\" recipient=\"quickstart\">" +
066 "<stop id=\"child2-1\" type=\"user\" recipient=\"temay\"/>" +
067 "<stop id=\"child2-2\" type=\"user\" recipient=\"jhopf\"/>" +
068 "<stop id=\"child2-3\" type=\"user\" recipient=\"pzhang\"/>" +
069 "</stop>" +
070 "<stop id=\"child3\" type=\"user\" recipient=\"shenl\"/>" +
071 "</stop>";
072
073 protected void assertStop(HierarchyProvider provider, String name, String parentName, String[] childNames) {
074 Stop stop = provider.getStopByIdentifier(name);
075 assertNotNull(stop);
076 if (parentName == null) {
077 assertNull(provider.getParent(stop));
078 } else {
079 Stop parent = provider.getStopByIdentifier(parentName);
080 assertNotNull(parent);
081 assertEquals(parent, ((SimpleStop) stop).parent);
082 }
083 assertEquals(childNames.length, ((SimpleStop) stop).children.size());
084 List<SimpleStop> children = ((SimpleStop) stop).children;
085 for (String childName: childNames) {
086 Stop child = provider.getStopByIdentifier(childName);
087 assertTrue(children.contains(child));
088 }
089 }
090
091 @Test
092 public void testParseHierarchy() throws Exception {
093 Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(HIERARCHY)));
094 SimpleHierarchyProvider provider = new SimpleHierarchyProvider();
095 provider.init(doc.getDocumentElement());
096
097 assertStop(provider, "root", null, new String[] { "child1", "child2" });
098
099 assertStop(provider, "child1", "root", new String[] { "child1-1", "child1-2" });
100 assertStop(provider, "child1-1", "child1", new String[] { });
101 assertStop(provider, "child1-2", "child1", new String[] { });
102
103 assertStop(provider, "child2", "root", new String[] { "child2-1", "child2-2" });
104 assertStop(provider, "child2-1", "child2", new String[] { });
105 assertStop(provider, "child2-2", "child2", new String[] { });
106
107 List<Stop> leaves = provider.getLeafStops(null);
108 assertEquals(4, leaves.size());
109 assertTrue(leaves.contains(provider.getStopByIdentifier("child1-1")));
110 assertTrue(leaves.contains(provider.getStopByIdentifier("child1-2")));
111 assertTrue(leaves.contains(provider.getStopByIdentifier("child2-1")));
112 assertTrue(leaves.contains(provider.getStopByIdentifier("child2-2")));
113 }
114
115 @Test
116 public void testHierarchyRoutingNode() throws WorkflowException {
117 loadXmlFile("HierarchyRoutingNodeConfig.xml");
118
119 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("arh14"), "HierarchyDocType");
120
121
122 doc.setApplicationContent(HIERARCHY);
123 doc.route("initial route");
124
125 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user1", "temay", "jhopf" }, true);
126 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "quickstart", "dewey" }, false);
127
128 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), doc.getDocumentId());
129 doc.approve("approving as user2");
130
131 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay", "jhopf" }, true);
132 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user3", "quickstart", "dewey" }, false);
133
134 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), doc.getDocumentId());
135 doc.approve("approving as jhopf");
136
137 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay" }, true);
138 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "jhopf", "user2", "user3", "quickstart", "dewey" }, false);
139
140 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user1"), doc.getDocumentId());
141 doc.approve("approving as user1");
142
143 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay" }, true);
144 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
145
146 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("temay"), doc.getDocumentId());
147 doc.approve("approving as temay");
148
149 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "quickstart" }, true);
150 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "temay", "user1", "jhopf", "user2", "dewey" }, false);
151
152 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user3"), doc.getDocumentId());
153 doc.approve("approving as user3");
154
155 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "quickstart" }, true);
156 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay", "user1", "jhopf", "user2", "dewey" }, false);
157
158 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("quickstart"), doc.getDocumentId());
159 doc.approve("approving as quickstart");
160
161 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "dewey" }, true);
162 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay", "user1", "jhopf", "user2", "quickstart" }, false);
163
164
165 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("dewey"), doc.getDocumentId());
166 doc.approve("approving as dewey");
167
168 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "dewey", "user3", "temay", "user1", "jhopf", "user2", "quickstart" }, false);
169
170 assertTrue(doc.isFinal());
171 }
172
173 @Test
174 public void testHierarchyRoutingNodeUnevenApproval() throws WorkflowException {
175 loadXmlFile("HierarchyRoutingNodeConfig.xml");
176
177 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("arh14"), "HierarchyDocType");
178
179 doc.setApplicationContent(HIERARCHY);
180 doc.route("initial route");
181
182 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user1", "temay", "jhopf" }, true);
183 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "quickstart", "dewey" }, false);
184
185 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), doc.getDocumentId());
186 doc.approve("approving as user2");
187
188 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay", "jhopf" }, true);
189 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user3", "quickstart", "dewey" }, false);
190
191 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), doc.getDocumentId());
192 doc.approve("approving as jhopf");
193
194 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay" }, true);
195 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "jhopf", "user2", "user3", "quickstart", "dewey" }, false);
196
197 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user1"), doc.getDocumentId());
198 doc.approve("approving as user1");
199
200 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay" }, true);
201 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
202
203 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user3"), doc.getDocumentId());
204 doc.approve("approving as user3");
205
206 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "temay" }, true);
207 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "user1", "jhopf", "user2", "dewey" }, false);
208
209 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("temay"), doc.getDocumentId());
210 doc.approve("approving as temay");
211
212 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "quickstart" }, true);
213 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay", "user1", "jhopf", "user2", "dewey" }, false);
214
215 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("quickstart"), doc.getDocumentId());
216 doc.approve("approving as quickstart");
217
218 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "dewey" }, true);
219 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay", "user1", "jhopf", "user2", "quickstart" }, false);
220
221 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("dewey"), doc.getDocumentId());
222 doc.approve("approving as dewey");
223
224 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "dewey", "user3", "temay", "user1", "jhopf", "user2", "quickstart" }, false);
225
226 assertTrue(doc.isFinal());
227 }
228
229 @Test
230 public void testHierarchyRoutingNodeUnevenApprovalExtraStops() throws WorkflowException {
231 loadXmlFile("HierarchyRoutingNodeConfig.xml");
232
233 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("arh14"), "HierarchyDocType");
234
235 doc.setApplicationContent(HIERARCHY);
236 doc.route("initial route");
237
238 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user1", "temay", "jhopf" }, true);
239 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "quickstart", "dewey" }, false);
240
241 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), doc.getDocumentId());
242 doc.approve("approving as user2");
243
244 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay", "jhopf" }, true);
245 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user3", "quickstart", "dewey" }, false);
246
247 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), doc.getDocumentId());
248 doc.approve("approving as jhopf");
249
250 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay" }, true);
251 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "jhopf", "user2", "user3", "quickstart", "dewey" }, false);
252
253 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user1"), doc.getDocumentId());
254 doc.setApplicationContent(HIERARCHY_UPDATED);
255 doc.approve("approving as user1");
256
257 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay", "delyea", "pzhang", "shenl" }, true);
258 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
259
260 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user3"), doc.getDocumentId());
261 doc.approve("approving as user3");
262
263 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "temay", "delyea", "pzhang", "shenl" }, true);
264 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "user1", "jhopf", "user2", "dewey" }, false);
265
266 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("temay"), doc.getDocumentId());
267 doc.approve("approving as temay");
268
269 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "delyea", "pzhang", "shenl" }, true);
270 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay", "user1", "jhopf", "user2", "dewey", "quickstart" }, false);
271
272 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("delyea"), doc.getDocumentId());
273 doc.approve("approving as delyea");
274
275 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "pzhang", "shenl" }, true);
276 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "delyea", "temay", "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
277
278 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user3"), doc.getDocumentId());
279 doc.approve("approving as user3");
280
281 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "pzhang", "shenl" }, true);
282 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "delyea", "temay", "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
283
284 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("pzhang"), doc.getDocumentId());
285 doc.approve("approving as pzhang");
286
287 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "quickstart", "shenl" }, true);
288 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "pzhang", "delyea", "temay", "user1", "jhopf", "user2", "dewey" }, false);
289
290 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("quickstart"), doc.getDocumentId());
291 doc.approve("approving as quickstart");
292
293 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "shenl" }, true);
294 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "pzhang", "delyea", "temay", "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
295
296 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("shenl"), doc.getDocumentId());
297 doc.approve("approving as shenl");
298
299 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "dewey" }, true);
300 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "pzhang", "delyea", "temay", "user1", "jhopf", "user2", "quickstart", "shenl" }, false);
301
302 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("dewey"), doc.getDocumentId());
303 doc.approve("approving as dewey");
304
305 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "shenl", "dewey", "pzhang", "delyea", "user3", "temay", "user1", "jhopf", "user2", "quickstart" }, false);
306
307 assertTrue(doc.isFinal());
308 }
309
310 @Test
311 public void testHierarchyRoutingNodeUnevenApprovalDisapprove() throws WorkflowException {
312 loadXmlFile("HierarchyRoutingNodeConfig.xml");
313
314 WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("arh14"), "HierarchyDocType");
315
316 doc.setApplicationContent(HIERARCHY);
317 doc.route("initial route");
318
319 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user1", "temay", "jhopf" }, true);
320 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "quickstart", "dewey" }, false);
321
322 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), doc.getDocumentId());
323 doc.approve("approving as user2");
324
325 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay", "jhopf" }, true);
326 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user2", "user3", "quickstart", "dewey" }, false);
327
328 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), doc.getDocumentId());
329 doc.approve("approving as jhopf");
330
331 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "temay" }, true);
332 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "jhopf", "user2", "user3", "quickstart", "dewey" }, false);
333
334 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user1"), doc.getDocumentId());
335 doc.approve("approving as user1");
336
337 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay" }, true);
338 TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
339
340 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user3"), doc.getDocumentId());
341 doc.disapprove("disapproving as user3");
342
343 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("arh14"), doc.getDocumentId());
344
345 //TestUtilities.assertApprovals(doc.getDocumentId(), new String[] { "user3", "temay", "user1", "jhopf", "user2", "quickstart", "dewey" }, false);
346
347 assertTrue(doc.isDisapproved());
348
349 TestUtilities.logActionRequests(doc.getDocumentId());
350
351 // these are ok, these are the ACKs for the previous approvers
352 int numActionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(doc.getDocumentId()).size();
353 assertEquals("Incorrect number of action requests", 4, numActionRequests);
354 int numActionItems = KEWServiceLocator.getActionListService().findByDocumentId(doc.getDocumentId()).size();
355 assertEquals("Incorrect number of action items.", 4, numActionItems);
356
357 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), doc.getDocumentId());
358 doc.acknowledge("acknowledging disapproval as user2");
359 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("jhopf"), doc.getDocumentId());
360 doc.acknowledge("acknowledging disapproval as jhopf");
361 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user1"), doc.getDocumentId());
362 doc.acknowledge("acknowledging disapproval as user1");
363 doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("arh14"), doc.getDocumentId());
364 doc.acknowledge("acknowledging disapproval as arh14");
365
366 assertTrue(doc.isDisapproved());
367
368 numActionRequests = KEWServiceLocator.getActionRequestService().findPendingByDoc(doc.getDocumentId()).size();
369 assertEquals("Incorrect number of action requests", 0, numActionRequests);
370 numActionItems = KEWServiceLocator.getActionListService().findByDocumentId(doc.getDocumentId()).size();
371 assertEquals("Incorrect number of action items.", 0, numActionItems);
372
373 }
374 }