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 }