View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.rule;
17  
18  import org.apache.log4j.Logger;
19  import org.junit.Test;
20  import org.kuali.rice.core.api.CoreApiServiceLocator;
21  import org.kuali.rice.core.api.config.property.ConfigContext;
22  import org.kuali.rice.core.api.util.xml.XmlException;
23  import org.kuali.rice.kew.batch.KEWXmlDataLoader;
24  import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
25  import org.kuali.rice.kew.rule.service.RuleServiceInternal;
26  import org.kuali.rice.kew.service.KEWServiceLocator;
27  import org.kuali.rice.kew.test.KEWTestCase;
28  import org.kuali.rice.kew.test.TestUtilities;
29  import org.kuali.rice.kew.api.KewApiConstants;
30  import org.kuali.rice.kew.xml.RuleXmlParser;
31  
32  import java.io.IOException;
33  import java.io.InputStream;
34  import java.util.ArrayList;
35  import java.util.List;
36  
37  import static org.junit.Assert.*;
38  
39  public class RuleXmlParserTest extends KEWTestCase {
40      private static final Logger LOG = Logger.getLogger(RuleXmlParserTest.class);
41  
42      protected void loadTestData() throws Exception {
43          loadXmlFile("RouteTemplateConfig.xml");
44          loadXmlFile("DuplicateRuleToImport.xml");
45      }
46  
47      @Test public void testRuleXmlParserCacheUpdate() throws Exception {
48          RuleServiceInternal ruleService = KEWServiceLocator.getRuleService();
49          int ruleSize = ruleService.fetchAllCurrentRulesForTemplateDocCombination("TestRuleTemplate", "TestDocumentType").size();
50  
51          List collections = new ArrayList();
52          //ultimately it is the content of RulesToImport that determines whether or not we're
53          //going to hit the rules xml parser
54          InputStream xmlFile = TestUtilities.loadResource(this.getClass(), "RulesToImport.xml");
55          collections.add(KEWXmlDataLoader.getFileXmlDocCollection(xmlFile, "WorkflowUnitTestTemp"));
56          CoreApiServiceLocator.getXmlIngesterService().ingest(collections, null);
57  
58          Thread.sleep(5000);//give cache time to reload;
59          int newRuleSize = ruleService.fetchAllCurrentRulesForTemplateDocCombination("TestRuleTemplate", "TestDocumentType").size();
60          assertEquals("Three more rules should have been returned from the cached service", ruleSize + 3, newRuleSize);
61      }
62  
63      @Test public void testDuplicateRule() throws IOException, XmlException {
64          InputStream stream = getClass().getResourceAsStream("DuplicateRuleToImport.xml");
65          assertNotNull(stream);
66          log.info("Importing duplicate again");
67          try {
68              KEWServiceLocator.getRuleService().loadXml(stream, null);
69          } catch (WorkflowServiceErrorException wsee) {
70              assertNotNull(TestUtilities.findExceptionInStack(wsee, XmlException.class));
71          }
72      }
73  
74      @Test public void testDuplicateRuleWithExpression() throws IOException, XmlException {
75          InputStream stream = getClass().getResourceAsStream("DuplicateRuleToImportWithExpression.xml");
76          assertNotNull(stream);
77          log.info("Importing duplicate again");
78          try {
79              KEWServiceLocator.getRuleService().loadXml(stream, null);
80          } catch (WorkflowServiceErrorException wsee) {
81              assertNotNull(TestUtilities.findExceptionInStack(wsee, XmlException.class));
82          }
83      }
84  
85      @Test public void testNotDuplicateRule() throws IOException, XmlException {
86          InputStream stream = getClass().getResourceAsStream("NotADuplicateRuleToImport.xml");
87          assertNotNull(stream);
88          log.info("Importing a unique rule");
89          // load the unique template first
90          KEWServiceLocator.getRuleTemplateService().loadXml(stream, null);
91          stream = getClass().getResourceAsStream("NotADuplicateRuleToImport.xml");
92          // then the rule
93          KEWServiceLocator.getRuleService().loadXml(stream, null);
94      }
95  
96      @Test public void testNotDuplicateRuleWithExpression() throws IOException, XmlException {
97          InputStream stream = getClass().getResourceAsStream("NotADuplicateRuleToImportWithExpression.xml");
98          assertNotNull(stream);
99          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 }