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  
17  package org.kuali.rice.krms.test;
18  
19  import org.apache.commons.lang.StringUtils;
20  import org.junit.Before;
21  import org.junit.Test;
22  import org.kuali.rice.core.api.criteria.QueryByCriteria;
23  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
24  import org.kuali.rice.krms.api.repository.action.ActionDefinition;
25  import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
26  import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
27  import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
28  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
29  import org.kuali.rice.krms.impl.repository.ActionAttributeBo;
30  
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collection;
34  import java.util.HashMap;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.Set;
38  
39  import static org.junit.Assert.*;
40  import static org.junit.Assert.assertEquals;
41  import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
42  import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
43  
44  import static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.*;
45  
46  /**
47   *   RuleManagementRuleDefinitionTest is to test the methods of ruleManagementServiceImpl relating to RuleDefinitions
48   *
49   *   Each test focuses on one of the methods.
50   */
51  public class RuleManagementRuleDefinitionTest  extends RuleManagementBaseTest{
52      @Override
53      @Before
54      public void setClassDiscriminator() {
55          // set a unique discriminator for test objects of this class
56          CLASS_DISCRIMINATOR = "RMRDT";
57      }
58  
59      /**
60       *  Test testGetRuleByNameAndNamespace()
61       *
62       *  This test focuses specifically on the RuleManagementServiceImpl .getRuleByNameAndNamespace("rule name", "namespace") method
63       */
64      @Test
65      public void testGetRuleByNameAndNamespace() {
66          // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
67          RuleManagementBaseTestObjectNames t0 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t0");
68  
69          RuleDefinition ruleDefinition = buildTestRuleDefinition(t0.namespaceName, t0.object0);
70  
71          RuleDefinition returnRuleDefinition = ruleManagementService.getRuleByNameAndNamespace(
72                  ruleDefinition.getName(), ruleDefinition.getNamespace());
73  
74          assertEquals("rule not found", ruleDefinition.getId(), returnRuleDefinition.getId());
75  
76          // try getRuleByNameAndNamespace with null Name parameter
77          try {
78              ruleManagementService.getRuleByNameAndNamespace(null, t0.namespaceName);
79              fail("Should have thrown IllegalArgumentException: name is null or blank");
80          } catch (IllegalArgumentException e) {
81              // throws IllegalArgumentException: name is null or blank
82          }
83  
84          // try getRuleByNameAndNamespace with null Name parameter
85          try {
86              ruleManagementService.getRuleByNameAndNamespace("   ", t0.namespaceName);
87              fail("Should have thrown IllegalArgumentException: name is null or blank");
88          } catch (IllegalArgumentException e) {
89              // throws IllegalArgumentException: name is null or blank
90          }
91  
92          // try getRuleByNameAndNamespace with null namespace parameter
93          try {
94              ruleManagementService.getRuleByNameAndNamespace(ruleDefinition.getName(),null);
95              fail("should throw IllegalArgumentException: namespace is null or blank");
96          } catch (IllegalArgumentException e) {
97              // IllegalArgumentException: namespace is null or blank
98          }
99  
100         // try getRuleByNameAndNamespace with blank namespace parameter
101         try {
102             ruleManagementService.getRuleByNameAndNamespace(ruleDefinition.getName(),"    ");
103             fail("should throw IllegalArgumentException: namespace is null or blank");
104         } catch (IllegalArgumentException e) {
105             // IllegalArgumentException: namespace is null or blank
106         }
107 
108 
109     }
110 
111     /**
112      *  Test testCreateRule()
113      *
114      *  This test focuses specifically on the RuleManagementServiceImpl .createRule(RuleDefinition) method
115      */
116     @Test
117     public void testCreateRule() {
118         // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
119         RuleManagementBaseTestObjectNames t1 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t1");
120 
121         // create a Rule
122         RuleDefinition ruleFirstCreate = buildTestRuleDefinition(t1.namespaceName, t1.object0);
123         assertTrue("created Rule not found", ruleManagementService.getRule(ruleFirstCreate.getId()).getId().contains(t1.rule_0_Id));
124 
125         // try to create a duplicate Rule
126         try {
127             RuleDefinition ruleSecondCreate = ruleManagementService.createRule(ruleFirstCreate);
128             fail("should have thrown RiceIllegalArgumentException");
129         } catch (RiceIllegalArgumentException e) {
130             //  throw new RiceIllegalArgumentException(ruleDefinition.getId());
131         }
132 
133         // try to create a malformed Rule
134         RuleDefinition malformedRule = buildTestRuleDefinition(t1.namespaceName, t1.object1);
135         RuleDefinition.Builder builder = RuleDefinition.Builder.create(malformedRule);
136         builder.setPropId("invalidValue");
137         malformedRule =  builder.build();
138         try {
139             ruleManagementService.createRule(malformedRule);
140             fail("should have thrown RiceIllegalArgumentException");
141         } catch (RiceIllegalArgumentException e) {
142             // throw new RiceIllegalArgumentException("propId does not match proposition.getId"
143         }
144     }
145 
146     /**
147      *  Test testUpdateRule()
148      *
149      *  This test focuses specifically on the RuleManagementServiceImpl .updateRule(RuleDefinition) method
150      */
151     @Test
152     public void testUpdateRule() {
153         // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
154         RuleManagementBaseTestObjectNames t2 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t2");
155 
156         // build a rule to test with
157         RuleDefinition.Builder ruleBuilder0 = RuleDefinition.Builder.create(buildTestRuleDefinition(t2.namespaceName,
158                 t2.object0));
159 
160         // update the rule's Name
161         ruleBuilder0.setName("updatedName");
162         ruleManagementService.updateRule(ruleBuilder0.build());
163 
164         // verify update
165         RuleDefinition rule0 = ruleManagementService.getRule(t2.rule_0_Id);
166         assertNotEquals("Rule Name Not Updated", t2.rule_0_Name, rule0.getName());
167         assertEquals("Rule Name Not Updated", "updatedName", rule0.getName());
168 
169         // build new rule for test
170         RuleDefinition.Builder ruleBuilder1 = RuleDefinition.Builder.create(buildTestRuleDefinition(t2.namespaceName,
171                 t2.object1));
172         assertEquals("Expected Proposition not found in Rule",t2.proposition_1_Descr,ruleBuilder1.getProposition().getDescription());
173 
174         // create new proposition to update rule with
175         String newPropId = "PropNewId";
176         PropositionDefinition prop = createTestSimpleProposition(t2.namespaceName, newPropId, "TSI_"+newPropId,
177                 "ABC", "=", "java.lang.String", t2.rule_0_Id, "TSI_" + newPropId + "_Descr");
178         PropositionDefinition.Builder propBuilder = PropositionDefinition.Builder.create(prop);
179         ruleBuilder1.setPropId(newPropId);
180         ruleBuilder1.setProposition(propBuilder);
181 
182         // Update Proposition in rule
183         ruleManagementService.updateRule(ruleBuilder1.build());
184         rule0 = ruleManagementService.getRule(ruleBuilder1.getId());
185         assertEquals("Expected Proposition not found in Rule","PropNewId_simple_proposition",rule0.getProposition().getDescription());
186 
187         // build new rule for test
188         RuleDefinition.Builder ruleBuilder2 = RuleDefinition.Builder.create(buildTestRuleDefinition(t2.namespaceName,t2.object7));
189         createTestKrmsAttribute(t2.actionAttribute, t2.actionAttribute_Key, t2.namespaceName);
190         Map<String, String> attributes = new HashMap<String, String>();
191         attributes.put(t2.actionAttribute_Key, t2.actionAttribute_Value);
192         List<ActionDefinition.Builder> actionBuilders = new ArrayList<ActionDefinition.Builder>();
193         KrmsTypeDefinition krmsTypeDefinition = createKrmsActionTypeDefinition(t2.namespaceName);
194         ActionDefinition.Builder actionBuilder = ActionDefinition.Builder.create(t2.action_Id, t2.action_Name,
195                 t2.namespaceName, krmsTypeDefinition.getId(), rule0.getId(), 1);
196         actionBuilder.setDescription(t2.action_Descr);
197         actionBuilder.setAttributes(attributes);
198         actionBuilders.add(actionBuilder);
199         ruleBuilder2.setActions(actionBuilders);
200         ruleManagementService.updateRule(ruleBuilder2.build());
201 
202         // Update Action in rule
203         ruleBuilder2 = RuleDefinition.Builder.create(ruleManagementService.getRule(t2.rule_7_Id));
204         Map<String, String> newAttributes = new HashMap<String, String>();
205         newAttributes.put(t2.actionAttribute_Key, t2.actionAttribute1_Value);
206 
207         for (ActionDefinition.Builder ruleActionBuilder : ruleBuilder2.getActions()) {
208             ruleActionBuilder.setAttributes(newAttributes);
209         }
210 
211         ruleManagementService.updateRule(ruleBuilder2.build());
212         rule0 = ruleManagementService.getRule(t2.rule_7_Id);
213         assertEquals("Invalid AgendaItem Rule Actions count",1,rule0.getActions().size());
214 
215         for (ActionDefinition action : rule0.getActions()) {
216             Map<String, Object> map = new HashMap<String, Object>();
217             map.put("action.id", action.getId());
218             Collection<ActionAttributeBo> actionAttributes = findMatching(dataObjectService, ActionAttributeBo.class, map);
219             assertEquals("Invalid AgendaItem Rule Actions attribute count",1,actionAttributes.size());
220 
221             for (ActionAttributeBo actionAttribute : actionAttributes) {
222                 String expectedAttribute = t2.actionAttribute1_Value;
223                 String actualAttribute = actionAttribute.getValue();
224                 assertEquals("Invalid AgendaItem Rule Actions attribute",expectedAttribute,actualAttribute);
225             }
226         }
227     }
228 
229     /**
230      *  Test testDeleteRule()
231      *
232      *  This test focuses specifically on the RuleManagementServiceImpl .deleteRule("rule id") method
233      */
234     @Test
235     public void testDeleteRule() {
236         // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
237         RuleManagementBaseTestObjectNames t3 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t3");
238 
239         // create a Rule
240         RuleDefinition rule = buildTestRuleDefinition(t3.namespaceName, t3.object0);
241         assertTrue("created Rule not found", ruleManagementService.getRule(rule.getId()).getId().contains(t3.rule_0_Id));
242         String propositionId = rule.getPropId();
243         assertEquals("Proposition for Rule not found", t3.proposition_0_Descr,
244                 ruleManagementService.getProposition(propositionId).getDescription());
245 
246 
247         ruleManagementService.deleteRule(rule.getId());
248 
249         assertNull("Rule was not deleted", ruleManagementService.getRule(rule.getId()));
250 
251         // make sure proposition was cleaned up when rule was deleted
252         try {
253             ruleManagementService.deleteProposition(propositionId);
254             fail("should fail with IllegalStateException: the Proposition to delete does not exists");
255         } catch (IllegalStateException e) {
256             // IllegalStateException: the Proposition to delete does not exists
257         }
258     }
259 
260     /**
261      *  Test testFindRuleIds()
262      *
263      *  This test focuses specifically on the RuleManagementServiceImpl .findRuleIds( QueryByCriteria) method
264      */
265     @Test
266     public void testFindRuleIds() {
267         // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
268         RuleManagementBaseTestObjectNames t4 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t4");
269 
270         RuleDefinition rule0 = buildTestRuleDefinition(t4.namespaceName, t4.object0);
271         RuleDefinition rule1 = buildTestRuleDefinition(t4.namespaceName, t4.object1);
272         RuleDefinition rule2 = buildTestRuleDefinition(t4.namespaceName, t4.object2);
273         RuleDefinition rule3 = buildTestRuleDefinition(t4.namespaceName, t4.object3);
274         String ruleNameSpace = rule0.getNamespace();
275         List<String> ruleNames =  new ArrayList<String>();
276         ruleNames.add(rule0.getName());
277         ruleNames.add(rule1.getName());
278         ruleNames.add(rule2.getName());
279         ruleNames.add(rule3.getName());
280 
281         QueryByCriteria.Builder builder = QueryByCriteria.Builder.create();
282 
283         builder.setPredicates(equal("namespace", ruleNameSpace), in("name", ruleNames.toArray(new String[]{})));
284 
285         List<String> ruleIds = ruleManagementService.findRuleIds(builder.build());
286         assertEquals("Wrong number of RuleIds returned", 4, ruleIds.size());
287 
288         if(!ruleIds.contains(rule0.getId())){
289             fail("RuleId not found in results");
290         }
291     }
292 
293     /**
294      *  Test testGetRule()
295      *
296      *  This test focuses specifically on the RuleManagementServiceImpl .getRule("rule id") method
297      */
298     @Test
299     public void testGetRule() {
300         // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
301         RuleManagementBaseTestObjectNames t5 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t5");
302 
303         // create a rule to test with
304         RuleDefinition ruleDefinition = buildTestRuleDefinition(t5.namespaceName, t5.object0);
305 
306         assertNotNull(ruleManagementService.getRule(ruleDefinition.getId()));
307 
308         assertNull("Should have returned null", ruleManagementService.getRule(null));
309         assertNull("Should have returned null", ruleManagementService.getRule("   "));
310         assertNull("Should have returned null", ruleManagementService.getRule("badValueId"));
311     }
312 
313     /**
314      *  Test testGetRules()
315      *
316      *  This test focuses specifically on the RuleManagementServiceImpl .getRules(List<String> ruleIds) method
317      */
318     @Test
319     public void testGetRules() {
320         // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
321         RuleManagementBaseTestObjectNames t6 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t6");
322 
323         // build two rules for testing
324         buildTestRuleDefinition(t6.namespaceName, t6.object0);
325         buildTestRuleDefinition(t6.namespaceName, t6.object1);
326 
327         // build List rule ids for the rules created
328         List<String> ruleIds = new ArrayList<String>();
329         ruleIds.add(t6.rule_0_Id);
330         ruleIds.add(t6.rule_1_Id);
331 
332         // get test rules by List of rule ids
333         List<RuleDefinition> ruleDefinitions = ruleManagementService.getRules(ruleIds);
334         assertEquals("Two RuleDefintions should have been returned",2,ruleDefinitions.size());
335 
336         for(RuleDefinition ruleDefinition : ruleDefinitions) {
337             if (!ruleIds.contains(ruleDefinition.getId())) {
338                 fail("Invalid RuleDefinition returned");
339             }
340         }
341 
342         try {
343             ruleManagementService.getRules(null);
344             fail("Should have failed with RiceIllegalArgumentException: ruleIds must not be null");
345         } catch (RiceIllegalArgumentException e) {
346             // throws RiceIllegalArgumentException: ruleIds must not be null
347         }
348 
349         assertEquals("No RuleDefinitions should have been returned",0,
350                 ruleManagementService.getRules(new ArrayList<String>()).size());
351 
352         ruleIds = Arrays.asList("badValueId");
353         assertEquals("No RuleDefinitions should have been returned",0, ruleManagementService.getRules(ruleIds).size());
354     }
355 
356     /**
357      * Tests whether the {@code RuleDefinition} cache is being evicted properly by checking the status the dependent
358      * objects before and after creating an {@code RuleDefinition} (and consequently emptying the cache).
359      *
360      * <p>
361      * The following object caches are affected:
362      * {@code RuleDefinition}, {@code PropositionDefinition}, {@code ActionDefinition}, {@code AgendaItemDefinition}
363      * </p>
364      */
365     @Test
366     public void testRuleCacheEvict() {
367         // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
368         RuleManagementBaseTestObjectNames t7 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t7");
369 
370         verifyEmptyRule(t7);
371 
372         String ruleId = buildTestRuleDefinition(t7.namespaceName, t7.object0).getId();
373         buildTestActionDefinition(t7.action_Id, t7.action_Name, t7.action_Descr, 1, ruleId, t7.namespaceName);
374         String agendaId = createTestAgenda(t7.object0).getId();
375         buildTestAgendaItemDefinition(t7.agendaItem_Id, agendaId, ruleId);
376 
377         verifyFullRule(t7);
378     }
379 
380     private void verifyEmptyRule(RuleManagementBaseTestObjectNames t) {
381         RuleDefinition rule = ruleManagementService.getRule(t.rule_Id);
382         assertNull("Rule is not null", rule);
383 
384         Set<PropositionDefinition> propositions = ruleManagementService.getPropositionsByRule(t.rule_Id);
385         assertFalse("Rule in Proposition found", propositions != null && !propositions.isEmpty());
386 
387         ActionDefinition action = ruleManagementService.getAction(t.action_Id);
388         assertFalse("Rule in Action found", action != null);
389 
390         AgendaItemDefinition agendaItem = ruleManagementService.getAgendaItem(t.agendaItem_Id);
391         assertFalse("Rule in AgendaItem found", agendaItem != null);
392     }
393 
394     private void verifyFullRule(RuleManagementBaseTestObjectNames t) {
395         RuleDefinition rule = ruleManagementService.getRule(t.rule_Id);
396         assertNotNull("Rule is null", rule);
397 
398         boolean foundRule = false;
399         Set<PropositionDefinition> propositions = ruleManagementService.getPropositionsByRule(t.rule_Id);
400         if (propositions != null) {
401             for (PropositionDefinition proposition : propositions) {
402                 if (StringUtils.equals(t.rule_Id, proposition.getRuleId())) {
403                     foundRule = true;
404                     break;
405                 }
406             }
407         }
408         assertTrue("Rule in Proposition not found", foundRule);
409 
410         ActionDefinition action = ruleManagementService.getAction(t.action_Id);
411         assertTrue("Rule in Action not found", action != null);
412         assertTrue("Rule in Action not found", StringUtils.equals(t.rule_Id, action.getRuleId()));
413 
414         AgendaItemDefinition agendaItem = ruleManagementService.getAgendaItem(t.agendaItem_Id);
415         assertTrue("Rule in AgendaItem not found", agendaItem != null);
416         assertTrue("Rule in AgendaItem not found", StringUtils.equals(t.rule_Id, agendaItem.getRuleId()));
417     }
418 }