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 */ 016package org.kuali.rice.kew.rule; 017 018import org.apache.log4j.Logger; 019import org.junit.Test; 020import org.kuali.rice.core.api.CoreApiServiceLocator; 021import org.kuali.rice.core.api.config.property.ConfigContext; 022import org.kuali.rice.core.api.util.xml.XmlException; 023import org.kuali.rice.kew.batch.KEWXmlDataLoader; 024import org.kuali.rice.kew.exception.WorkflowServiceErrorException; 025import org.kuali.rice.kew.rule.service.RuleServiceInternal; 026import org.kuali.rice.kew.service.KEWServiceLocator; 027import org.kuali.rice.kew.test.KEWTestCase; 028import org.kuali.rice.kew.test.TestUtilities; 029import org.kuali.rice.kew.api.KewApiConstants; 030import org.kuali.rice.kew.xml.RuleXmlParser; 031 032import java.io.IOException; 033import java.io.InputStream; 034import java.util.ArrayList; 035import java.util.List; 036 037import static org.junit.Assert.*; 038 039public class RuleXmlParserTest extends KEWTestCase { 040 private static final Logger LOG = Logger.getLogger(RuleXmlParserTest.class); 041 042 protected void loadTestData() throws Exception { 043 loadXmlFile("RouteTemplateConfig.xml"); 044 loadXmlFile("DuplicateRuleToImport.xml"); 045 } 046 047 @Test public void testRuleXmlParserCacheUpdate() throws Exception { 048 RuleServiceInternal ruleService = KEWServiceLocator.getRuleService(); 049 int ruleSize = ruleService.fetchAllCurrentRulesForTemplateDocCombination("TestRuleTemplate", "TestDocumentType").size(); 050 051 List collections = new ArrayList(); 052 //ultimately it is the content of RulesToImport that determines whether or not we're 053 //going to hit the rules xml parser 054 InputStream xmlFile = TestUtilities.loadResource(this.getClass(), "RulesToImport.xml"); 055 collections.add(KEWXmlDataLoader.getFileXmlDocCollection(xmlFile, "WorkflowUnitTestTemp")); 056 CoreApiServiceLocator.getXmlIngesterService().ingest(collections, null); 057 058 Thread.sleep(5000);//give cache time to reload; 059 int newRuleSize = ruleService.fetchAllCurrentRulesForTemplateDocCombination("TestRuleTemplate", "TestDocumentType").size(); 060 assertEquals("Three more rules should have been returned from the cached service", ruleSize + 3, newRuleSize); 061 } 062 063 @Test public void testDuplicateRule() throws IOException, XmlException { 064 InputStream stream = getClass().getResourceAsStream("DuplicateRuleToImport.xml"); 065 assertNotNull(stream); 066 log.info("Importing duplicate again"); 067 try { 068 KEWServiceLocator.getRuleService().loadXml(stream, null); 069 } catch (WorkflowServiceErrorException wsee) { 070 assertNotNull(TestUtilities.findExceptionInStack(wsee, XmlException.class)); 071 } 072 } 073 074 @Test public void testDuplicateRuleWithExpression() throws IOException, XmlException { 075 InputStream stream = getClass().getResourceAsStream("DuplicateRuleToImportWithExpression.xml"); 076 assertNotNull(stream); 077 log.info("Importing duplicate again"); 078 try { 079 KEWServiceLocator.getRuleService().loadXml(stream, null); 080 } catch (WorkflowServiceErrorException wsee) { 081 assertNotNull(TestUtilities.findExceptionInStack(wsee, XmlException.class)); 082 } 083 } 084 085 @Test public void testNotDuplicateRule() throws IOException, XmlException { 086 InputStream stream = getClass().getResourceAsStream("NotADuplicateRuleToImport.xml"); 087 assertNotNull(stream); 088 log.info("Importing a unique rule"); 089 // load the unique template first 090 KEWServiceLocator.getRuleTemplateService().loadXml(stream, null); 091 stream = getClass().getResourceAsStream("NotADuplicateRuleToImport.xml"); 092 // then the rule 093 KEWServiceLocator.getRuleService().loadXml(stream, null); 094 } 095 096 @Test public void testNotDuplicateRuleWithExpression() throws IOException, XmlException { 097 InputStream stream = getClass().getResourceAsStream("NotADuplicateRuleToImportWithExpression.xml"); 098 assertNotNull(stream); 099 log.info("Importing a unique rule"); 100 // load the unique template first 101 KEWServiceLocator.getRuleTemplateService().loadXml(stream, null); 102 stream = getClass().getResourceAsStream("NotADuplicateRuleToImportWithExpression.xml"); 103 // then the rule 104 KEWServiceLocator.getRuleService().loadXml(stream, null); 105 } 106 107 private static RuleExtensionValue getExtensionValue(List<RuleExtensionValue> list, String name) { 108 for (RuleExtensionValue extensionValue: list) { 109 if (name.equals(extensionValue.getKey())) return extensionValue; 110 } 111 return null; 112 } 113 114 @Test public void testNamedRule() { 115 loadXmlFile("NamedRule.xml"); 116 RuleServiceInternal ruleService = KEWServiceLocator.getRuleService(); 117 RuleBaseValues rule = ruleService.getRuleByName("ANamedRule"); 118 assertNotNull(rule); 119 assertEquals("ANamedRule", rule.getName()); 120 assertEquals("A named rule", rule.getDescription()); 121 LOG.info("Before Testing To and From Dates : " + rule.getToDateString()+" "+rule.getFromDateString()); 122 assertNull(rule.getToDateString()); 123 assertNull(rule.getFromDateString()); 124 LOG.info("Rule To and From Dates : " + rule.getDocTypeName()+" "+rule.getName()); 125 List extensions = rule.getRuleExtensions(); 126 assertEquals(1, extensions.size()); 127 RuleExtensionBo extension = (RuleExtensionBo) extensions.get(0); 128 assertEquals("TestRuleAttribute", extension.getRuleTemplateAttribute().getRuleAttribute().getName()); 129 List extensionValues = extension.getExtensionValues(); 130 assertEquals(2, extensionValues.size()); 131 //RuleExtensionValue extensionValue = (RuleExtensionValue) extensionValues.get(0); 132 RuleExtensionValue extensionValue = getExtensionValue(extensionValues, "color"); 133 assertEquals("color", extensionValue.getKey()); 134 assertEquals("green", extensionValue.getValue()); 135 //extensionValue = (RuleExtensionValue) extensionValues.get(1); 136 extensionValue = getExtensionValue(extensionValues, "shape"); 137 assertEquals("shape", extensionValue.getKey()); 138 assertEquals("square", extensionValue.getValue()); 139 List responsibilities = rule.getRuleResponsibilities(); 140 assertEquals(1, responsibilities.size()); 141 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) responsibilities.get(0); 142 assertEquals("user1", responsibility.getPrincipal().getPrincipalName()); 143 assertEquals("A", responsibility.getActionRequestedCd()); 144 } 145 146 @Test public void testNamedRuleWithExpression() { 147 loadXmlFile("NamedRuleWithExpression.xml"); 148 RuleServiceInternal ruleService = KEWServiceLocator.getRuleService(); 149 RuleBaseValues rule = ruleService.getRuleByName("ANamedRule"); 150 assertNotNull(rule); 151 assertEquals("ANamedRule", rule.getName()); 152 assertEquals("A named rule", rule.getDescription()); 153 List extensions = rule.getRuleExtensions(); 154 assertEquals(1, extensions.size()); 155 RuleExtensionBo extension = (RuleExtensionBo) extensions.get(0); 156 assertEquals("TestRuleAttribute", extension.getRuleTemplateAttribute().getRuleAttribute().getName()); 157 List extensionValues = extension.getExtensionValues(); 158 assertEquals(2, extensionValues.size()); 159 //RuleExtensionValue extensionValue = (RuleExtensionValue) extensionValues.get(0); 160 RuleExtensionValue extensionValue = getExtensionValue(extensionValues, "color"); 161 assertEquals("color", extensionValue.getKey()); 162 assertEquals("green", extensionValue.getValue()); 163 //extensionValue = (RuleExtensionValue) extensionValues.get(1); 164 extensionValue = getExtensionValue(extensionValues, "shape"); 165 assertEquals("shape", extensionValue.getKey()); 166 assertEquals("square", extensionValue.getValue()); 167 List responsibilities = rule.getRuleResponsibilities(); 168 assertEquals(1, responsibilities.size()); 169 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) responsibilities.get(0); 170 assertEquals("user1", responsibility.getPrincipal().getPrincipalName()); 171 assertEquals("A", responsibility.getActionRequestedCd()); 172 assertNotNull(rule.getRuleExpressionDef()); 173 assertEquals("someType", rule.getRuleExpressionDef().getType()); 174 assertEquals("some expression", rule.getRuleExpressionDef().getExpression()); 175 } 176 177 @Test public void testUpdatedRule() { 178 testNamedRule(); 179 180 RuleServiceInternal ruleService = KEWServiceLocator.getRuleService(); 181 // let's grab the responsibility id from the original named rule 182 RuleBaseValues rule = ruleService.getRuleByName("ANamedRule"); 183 String responsibilityId = rule.getRuleResponsibilities().get(0).getResponsibilityId(); 184 String ruleId = rule.getId(); 185 Integer versionNumber = rule.getVersionNbr(); 186 187 loadXmlFile("UpdatedNamedRule.xml"); 188 rule = ruleService.getRuleByName("ANamedRule"); 189 assertNotNull(rule); 190 assertEquals("ANamedRule", rule.getName()); 191 assertTrue("Rule should be current.", rule.getCurrentInd()); 192 assertFalse("Rule should not be a delegate rule.", rule.getDelegateRule()); 193 assertFalse("Rule should not be a template rule.", rule.getTemplateRuleInd()); 194 assertNull("Rule should not have a from date.", rule.getFromDateValue()); 195 assertNull("Rule should not have a to date.", rule.getToDateValue()); 196 197 // check that the previous versions line up and that the rule is not the same 198 assertFalse("Rule ids should be different", ruleId.equals(rule.getId())); 199 assertEquals("Previous version id should be correct", ruleId, rule.getPreviousRuleId()); 200 assertEquals("Version ids are incorrect", new Integer(versionNumber + 1), rule.getVersionNbr()); 201 // fetch the original rule and verify that it's no longer current 202 RuleBaseValues oldRule = ruleService.findRuleBaseValuesById(ruleId); 203 assertFalse("Old rule should no longer be current.", oldRule.getCurrentInd()); 204 205 assertEquals("A named rule with an updated description, rule extension values, and responsibilities", rule.getDescription()); 206 List extensions = rule.getRuleExtensions(); 207 assertEquals(1, extensions.size()); 208 RuleExtensionBo extension = (RuleExtensionBo) extensions.get(0); 209 assertEquals("TestRuleAttribute", extension.getRuleTemplateAttribute().getRuleAttribute().getName()); 210 List extensionValues = extension.getExtensionValues(); 211 assertEquals(2, extensionValues.size()); 212 //RuleExtensionValue extensionValue = (RuleExtensionValue) extensionValues.get(0); 213 RuleExtensionValue extensionValue = getExtensionValue(extensionValues, "flavor"); 214 assertEquals("flavor", extensionValue.getKey()); 215 assertEquals("vanilla", extensionValue.getValue()); 216 //extensionValue = (RuleExtensionValue) extensionValues.get(1); 217 extensionValue = getExtensionValue(extensionValues, "value"); 218 assertEquals("value", extensionValue.getKey()); 219 assertEquals("10", extensionValue.getValue()); 220 List responsibilities = rule.getRuleResponsibilities(); 221 assertEquals(2, responsibilities.size()); 222 223 // responsibility should have the same id as our original responsibility 224 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) responsibilities.get(0); 225 assertEquals(responsibilityId, responsibility.getResponsibilityId()); 226 assertEquals("user1", responsibility.getPrincipal().getPrincipalName()); 227 assertEquals("A", responsibility.getActionRequestedCd()); 228 assertEquals(new Integer(1), responsibility.getPriority()); 229 230 responsibility = (RuleResponsibilityBo) responsibilities.get(1); 231 assertFalse(responsibilityId.equals(responsibility.getResponsibilityId())); 232 assertEquals("user2", responsibility.getPrincipal().getPrincipalName()); 233 assertEquals("F", responsibility.getActionRequestedCd()); 234 assertEquals(new Integer(1), responsibility.getPriority()); 235 } 236 237 @Test public void testUpdatedRuleWithExpression() { 238 testNamedRule(); 239 loadXmlFile("UpdatedNamedRuleWithExpression.xml"); 240 RuleServiceInternal ruleService = KEWServiceLocator.getRuleService(); 241 RuleBaseValues rule = ruleService.getRuleByName("ANamedRule"); 242 assertNotNull(rule); 243 assertEquals("ANamedRule", rule.getName()); 244 assertEquals("A named rule with an updated description, rule extension values, and responsibilities", rule.getDescription()); 245 List extensions = rule.getRuleExtensions(); 246 assertEquals(1, extensions.size()); 247 RuleExtensionBo extension = (RuleExtensionBo) extensions.get(0); 248 assertEquals("TestRuleAttribute", extension.getRuleTemplateAttribute().getRuleAttribute().getName()); 249 List extensionValues = extension.getExtensionValues(); 250 assertEquals(2, extensionValues.size()); 251 //RuleExtensionValue extensionValue = (RuleExtensionValue) extensionValues.get(0); 252 RuleExtensionValue extensionValue = getExtensionValue(extensionValues, "flavor"); 253 assertEquals("flavor", extensionValue.getKey()); 254 assertEquals("vanilla", extensionValue.getValue()); 255 //extensionValue = (RuleExtensionValue) extensionValues.get(1); 256 extensionValue = getExtensionValue(extensionValues, "value"); 257 assertEquals("value", extensionValue.getKey()); 258 assertEquals("10", extensionValue.getValue()); 259 List responsibilities = rule.getRuleResponsibilities(); 260 assertEquals(1, responsibilities.size()); 261 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) responsibilities.get(0); 262 assertEquals("user2", responsibility.getPrincipal().getPrincipalName()); 263 assertEquals("F", responsibility.getActionRequestedCd()); 264 } 265 266 /** 267 * This test tests that an anonymous rule will still be checked against named rules for duplication. 268 */ 269 @Test 270 public void testAnonymousDuplicatesNamed() { 271 testNamedRule(); 272 273 final InputStream stream = getClass().getResourceAsStream("DuplicateAnonymousRule.xml"); 274 assertNotNull(stream); 275 log.info("Importing anonymous duplicate rule"); 276 try { 277 KEWServiceLocator.getRuleService().loadXml(stream, null); 278 fail("Expected exception was not thrown"); 279 } catch (WorkflowServiceErrorException e) { 280 assertNotNull("Expected exception was not thrown", TestUtilities.findExceptionInStack(e.getCause(), XmlException.class)); 281 } 282 } 283 284 /** 285 * This test tests that an anonymous rule will still be checked against named rules for duplication. 286 */ 287 @Test public void testAnonymousWithExpressionDuplicatesNamed() { 288 testNamedRuleWithExpression(); 289 290 final InputStream stream = getClass().getResourceAsStream("DuplicateAnonymousRuleWithExpression.xml"); 291 assertNotNull(stream); 292 log.info("Importing anonymous duplicate rule"); 293 try { 294 KEWServiceLocator.getRuleService().loadXml(stream, null); 295 fail("Expected exception was not thrown"); 296 } catch (WorkflowServiceErrorException e) { 297 assertNotNull("Expected exception was not thrown", TestUtilities.findExceptionInStack(e.getCause(), XmlException.class)); 298 } 299 } 300 301 @Test public void testParameterReplacement() throws IOException, XmlException { 302 ConfigContext.getCurrentContextConfig().putProperty("test.replacement.user", "user3"); 303 ConfigContext.getCurrentContextConfig().putProperty("test.replacement.workgroup", "WorkflowAdmin"); 304 List<RuleBaseValues> rules = new RuleXmlParser().parseRules(getClass().getResourceAsStream("ParameterizedRule.xml")); 305 assertEquals(1, rules.size()); 306 RuleBaseValues rule = rules.get(0); 307 assertEquals(2, rule.getRuleResponsibilities().size()); 308 RuleResponsibilityBo resp = (RuleResponsibilityBo) rule.getRuleResponsibilities().get(0); 309 310 if (resp.isUsingPrincipal()) { 311 assertEquals("user3", resp.getPrincipal().getPrincipalName()); 312 } else { 313 assertEquals("WorkflowAdmin", resp.getGroup().getName()); 314 } 315 316 ConfigContext.getCurrentContextConfig().putProperty("test.replacement.user", "user1"); 317 ConfigContext.getCurrentContextConfig().putProperty("test.replacement.workgroup", "TestWorkgroup"); 318 rules = new RuleXmlParser().parseRules(getClass().getResourceAsStream("ParameterizedRule.xml")); 319 assertEquals(1, rules.size()); 320 rule = rules.get(0); 321 assertEquals(2, rule.getRuleResponsibilities().size()); 322 resp = (RuleResponsibilityBo) rule.getRuleResponsibilities().get(0); 323 324 if (resp.isUsingPrincipal()) 325 { 326 assertEquals("user1", resp.getPrincipal().getPrincipalName()); 327 } 328 else 329 { 330 assertEquals("TestWorkgroup", resp.getGroup().getName()); 331 } 332 } 333 334 @Test public void removeTemplateFromNamedRule() { 335 RuleServiceInternal ruleService = KEWServiceLocator.getRuleService(); 336 int originalRuleCount = ruleService.fetchAllCurrentRulesForTemplateDocCombination("TestRuleTemplate", "TestDocumentType").size(); 337 338 testNamedRule(); 339 340 LOG.debug("Rules for doctype/template combo:"); 341 int ruleCount = 0; 342 List<RuleBaseValues> list = ruleService.fetchAllCurrentRulesForTemplateDocCombination("TestRuleTemplate", "TestDocumentType"); 343 if (list != null) { 344 ruleCount = list.size(); 345 for (RuleBaseValues rbv: list) { 346 LOG.info(rbv); 347 } 348 } 349 350 loadXmlFile("NamedRuleWithoutTemplate.xml"); 351 352 LOG.debug("Rules for doctype/template combo after import of named rule:"); 353 int ruleCountAfter = 0; 354 list = ruleService.fetchAllCurrentRulesForTemplateDocCombination("TestRuleTemplate", "TestDocumentType"); 355 if (list != null) { 356 ruleCountAfter = list.size(); 357 for (RuleBaseValues rbv: list) { 358 LOG.info(rbv); 359 } 360 } 361 362 RuleBaseValues rule = ruleService.getRuleByName("ANamedRule"); 363 364 assertNotNull(rule); 365 LOG.info("Rule id of latest version: " + rule.getId()); 366 assertEquals("ANamedRule", rule.getName()); 367 assertEquals("A named rule with previously defined template removed", rule.getDescription()); 368 369 assertEquals("The rules for template/doctype combo should have been decreased by one after reimport of named rule without template", ruleCount - 1, ruleCountAfter); 370 assertEquals("Rule count should be original template/doctype combo rule count after removing template from named rule", originalRuleCount, ruleCountAfter); 371 372 assertNull(rule.getRuleTemplate()); 373 374 // templateless rules cannot have extensions, so these should be removed 375 List extensions = rule.getRuleExtensions(); 376 assertEquals(0, extensions.size()); 377 378 List responsibilities = rule.getRuleResponsibilities(); 379 assertEquals(1, responsibilities.size()); 380 RuleResponsibilityBo responsibility = (RuleResponsibilityBo) responsibilities.get(0); 381 assertEquals("user2", responsibility.getPrincipal().getPrincipalName()); 382 assertEquals("F", responsibility.getActionRequestedCd()); 383 } 384 385 @Test public void testInvalidTemplatelessNamedRule() { 386 testNamedRule(); 387 try { 388 loadXmlFile("InvalidTemplatelessNamedRule.xml"); 389 fail("Rule should have failed to load because it attempts to define extensions on a templateless rule."); 390 } catch (Exception e) {} 391 } 392 393 @Test public void testRulesWithDifferentResponsibilityTypes() throws Exception { 394 loadXmlFile("RulesWithDifferentResponsibilityTypes.xml"); 395 RuleServiceInternal ruleService = KEWServiceLocator.getRuleService(); 396 397 RuleBaseValues rule = ruleService.getRuleByName("RespTypeTest1"); 398 assertNotNull(rule); 399 assertEquals("Rule should have a principal responsibility", KewApiConstants.RULE_RESPONSIBILITY_WORKFLOW_ID, rule.getRuleResponsibilities().get(0).getRuleResponsibilityType()); 400 assertEquals("Rule should have a principal id of user1", "user1", rule.getRuleResponsibilities().get(0).getRuleResponsibilityName()); 401 402 rule = ruleService.getRuleByName("RespTypeTest2"); 403 assertNotNull(rule); 404 assertEquals("Rule should have a principal responsibility", KewApiConstants.RULE_RESPONSIBILITY_WORKFLOW_ID, rule.getRuleResponsibilities().get(0).getRuleResponsibilityType()); 405 assertEquals("Rule should have a principal id of user1", "user1", rule.getRuleResponsibilities().get(0).getRuleResponsibilityName()); 406 407 rule = ruleService.getRuleByName("RespTypeTest3"); 408 assertNotNull(rule); 409 assertEquals("Rule should have a group responsibility", KewApiConstants.RULE_RESPONSIBILITY_GROUP_ID, rule.getRuleResponsibilities().get(0).getRuleResponsibilityType()); 410 assertEquals("Rule should have a group id of 3001", "3001", rule.getRuleResponsibilities().get(0).getRuleResponsibilityName()); 411 412 rule = ruleService.getRuleByName("RespTypeTest4"); 413 assertNotNull(rule); 414 assertEquals("Rule should have a group responsibility", KewApiConstants.RULE_RESPONSIBILITY_GROUP_ID, rule.getRuleResponsibilities().get(0).getRuleResponsibilityType()); 415 assertEquals("Rule should have a group id of 1", "1", rule.getRuleResponsibilities().get(0).getRuleResponsibilityName()); 416 417 rule = ruleService.getRuleByName("RespTypeTest5"); 418 assertNotNull(rule); 419 assertEquals("Rule should have a role responsibility", KewApiConstants.RULE_RESPONSIBILITY_ROLE_ID, rule.getRuleResponsibilities().get(0).getRuleResponsibilityType()); 420 assertEquals("Invalid role name", "org.kuali.rice.kew.rule.TestRuleAttribute!TEST", rule.getRuleResponsibilities().get(0).getRuleResponsibilityName()); 421 422 rule = ruleService.getRuleByName("RespTypeTest6"); 423 assertNotNull(rule); 424 assertEquals("Rule should have a role responsibility", KewApiConstants.RULE_RESPONSIBILITY_ROLE_ID, rule.getRuleResponsibilities().get(0).getRuleResponsibilityType()); 425 assertEquals("Invalid role name", "org.kuali.rice.kew.rule.TestRuleAttribute!TEST", rule.getRuleResponsibilities().get(0).getRuleResponsibilityName()); 426 } 427}