001/*
002 * Copyright 2006-2013 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
017package org.kuali.rice.krms.test;
018
019import org.apache.commons.lang.StringUtils;
020import org.junit.Before;
021import org.junit.Test;
022import org.kuali.rice.core.api.criteria.QueryByCriteria;
023import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
024import org.kuali.rice.krms.api.repository.action.ActionDefinition;
025import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
026import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
027import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
028import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
029import org.kuali.rice.krms.impl.repository.ActionAttributeBo;
030
031import java.util.ArrayList;
032import java.util.Arrays;
033import java.util.Collection;
034import java.util.HashMap;
035import java.util.List;
036import java.util.Map;
037import java.util.Set;
038
039import static org.junit.Assert.*;
040import static org.junit.Assert.assertEquals;
041import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
042import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
043
044
045/**
046 *   RuleManagementRuleDefinitionTest is to test the methods of ruleManagementServiceImpl relating to RuleDefinitions
047 *
048 *   Each test focuses on one of the methods.
049 */
050public class RuleManagementRuleDefinitionTest  extends RuleManagementBaseTest{
051    @Override
052    @Before
053    public void setClassDiscriminator() {
054        // set a unique discriminator for test objects of this class
055        CLASS_DISCRIMINATOR = "RMRDT";
056    }
057
058    /**
059     *  Test testGetRuleByNameAndNamespace()
060     *
061     *  This test focuses specifically on the RuleManagementServiceImpl .getRuleByNameAndNamespace("rule name", "namespace") method
062     */
063    @Test
064    public void testGetRuleByNameAndNamespace() {
065        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
066        RuleManagementBaseTestObjectNames t0 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t0");
067
068        RuleDefinition ruleDefinition = buildTestRuleDefinition(t0.namespaceName, t0.object0);
069
070        RuleDefinition returnRuleDefinition = ruleManagementService.getRuleByNameAndNamespace(
071                ruleDefinition.getName(), ruleDefinition.getNamespace());
072
073        assertEquals("rule not found", ruleDefinition.getId(), returnRuleDefinition.getId());
074
075        // try getRuleByNameAndNamespace with null Name parameter
076        try {
077            ruleManagementService.getRuleByNameAndNamespace(null, t0.namespaceName);
078            fail("Should have thrown IllegalArgumentException: name is null or blank");
079        } catch (IllegalArgumentException e) {
080            // throws IllegalArgumentException: name is null or blank
081        }
082
083        // try getRuleByNameAndNamespace with null Name parameter
084        try {
085            ruleManagementService.getRuleByNameAndNamespace("   ", t0.namespaceName);
086            fail("Should have thrown IllegalArgumentException: name is null or blank");
087        } catch (IllegalArgumentException e) {
088            // throws IllegalArgumentException: name is null or blank
089        }
090
091        // try getRuleByNameAndNamespace with null namespace parameter
092        try {
093            ruleManagementService.getRuleByNameAndNamespace(ruleDefinition.getName(),null);
094            fail("should throw IllegalArgumentException: namespace is null or blank");
095        } catch (IllegalArgumentException e) {
096            // IllegalArgumentException: namespace is null or blank
097        }
098
099        // try getRuleByNameAndNamespace with blank namespace parameter
100        try {
101            ruleManagementService.getRuleByNameAndNamespace(ruleDefinition.getName(),"    ");
102            fail("should throw IllegalArgumentException: namespace is null or blank");
103        } catch (IllegalArgumentException e) {
104            // IllegalArgumentException: namespace is null or blank
105        }
106
107
108    }
109
110    /**
111     *  Test testCreateRule()
112     *
113     *  This test focuses specifically on the RuleManagementServiceImpl .createRule(RuleDefinition) method
114     */
115    @Test
116    public void testCreateRule() {
117        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
118        RuleManagementBaseTestObjectNames t1 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t1");
119
120        // create a Rule
121        RuleDefinition ruleFirstCreate = buildTestRuleDefinition(t1.namespaceName, t1.object0);
122        assertTrue("created Rule not found", ruleManagementService.getRule(ruleFirstCreate.getId()).getId().contains(t1.rule_0_Id));
123
124        // try to create a duplicate Rule
125        try {
126            RuleDefinition ruleSecondCreate = ruleManagementService.createRule(ruleFirstCreate);
127            fail("should have thrown RiceIllegalArgumentException");
128        } catch (RiceIllegalArgumentException e) {
129            //  throw new RiceIllegalArgumentException(ruleDefinition.getId());
130        }
131
132        // try to create a malformed Rule
133        RuleDefinition malformedRule = buildTestRuleDefinition(t1.namespaceName, t1.object1);
134        RuleDefinition.Builder builder = RuleDefinition.Builder.create(malformedRule);
135        builder.setPropId("invalidValue");
136        malformedRule =  builder.build();
137        try {
138            ruleManagementService.createRule(malformedRule);
139            fail("should have thrown RiceIllegalArgumentException");
140        } catch (RiceIllegalArgumentException e) {
141            // throw new RiceIllegalArgumentException("propId does not match proposition.getId"
142        }
143    }
144
145    /**
146     *  Test testUpdateRule()
147     *
148     *  This test focuses specifically on the RuleManagementServiceImpl .updateRule(RuleDefinition) method
149     */
150    @Test
151    public void testUpdateRule() {
152        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
153        RuleManagementBaseTestObjectNames t2 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t2");
154
155        // build a rule to test with
156        RuleDefinition.Builder ruleBuilder0 = RuleDefinition.Builder.create(buildTestRuleDefinition(t2.namespaceName,
157                t2.object0));
158
159        // update the rule's Name
160        ruleBuilder0.setName("updatedName");
161        ruleManagementService.updateRule(ruleBuilder0.build());
162
163        // verify update
164        RuleDefinition rule0 = ruleManagementService.getRule(t2.rule_0_Id);
165        assertNotEquals("Rule Name Not Updated", t2.rule_0_Name, rule0.getName());
166        assertEquals("Rule Name Not Updated", "updatedName", rule0.getName());
167
168        // build new rule for test
169        RuleDefinition.Builder ruleBuilder1 = RuleDefinition.Builder.create(buildTestRuleDefinition(t2.namespaceName,
170                t2.object1));
171        assertEquals("Expected Proposition not found in Rule",t2.proposition_1_Descr,ruleBuilder1.getProposition().getDescription());
172
173        // create new proposition to update rule with
174        String newPropId = "PropNewId";
175        PropositionDefinition prop = createTestSimpleProposition(t2.namespaceName, newPropId, "TSI_"+newPropId,
176                "ABC", "=", "java.lang.String", t2.rule_0_Id, "TSI_" + newPropId + "_Descr");
177        PropositionDefinition.Builder propBuilder = PropositionDefinition.Builder.create(prop);
178        ruleBuilder1.setPropId(newPropId);
179        ruleBuilder1.setProposition(propBuilder);
180
181        // Update Proposition in rule
182        ruleManagementService.updateRule(ruleBuilder1.build());
183        rule0 = ruleManagementService.getRule(ruleBuilder1.getId());
184        assertEquals("Expected Proposition not found in Rule","PropNewId_simple_proposition",rule0.getProposition().getDescription());
185
186        // build new rule for test
187        RuleDefinition.Builder ruleBuilder2 = RuleDefinition.Builder.create(buildTestRuleDefinition(t2.namespaceName,t2.object7));
188        createTestKrmsAttribute(t2.actionAttribute, t2.actionAttribute_Key, t2.namespaceName);
189        Map<String, String> attributes = new HashMap<String, String>();
190        attributes.put(t2.actionAttribute_Key, t2.actionAttribute_Value);
191        List<ActionDefinition.Builder> actionBuilders = new ArrayList<ActionDefinition.Builder>();
192        KrmsTypeDefinition krmsTypeDefinition = createKrmsActionTypeDefinition(t2.namespaceName);
193        ActionDefinition.Builder actionBuilder = ActionDefinition.Builder.create(t2.action_Id, t2.action_Name,
194                t2.namespaceName, krmsTypeDefinition.getId(), rule0.getId(), 1);
195        actionBuilder.setDescription(t2.action_Descr);
196        actionBuilder.setAttributes(attributes);
197        actionBuilders.add(actionBuilder);
198        ruleBuilder2.setActions(actionBuilders);
199        ruleManagementService.updateRule(ruleBuilder2.build());
200
201        // Update Action in rule
202        ruleBuilder2 = RuleDefinition.Builder.create(ruleManagementService.getRule(t2.rule_7_Id));
203        Map<String, String> newAttributes = new HashMap<String, String>();
204        newAttributes.put(t2.actionAttribute_Key, t2.actionAttribute1_Value);
205        for (ActionDefinition.Builder ruleActionBuilder : ruleBuilder2.getActions()) {
206            ruleActionBuilder.setAttributes(newAttributes);
207        }
208        ruleManagementService.updateRule(ruleBuilder2.build());
209        rule0 = ruleManagementService.getRule(t2.rule_7_Id);
210        assertEquals("Invalid AgendaItem Rule Actions count",1,rule0.getActions().size());
211        for (ActionDefinition action : rule0.getActions()) {
212            Map<String, Object> map = new HashMap<String, Object>();
213            map.put("actionId", action.getId());
214            Collection<ActionAttributeBo> actionAttributes = businessObjectService.findMatching(ActionAttributeBo.class, map);
215            assertEquals("Invalid AgendaItem Rule Actions attribute count",1,actionAttributes.size());
216            for (ActionAttributeBo actionAttribute : actionAttributes) {
217                String expectedAttribute = t2.actionAttribute1_Value;
218                String actualAttribute = actionAttribute.getValue();
219                assertEquals("Invalid AgendaItem Rule Actions attribute",expectedAttribute,actualAttribute);
220            }
221        }
222    }
223
224    /**
225     *  Test testDeleteRule()
226     *
227     *  This test focuses specifically on the RuleManagementServiceImpl .deleteRule("rule id") method
228     */
229    @Test
230    public void testDeleteRule() {
231        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
232        RuleManagementBaseTestObjectNames t3 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t3");
233
234        // create a Rule
235        RuleDefinition rule = buildTestRuleDefinition(t3.namespaceName, t3.object0);
236        assertTrue("created Rule not found", ruleManagementService.getRule(rule.getId()).getId().contains(t3.rule_0_Id));
237        String propositionId = rule.getPropId();
238        assertEquals("Proposition for Rule not found", t3.proposition_0_Descr,
239                ruleManagementService.getProposition(propositionId).getDescription());
240
241
242        ruleManagementService.deleteRule(rule.getId());
243
244        assertNull("Rule was not deleted", ruleManagementService.getRule(rule.getId()));
245
246        // make sure proposition was cleaned up when rule was deleted
247        try {
248            ruleManagementService.deleteProposition(propositionId);
249            fail("should fail with IllegalStateException: the Proposition to delete does not exists");
250        } catch (IllegalStateException e) {
251            // IllegalStateException: the Proposition to delete does not exists
252        }
253    }
254
255    /**
256     *  Test testFindRuleIds()
257     *
258     *  This test focuses specifically on the RuleManagementServiceImpl .findRuleIds( QueryByCriteria) method
259     */
260    @Test
261    public void testFindRuleIds() {
262        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
263        RuleManagementBaseTestObjectNames t4 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t4");
264
265        RuleDefinition rule0 = buildTestRuleDefinition(t4.namespaceName, t4.object0);
266        RuleDefinition rule1 = buildTestRuleDefinition(t4.namespaceName, t4.object1);
267        RuleDefinition rule2 = buildTestRuleDefinition(t4.namespaceName, t4.object2);
268        RuleDefinition rule3 = buildTestRuleDefinition(t4.namespaceName, t4.object3);
269        String ruleNameSpace = rule0.getNamespace();
270        List<String> ruleNames =  new ArrayList<String>();
271        ruleNames.add(rule0.getName());
272        ruleNames.add(rule1.getName());
273        ruleNames.add(rule2.getName());
274        ruleNames.add(rule3.getName());
275
276        QueryByCriteria.Builder builder = QueryByCriteria.Builder.create();
277
278        builder.setPredicates(equal("namespace", ruleNameSpace), in("name", ruleNames.toArray(new String[]{})));
279
280        List<String> ruleIds = ruleManagementService.findRuleIds(builder.build());
281        assertEquals("Wrong number of RuleIds returned", 4, ruleIds.size());
282
283        if(!ruleIds.contains(rule0.getId())){
284            fail("RuleId not found in results");
285        }
286    }
287
288    /**
289     *  Test testGetRule()
290     *
291     *  This test focuses specifically on the RuleManagementServiceImpl .getRule("rule id") method
292     */
293    @Test
294    public void testGetRule() {
295        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
296        RuleManagementBaseTestObjectNames t5 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t5");
297
298        // create a rule to test with
299        RuleDefinition ruleDefinition = buildTestRuleDefinition(t5.namespaceName, t5.object0);
300
301        assertNotNull(ruleManagementService.getRule(ruleDefinition.getId()));
302
303        assertNull("Should have returned null", ruleManagementService.getRule(null));
304        assertNull("Should have returned null", ruleManagementService.getRule("   "));
305        assertNull("Should have returned null", ruleManagementService.getRule("badValueId"));
306    }
307
308    /**
309     *  Test testGetRules()
310     *
311     *  This test focuses specifically on the RuleManagementServiceImpl .getRules(List<String> ruleIds) method
312     */
313    @Test
314    public void testGetRules() {
315        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
316        RuleManagementBaseTestObjectNames t6 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t6");
317
318        // build two rules for testing
319        buildTestRuleDefinition(t6.namespaceName, t6.object0);
320        buildTestRuleDefinition(t6.namespaceName, t6.object1);
321
322        // build List rule ids for the rules created
323        List<String> ruleIds = new ArrayList<String>();
324        ruleIds.add(t6.rule_0_Id);
325        ruleIds.add(t6.rule_1_Id);
326
327        // get test rules by List of rule ids
328        List<RuleDefinition> ruleDefinitions = ruleManagementService.getRules(ruleIds);
329        assertEquals("Two RuleDefintions should have been returned",2,ruleDefinitions.size());
330
331        for(RuleDefinition ruleDefinition : ruleDefinitions) {
332            if (!ruleIds.contains(ruleDefinition.getId())) {
333                fail("Invalid RuleDefinition returned");
334            }
335        }
336
337        try {
338            ruleManagementService.getRules(null);
339            fail("Should have failed with RiceIllegalArgumentException: ruleIds must not be null");
340        } catch (RiceIllegalArgumentException e) {
341            // throws RiceIllegalArgumentException: ruleIds must not be null
342        }
343
344        assertEquals("No RuleDefinitions should have been returned",0,
345                ruleManagementService.getRules(new ArrayList<String>()).size());
346
347        ruleIds = Arrays.asList("badValueId");
348        assertEquals("No RuleDefinitions should have been returned",0, ruleManagementService.getRules(ruleIds).size());
349    }
350
351    /**
352     * Tests whether the {@code RuleDefinition} cache is being evicted properly by checking the status the dependent
353     * objects before and after creating an {@code RuleDefinition} (and consequently emptying the cache).
354     *
355     * <p>
356     * The following object caches are affected:
357     * {@code RuleDefinition}, {@code PropositionDefinition}, {@code ActionDefinition}, {@code AgendaItemDefinition}
358     * </p>
359     */
360    @Test
361    public void testRuleCacheEvict() {
362        // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
363        RuleManagementBaseTestObjectNames t7 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t7");
364
365        verifyEmptyRule(t7);
366
367        String ruleId = buildTestRuleDefinition(t7.namespaceName, t7.object0).getId();
368        buildTestActionDefinition(t7.action_Id, t7.action_Name, t7.action_Descr, 1, ruleId, t7.namespaceName);
369        String agendaId = createTestAgenda(t7.object0).getId();
370        buildTestAgendaItemDefinition(t7.agendaItem_Id, agendaId, ruleId);
371
372        verifyFullRule(t7);
373    }
374
375    private void verifyEmptyRule(RuleManagementBaseTestObjectNames t) {
376        RuleDefinition rule = ruleManagementService.getRule(t.rule_Id);
377        assertNull("Rule is not null", rule);
378
379        Set<PropositionDefinition> propositions = ruleManagementService.getPropositionsByRule(t.rule_Id);
380        assertFalse("Rule in Proposition found", propositions != null && !propositions.isEmpty());
381
382        ActionDefinition action = ruleManagementService.getAction(t.action_Id);
383        assertFalse("Rule in Action found", action != null);
384
385        AgendaItemDefinition agendaItem = ruleManagementService.getAgendaItem(t.agendaItem_Id);
386        assertFalse("Rule in AgendaItem found", agendaItem != null);
387    }
388
389    private void verifyFullRule(RuleManagementBaseTestObjectNames t) {
390        RuleDefinition rule = ruleManagementService.getRule(t.rule_Id);
391        assertNotNull("Rule is null", rule);
392
393        boolean foundRule = false;
394        Set<PropositionDefinition> propositions = ruleManagementService.getPropositionsByRule(t.rule_Id);
395        if (propositions != null) {
396            for (PropositionDefinition proposition : propositions) {
397                if (StringUtils.equals(t.rule_Id, proposition.getRuleId())) {
398                    foundRule = true;
399                    break;
400                }
401            }
402        }
403        assertTrue("Rule in Proposition not found", foundRule);
404
405        ActionDefinition action = ruleManagementService.getAction(t.action_Id);
406        assertTrue("Rule in Action not found", action != null);
407        assertTrue("Rule in Action not found", StringUtils.equals(t.rule_Id, action.getRuleId()));
408
409        AgendaItemDefinition agendaItem = ruleManagementService.getAgendaItem(t.agendaItem_Id);
410        assertTrue("Rule in AgendaItem not found", agendaItem != null);
411        assertTrue("Rule in AgendaItem not found", StringUtils.equals(t.rule_Id, agendaItem.getRuleId()));
412    }
413}