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    
017    package org.kuali.rice.krms.test;
018    
019    import org.apache.commons.lang.StringUtils;
020    import org.junit.Before;
021    import org.junit.Test;
022    import org.kuali.rice.core.api.criteria.QueryByCriteria;
023    import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
024    import org.kuali.rice.krms.api.repository.LogicalOperator;
025    import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
026    import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
027    import org.kuali.rice.krms.api.repository.proposition.PropositionType;
028    import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
029    
030    import java.util.ArrayList;
031    import java.util.Arrays;
032    import java.util.List;
033    import java.util.Set;
034    
035    import static org.junit.Assert.*;
036    import static org.kuali.rice.core.api.criteria.PredicateFactory.equal;
037    
038    /**
039     *   RuleManagementPropositionDefinitionTest is to test the methods of ruleManagementServiceImpl relating to PropositionDefinitions
040     *
041     *   Each test focuses on one of the methods.
042     */
043    public class RuleManagementPropositionDefinitionTest extends RuleManagementBaseTest {
044        @Override
045        @Before
046        public void setClassDiscriminator() {
047            // set a unique class discriminator for test objects of this class
048            CLASS_DISCRIMINATOR = "RMPDT";
049        }
050    
051        /**
052         *  Test testCreateProposition()
053         *
054         *  This test focuses specifically on the RuleManagementServiceImpl .createProposition(PropositionDefinition) method
055         */
056        @Test
057        public void testCreateProposition() {
058            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
059            RuleManagementBaseTestObjectNames t0 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t0");
060    
061            PropositionDefinition propositionDefinition = createTestSimpleProposition(
062                    t0.namespaceName, t0.proposition_0_Id, "campusCode", "BL", "=", "java.lang.String", t0.rule_0_Id, "Campus Code");
063    
064            assertEquals("created Proposition not found", t0.rule_0_Id, propositionDefinition.getRuleId());
065    
066            try {
067                // returnPropositionDefinition has existing propositionId
068                ruleManagementService.createProposition(propositionDefinition);
069                fail("should throw exception if trying to create and already exists");
070            } catch (RiceIllegalArgumentException e) {
071                //  throw new RiceIllegalArgumentException(propositionDefinition.getId());
072            }
073        }
074    
075        /**
076         *  Test testCompoundCreateProposition()
077         *
078         *  This test focuses specifically on the RuleManagementServiceImpl .createProposition(PropositionDefinition) method
079         */
080        @Test
081        public void testCompoundCreateProposition() {
082            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
083            RuleManagementBaseTestObjectNames t1 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t1");
084    
085            // **************************
086            // Create a complex Compound Proposition (True if Account is 54321 and Occasion is either a Conference or Training)
087            // ***************************
088            //  C1_compound_proposition            "COMPOUND" "S1_simple_proposition"  "C2_compound_proposition" "&"
089            //      S1_simple_proposition          "SIMPLE"   "Account"                "54321"                   "="
090            //      C2_compound_proposition        "COMPOUND" "S2_simple_proposition"  "S2_simple_proposition"   "|"
091            //          S2_simple_proposition      "SIMPLE"   "Occasion"               "Conference"              "="
092            //          S3_simple_proposition      "SIMPLE"   "Occasion"               "Training"                "="
093    
094            PropositionDefinition propS3 = createTestSimpleProposition(
095                    t1.namespaceName, "S3", "Occasion", "Training", "=", "java.lang.String", t1.rule_0_Id, "Special Event");
096            PropositionDefinition.Builder propBuilderS3 = PropositionDefinition.Builder.create(propS3);
097    
098            PropositionDefinition propS2 = createTestSimpleProposition(
099                    t1.namespaceName, "S2", "Occasion", "Conference", "=", "java.lang.String", t1.rule_0_Id, "Special Event");
100            PropositionDefinition.Builder propBuilderS2 = PropositionDefinition.Builder.create(propS2);
101    
102            PropositionDefinition propS1 = createTestSimpleProposition(
103                    t1.namespaceName, "S1", "Account", "54321", "=", "java.lang.String", t1.rule_0_Id, "Charged To Account");
104            PropositionDefinition.Builder propBuilderS1 = PropositionDefinition.Builder.create(propS1);
105    
106            PropositionDefinition.Builder propBuilderC2 = PropositionDefinition.Builder.create(
107                    null,PropositionType.COMPOUND.getCode(),t1.rule_0_Id,null,new ArrayList<PropositionParameter.Builder>());
108    
109            propBuilderC2.compoundOpCode(LogicalOperator.OR.getCode());
110            List<PropositionDefinition.Builder> compoundComponentsC2 = new ArrayList<PropositionDefinition.Builder>();
111            compoundComponentsC2.add(propBuilderS2);
112            compoundComponentsC2.add(propBuilderS3);
113            propBuilderC2.setCompoundComponents(compoundComponentsC2);
114            propBuilderC2.setDescription("C2_compound_proposition");
115    
116            PropositionDefinition.Builder propBuilderC1 = PropositionDefinition.Builder.create(
117                    null,PropositionType.COMPOUND.getCode(),t1.rule_0_Id,null,new ArrayList<PropositionParameter.Builder>());
118    
119            propBuilderC1.compoundOpCode(LogicalOperator.AND.getCode());
120            List<PropositionDefinition.Builder> compoundComponentsC1 = new ArrayList<PropositionDefinition.Builder>();
121            compoundComponentsC1.add(propBuilderS1);
122            compoundComponentsC1.add(propBuilderC2);
123            propBuilderC1.setCompoundComponents(compoundComponentsC1);
124            propBuilderC1.setDescription("C1_compound_proposition");
125            PropositionDefinition propC1 = ruleManagementService.createProposition(propBuilderC1.build());
126    
127            propC1 = ruleManagementService.getProposition(propC1.getId());
128            assertEquals("proposition not in database","C1_compound_proposition",propC1.getDescription());
129    
130            List<String> propositionDescrs = Arrays.asList("C1_compound_proposition", "C2_compound_proposition",
131                    "S1_simple_proposition", "S2_simple_proposition", "S3_simple_proposition");
132    
133            Set<PropositionDefinition> propsFound = ruleManagementService.getPropositionsByRule(t1.rule_0_Id);
134            for (PropositionDefinition propTemp : propsFound) {
135                assertTrue(propositionDescrs.contains(propTemp.getDescription()));
136            }
137    
138            assertEquals("invalid number of propositions found for ruleId", 5, propsFound.size());
139        }
140    
141        /**
142         *  Test testGetProposition()
143         *
144         *  This test focuses specifically on the RuleManagementServiceImpl .getProposition("proposition id") method
145         */
146        @Test
147        public void testGetProposition() {
148            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
149            RuleManagementBaseTestObjectNames t2 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t2");
150    
151            PropositionDefinition propositionDefinition = createTestPropositionForRule(t2.object0);
152    
153            PropositionDefinition returnPropositionDefinition = ruleManagementService.getProposition(propositionDefinition.getId());
154    
155            //  match ruleIds from returned proposition returned by get by propositionId
156            assertEquals("", propositionDefinition.getRuleId(), returnPropositionDefinition.getRuleId());
157    
158            try {
159                ruleManagementService.getProposition(null);
160                fail("should throw RiceIllegalArgumentException");
161            } catch (RiceIllegalArgumentException e) {
162                // throw new RiceIllegalArgumentException (id);
163            }
164        }
165    
166        /**
167         *  Test testGetPropositionsByType()
168         *
169         *  This test focuses specifically on the RuleManagementServiceImpl .getPropositionsByType("proposition type id") method
170         */
171        @Test
172        public void testGetPropositionsByType() {
173            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
174            RuleManagementBaseTestObjectNames t3 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t3");
175    
176            PropositionDefinition propositionDefinition = createTestPropositionForRule(t3.object0);
177    
178            Set<PropositionDefinition> propositionDefinitionSet = ruleManagementService.getPropositionsByType(propositionDefinition.getTypeId());
179    
180            boolean propositionFound = false;
181            for ( PropositionDefinition pd : propositionDefinitionSet ) {
182                if (pd.getId().equals(propositionDefinition.getId())){
183                    assertEquals("unexpected PropositionTypeId returned",propositionDefinition.getTypeId(),pd.getTypeId());
184                    propositionFound = true;
185                }
186            }
187    
188            assertTrue("proposition not found by PropositionTypeId",propositionFound);
189        }
190    
191        /**
192         *  Test testGetPropositionsByRule()
193         *
194         *  This test focuses specifically on the RuleManagementServiceImpl .getPropositionsByRule("rule id") method
195         */
196        @Test
197        public void testGetPropositionsByRule() {
198            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
199            RuleManagementBaseTestObjectNames t4 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t4");
200    
201            PropositionDefinition propositionDefinition = createTestPropositionForRule(t4.object0);
202    
203            Set<PropositionDefinition> propositionDefinitionSet = ruleManagementService.getPropositionsByRule(
204                    propositionDefinition.getRuleId());
205    
206            boolean propositionFound = false;
207            for ( PropositionDefinition pd : propositionDefinitionSet ) {
208                if (pd.getId().equals(propositionDefinition.getId())){
209                    propositionFound = true;
210                }
211            }
212    
213            assertTrue("proposition not found by RuleId",propositionFound);
214        }
215    
216        /**
217         *  Test testUpdateProposition()
218         *
219         *  This test focuses specifically on the RuleManagementServiceImpl .updateProposition(PropositionDefinition) method
220         */
221        @Test
222        public void testUpdateProposition() {
223            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
224            RuleManagementBaseTestObjectNames t5 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t5");
225    
226            PropositionDefinition propositionDefinition = createTestPropositionForRule(t5.object0);
227            PropositionDefinition.Builder builder = PropositionDefinition.Builder.create(propositionDefinition);
228            builder.setDescription("UpdatedDescription");
229            builder.setPropositionTypeCode(PropositionType.COMPOUND.getCode());
230    
231            // focus of test is on this instruction
232            ruleManagementService.updateProposition(builder.build());
233    
234            PropositionDefinition returnPropositionDefinition = ruleManagementService.getProposition(propositionDefinition.getId());
235    
236            assertEquals("description was not updated", "UpdatedDescription", returnPropositionDefinition.getDescription());
237            assertEquals("propositionType was not updated", PropositionType.COMPOUND.getCode(), returnPropositionDefinition.getPropositionTypeCode());
238        }
239    
240        /**
241         *  Test testDeleteProposition()
242         *
243         *  This test focuses specifically on the RuleManagementServiceImpl .deleteProposition("proposition id") method
244         */
245        @Test
246        public void testDeleteProposition() {
247            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
248            RuleManagementBaseTestObjectNames t6 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t6");
249    
250            PropositionDefinition propositionDefinition = createTestPropositionForRule(t6.object0);
251    
252            ruleManagementService.deleteProposition(propositionDefinition.getId());
253    
254            assertTrue("proposition should have been deleted", ruleManagementService.getPropositionsByRule(propositionDefinition.getRuleId()).isEmpty());
255    
256            try {
257                ruleManagementService.deleteProposition(propositionDefinition.getId());
258                fail("should fail with IllegalStateException: the Proposition to delete does not exists");
259            } catch (IllegalStateException e) {
260                // IllegalStateException: the Proposition to delete does not exists
261            }
262        }
263    
264        /**
265         *  Test testFindPropositionIds()
266         *
267         *  This test focuses specifically on the RuleManagementServiceImpl .findPropositionIds(QueryByCriteria) method
268         */
269        @Test
270        public void testFindPropositionIds() {
271            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
272            RuleManagementBaseTestObjectNames t6 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t6");
273    
274            List<String> propositionIds = Arrays.asList(
275                    createTestPropositionForRule(t6.object0).getId(),
276                    createTestPropositionForRule(t6.object1).getId(),
277                    createTestPropositionForRule(t6.object2).getId(),
278                    createTestPropositionForRule(t6.object3).getId());
279    
280            for (String propositionId : propositionIds) {
281                PropositionDefinition.Builder builder = PropositionDefinition.Builder.create(
282                        ruleManagementService.getProposition(propositionId));
283                builder.setDescription("targetOfQuery");
284                ruleManagementService.updateProposition(builder.build());
285            }
286    
287            QueryByCriteria.Builder query = QueryByCriteria.Builder.create();
288            query.setPredicates(equal("description", "targetOfQuery"));
289    
290            List<String> returnedPropositionIds = ruleManagementService.findPropositionIds(query.build());
291    
292            for (String returnedPropositionId : returnedPropositionIds ) {
293                assertTrue(propositionIds.contains(returnedPropositionId));
294            }
295    
296            assertEquals("incorrect number of Propositions found", 4, returnedPropositionIds.size());
297        }
298    
299        /**
300         * Tests whether the {@code PropositionDefinition} cache is being evicted properly by checking the status the
301         * dependent objects before and after creating an {@code PropositionDefinition} (and consequently emptying the cache).
302         *
303         * <p>
304         * The following object caches are affected:
305         * {@code PropositionDefinition}, {@code RuleDefinition}
306         * </p>
307         */
308        @Test
309        public void testPropositionCacheEvict() {
310            // get a set of unique object names for use by this test (discriminator passed can be any unique value within this class)
311            RuleManagementBaseTestObjectNames t7 =  new RuleManagementBaseTestObjectNames( CLASS_DISCRIMINATOR, "t7");
312    
313            verifyEmptyProposition(t7);
314    
315            // Proposition is built as part of a Rule
316            buildTestRuleDefinition(t7.namespaceName, t7.object0);
317    
318            verifyFullProposition(t7);
319        }
320    
321        private void verifyEmptyProposition(RuleManagementBaseTestObjectNames t) {
322            Set<PropositionDefinition> propositions = ruleManagementService.getPropositionsByRule(t.rule_Id);
323            assertFalse("Proposition is not null", propositions != null && !propositions.isEmpty());
324    
325            RuleDefinition rule = ruleManagementService.getRule(t.rule_Id);
326            assertFalse("Proposition in Rule found", rule != null);
327        }
328    
329        private void verifyFullProposition(RuleManagementBaseTestObjectNames t) {
330            Set<PropositionDefinition> propositions = ruleManagementService.getPropositionsByRule(t.rule_Id);
331            assertTrue("Proposition is not null", propositions != null && !propositions.isEmpty());
332    
333            String propositionId = new ArrayList<PropositionDefinition>(propositions).get(0).getId();
334    
335            RuleDefinition rule = ruleManagementService.getRule(t.rule_Id);
336            assertTrue("Proposition in Rule not found", rule != null);
337            assertTrue("Proposition in Rule not found", StringUtils.equals(propositionId, rule.getPropId()));
338        }
339    }