001 /**
002 * Copyright 2005-2014 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.rule;
017
018 import org.apache.log4j.Logger;
019 import org.junit.Test;
020 import org.kuali.rice.core.api.CoreApiServiceLocator;
021 import org.kuali.rice.core.api.config.property.ConfigContext;
022 import org.kuali.rice.core.api.util.xml.XmlException;
023 import org.kuali.rice.kew.batch.KEWXmlDataLoader;
024 import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
025 import org.kuali.rice.kew.rule.service.RuleServiceInternal;
026 import org.kuali.rice.kew.service.KEWServiceLocator;
027 import org.kuali.rice.kew.test.KEWTestCase;
028 import org.kuali.rice.kew.test.TestUtilities;
029 import org.kuali.rice.kew.api.KewApiConstants;
030 import org.kuali.rice.kew.xml.RuleXmlParser;
031
032 import java.io.IOException;
033 import java.io.InputStream;
034 import java.util.ArrayList;
035 import java.util.List;
036
037 import static org.junit.Assert.*;
038
039 public 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 }