View Javadoc

1   /**
2    * Copyright 2005-2012 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.student.krms.sample;
17  
18  import static junit.framework.Assert.assertFalse;
19  import static junit.framework.Assert.assertNotNull;
20  import static junit.framework.Assert.assertTrue;
21  
22  import java.util.ArrayList;
23  import java.util.Arrays;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.junit.Before;
30  import org.junit.Ignore;
31  import org.junit.Test;
32  import org.kuali.rice.krms.api.engine.EngineResults;
33  import org.kuali.rice.krms.api.engine.ExecutionOptions;
34  import org.kuali.rice.krms.api.engine.ExecutionFlag;
35  import org.kuali.rice.krms.api.engine.Facts;
36  import org.kuali.rice.krms.api.engine.SelectionCriteria;
37  import org.kuali.rice.krms.api.engine.Term;
38  import org.kuali.rice.krms.api.engine.TermResolver;
39  import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
40  import org.kuali.rice.krms.api.repository.context.ContextDefinition;
41  import org.kuali.rice.krms.framework.engine.Action;
42  import org.kuali.rice.krms.framework.engine.Agenda;
43  import org.kuali.rice.krms.framework.engine.AgendaTreeEntry;
44  import org.kuali.rice.krms.framework.engine.BasicAgenda;
45  import org.kuali.rice.krms.framework.engine.BasicAgendaTree;
46  import org.kuali.rice.krms.framework.engine.BasicAgendaTreeEntry;
47  import org.kuali.rice.krms.framework.engine.BasicContext;
48  import org.kuali.rice.krms.framework.engine.BasicRule;
49  import org.kuali.rice.krms.framework.engine.ComparableTermBasedProposition;
50  import org.kuali.rice.krms.framework.engine.expression.ComparisonOperator;
51  import org.kuali.rice.krms.framework.engine.Context;
52  import org.kuali.rice.krms.framework.engine.ContextProvider;
53  import org.kuali.rice.krms.framework.engine.Proposition;
54  import org.kuali.rice.krms.framework.engine.ProviderBasedEngine;
55  import org.kuali.rice.krms.framework.engine.ResultLogger;
56  import org.kuali.rice.krms.framework.engine.Rule;
57  import org.kuali.rice.krms.framework.engine.expression.ComparisonOperatorServiceImpl;
58  import org.kuali.rice.krms.impl.repository.AgendaBoService;
59  import org.kuali.rice.krms.impl.repository.ContextBoService;
60  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
61  import org.kuali.student.common.util.krms.ManualContextProvider;
62  import org.kuali.student.krms.KSKRMSConstants;
63  
64  public class AgendaTest {
65  	private static final ResultLogger LOG = ResultLogger.getInstance();
66  
67  	// totalCostTerm will resolve to the Integer value 5
68      private ComparisonOperator operatorGreaterThan;
69  	private Proposition trueProp;
70  	private Proposition falseProp;
71  //
72  	private AgendaBoService agendaBoService;
73  	protected ContextBoService contextRepository;
74  	
75  	@Before
76  	public void setUp() {
77  		agendaBoService = KrmsRepositoryServiceLocator.getAgendaBoService();
78  		contextRepository = KrmsRepositoryServiceLocator.getContextBoService();
79  		//
80          operatorGreaterThan = ComparisonOperator.GREATER_THAN;
81          operatorGreaterThan.setComparisonOperatorService(ComparisonOperatorServiceImpl.getInstance());
82          trueProp = new ComparableTermBasedProposition(operatorGreaterThan, totalCostTerm, Integer.valueOf(1));
83          falseProp = new ComparableTermBasedProposition(operatorGreaterThan, totalCostTerm, Integer.valueOf(1000));
84  
85  		ActionMock.resetActionsFired();
86  	}
87  
88  
89  	// @Test
90  	public void testAllRulesKSAgenda() {
91  
92  //		Rule rule1 = new BasicRule("r1", trueProp, Collections.<Action>singletonList(new ActionMock("a1")));
93  //		Rule rule2 = new BasicRule("r2", falseProp, Collections.<Action>singletonList(new ActionMock("a2")));
94  //		Rule rule3 = new BasicRule("r3", trueProp, Collections.<Action>singletonList(new ActionMock("a3")));
95  		
96  //		AgendaTreeEntry entry1 = new BasicAgendaTreeEntry(rule1);
97  //		AgendaTreeEntry entry2 = new BasicAgendaTreeEntry(rule2);
98  //		AgendaTreeEntry entry3 = new BasicAgendaTreeEntry(rule3);
99  //		BasicAgendaTree agendaTree = new BasicAgendaTree(entry1, entry2, entry3);
100 		
101 		ContextDefinition contextDef = getKRMSContext(KSKRMSConstants.CONTEXT_STUD_ELIGIBILITY);
102 		AgendaDefinition adgendaDef = getKRMSAgenda(KSKRMSConstants.AGENDA1, contextDef);
103 		assertNotNull(contextDef);
104 		assertNotNull(adgendaDef);
105 //		Agenda agenda = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree);
106 		
107 //		execute(agenda);
108 
109 //		assertTrue(ActionMock.actionFired("a1"));
110 //		assertFalse(ActionMock.actionFired("a2"));
111 //		assertTrue(ActionMock.actionFired("a3"));
112 	}
113 	
114 	// @Test
115 	public void testAllRulesAgenda() {
116 
117 		Rule rule1 = new BasicRule("r1", trueProp, Collections.<Action>singletonList(new ActionMock("a1")));
118 		Rule rule2 = new BasicRule("r2", falseProp, Collections.<Action>singletonList(new ActionMock("a2")));
119 		Rule rule3 = new BasicRule("r3", trueProp, Collections.<Action>singletonList(new ActionMock("a3")));
120 		
121 		AgendaTreeEntry entry1 = new BasicAgendaTreeEntry(rule1);
122 		AgendaTreeEntry entry2 = new BasicAgendaTreeEntry(rule2);
123 		AgendaTreeEntry entry3 = new BasicAgendaTreeEntry(rule3);
124 		BasicAgendaTree agendaTree = new BasicAgendaTree(entry1, entry2, entry3); 
125 		Agenda agenda = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree);
126 		
127 		execute(agenda);
128 
129 		assertTrue(ActionMock.actionFired("a1"));
130 		assertFalse(ActionMock.actionFired("a2"));
131 		assertTrue(ActionMock.actionFired("a3"));
132 	}
133 	
134 	//@Test
135 	public void testIfTrueSubAgenda() {
136 
137 		Rule rule1 = new BasicRule("r1", trueProp, Collections.<Action>singletonList(new ActionMock("a1")));
138 		Rule rule2 = new BasicRule("r2", falseProp, Collections.<Action>singletonList(new ActionMock("a2")));
139 		Rule subRule1 = new BasicRule("r1s1", trueProp, Collections.<Action>singletonList(new ActionMock("a3")));
140 		
141 		BasicAgendaTree subAgendaTree1 = new BasicAgendaTree(new BasicAgendaTreeEntry(subRule1));
142 		BasicAgendaTree agendaTree1 = new BasicAgendaTree(new BasicAgendaTreeEntry(rule1, subAgendaTree1, null)); 
143 		Agenda agenda1 = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree1);
144 		
145 		execute(agenda1);
146 
147 		assertTrue(ActionMock.actionFired("a1"));
148 		assertTrue(ActionMock.actionFired("a3"));
149 		
150 		// RESET
151 		ActionMock.resetActionsFired();
152 		
153 		BasicAgendaTree subAgendaTree2 = new BasicAgendaTree(new BasicAgendaTreeEntry(subRule1));
154 		BasicAgendaTree agendaTree2 = new BasicAgendaTree(new BasicAgendaTreeEntry(rule2, subAgendaTree2, null)); 
155 		Agenda agenda2 = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree2);
156 		
157 		execute(agenda2);
158 
159 		assertFalse(ActionMock.actionFired("a2"));
160 		assertFalse(ActionMock.actionFired("a3"));
161 	}
162 
163 	//@Test
164 	public void testIfFalseSubAgenda() {
165 
166 		Rule rule1 = new BasicRule("r1", trueProp, Collections.<Action>singletonList(new ActionMock("a1")));
167 		Rule rule2 = new BasicRule("r2", falseProp, Collections.<Action>singletonList(new ActionMock("a2")));
168 		Rule subRule1 = new BasicRule("r1s1", trueProp, Collections.<Action>singletonList(new ActionMock("a3")));
169 		
170 		BasicAgendaTree subAgendaTree1 = new BasicAgendaTree(new BasicAgendaTreeEntry(subRule1));
171 		BasicAgendaTree agendaTree1 = new BasicAgendaTree(new BasicAgendaTreeEntry(rule1, null, subAgendaTree1)); 
172 		Agenda agenda1 = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree1);
173 		
174 		execute(agenda1);
175 
176 		assertTrue(ActionMock.actionFired("a1"));
177 		assertFalse(ActionMock.actionFired("a3"));
178 		
179 		// RESET
180 		ActionMock.resetActionsFired();
181 		
182 		BasicAgendaTree subAgendaTree2 = new BasicAgendaTree(new BasicAgendaTreeEntry(subRule1));
183 		BasicAgendaTree agendaTree2 = new BasicAgendaTree(new BasicAgendaTreeEntry(rule2, null, subAgendaTree2)); 
184 		Agenda agenda2 = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree2);
185 		
186 		execute(agenda2);
187 
188 		assertFalse(ActionMock.actionFired("a2"));
189 		assertTrue(ActionMock.actionFired("a3"));
190 	}
191 	
192 	@Test
193 	public void testAfterAgenda() {
194 
195 		Rule rule1 = new BasicRule("r1", trueProp, Collections.<Action>singletonList(new ActionMock("a1")));
196 		Rule rule2 = new BasicRule("r2", falseProp, Collections.<Action>singletonList(new ActionMock("a2")));
197 		Rule subRule1 = new BasicRule("r1s1", trueProp, Collections.<Action>singletonList(new ActionMock("a3")));
198 		
199 		BasicAgendaTree agendaTree1 = new BasicAgendaTree(new BasicAgendaTreeEntry(rule1), new BasicAgendaTreeEntry(subRule1)); 
200 		Agenda agenda1 = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree1);
201 		
202 		execute(agenda1);
203 
204 		assertTrue(ActionMock.actionFired("a1"));
205 		assertTrue(ActionMock.actionFired("a3"));
206 		
207 		// RESET
208 		ActionMock.resetActionsFired();
209 		
210 		BasicAgendaTree agendaTree2 = new BasicAgendaTree(new BasicAgendaTreeEntry(rule2), new BasicAgendaTreeEntry(subRule1)); 
211 		Agenda agenda2 = new BasicAgenda(Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"), agendaTree2);
212 		
213 		execute(agenda2);
214 
215 		assertFalse(ActionMock.actionFired("a2"));
216 		assertTrue(ActionMock.actionFired("a3"));
217 	}
218 
219     /**
220      * Make sure agenda qualifier matching is based on the provided qualifiers
221      * see https://jira.kuali.org/browse/KULRICE-6098
222      */
223     public void testQualifierMissingFromAgenda() {
224         // RESET
225 		ActionMock.resetActionsFired();
226 
227         Rule rule1 = new BasicRule("r1", trueProp, Collections.<Action>singletonList(new ActionMock("a1")));
228 
229         BasicAgendaTree agendaTree1 = new BasicAgendaTree(new BasicAgendaTreeEntry(rule1));
230         Agenda agenda1 = new BasicAgenda(Collections.<String, String>emptyMap(), agendaTree1);
231 
232         // this shouldn't select any agendas, so no rules will really get executed
233         execute(agenda1, Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"));
234 
235         // Expected: the agenda didn't get selected, so the action didn't fire
236         assertFalse("the agenda should not have been selected and executed", ActionMock.actionFired("a1"));
237     }
238 
239     /**
240      * execute the engine against a trivial context containing the given agenda.
241      * a default agenda qualifier of Event=test will be used.
242      * @param agenda
243      */
244     private void execute(Agenda agenda) {
245         execute(agenda, Collections.singletonMap(AgendaDefinition.Constants.EVENT, "test"));
246     }
247 
248     /**
249      * execute the engine against a trivial context containing the given agenda.
250      * the given agenda qualifier will be used.
251      * @param agenda
252      * @param agendaQualifiers
253      */
254 	private void execute(Agenda agenda, Map<String, String> agendaQualifiers) {
255 		Map<String, String> contextQualifiers = new HashMap<String, String>();
256 		contextQualifiers.put("docTypeName", "Proposal");
257 
258 		List<TermResolver<?>> testResolvers = new ArrayList<TermResolver<?>>();
259 		testResolvers.add(testResolver);
260 		
261 		Context context = new BasicContext(Arrays.asList(agenda), testResolvers);
262 		ContextProvider contextProvider = new ManualContextProvider(context);
263 		
264 		SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(null, contextQualifiers,
265                 agendaQualifiers);
266 		
267 		ProviderBasedEngine engine = new ProviderBasedEngine();
268 		engine.setContextProvider(contextProvider);
269 
270 		// Set execution options to log execution
271 		ExecutionOptions executionOptions = new ExecutionOptions().setFlag(ExecutionFlag.LOG_EXECUTION, true);
272 		
273 		EngineResults results = engine.execute(selectionCriteria, Facts.EMPTY_FACTS, executionOptions);
274 		assertNotNull(results);
275 	}
276 	
277 	private static final Term totalCostTerm = new Term("totalCost");
278 	
279 	private static final TermResolver<Integer> testResolver = new TermResolverMock<Integer>(totalCostTerm.getName(), 10);
280 
281 	private AgendaDefinition getKRMSAgenda(String agendaName, ContextDefinition contextDef) {
282 		AgendaDefinition agendaDef = agendaBoService
283 				.getAgendaByNameAndContextId(agendaName,
284 						contextDef.getId());
285 		return agendaDef;
286 	}
287 
288 	private ContextDefinition getKRMSContext(String context) {
289 		return contextRepository.getContextByNameAndNamespace(
290 				context, KSKRMSConstants.KSNAMESPACE);
291 	}
292 }