View Javadoc

1   /**
2    * Copyright 2005-2011 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.krms.test;
17  
18  import org.joda.time.DateTime;
19  import org.junit.Before;
20  import org.junit.Test;
21  import org.kuali.rice.kew.util.PerformanceLogger;
22  import org.kuali.rice.krms.api.KrmsApiServiceLocator;
23  import org.kuali.rice.krms.api.engine.EngineResults;
24  import org.kuali.rice.krms.api.engine.ExecutionFlag;
25  import org.kuali.rice.krms.api.engine.ExecutionOptions;
26  import org.kuali.rice.krms.api.engine.Facts;
27  import org.kuali.rice.krms.api.engine.ResultEvent;
28  import org.kuali.rice.krms.api.engine.SelectionCriteria;
29  import org.kuali.rice.krms.api.repository.LogicalOperator;
30  import org.kuali.rice.krms.api.repository.action.ActionDefinition;
31  import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
32  import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
33  import org.kuali.rice.krms.api.repository.context.ContextDefinition;
34  import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
35  import org.kuali.rice.krms.api.repository.function.FunctionParameterDefinition;
36  import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
37  import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
38  import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
39  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
40  import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
41  import org.kuali.rice.krms.api.repository.term.TermDefinition;
42  import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
43  import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
44  import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
45  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
46  import org.kuali.rice.krms.impl.repository.ActionBoService;
47  import org.kuali.rice.krms.impl.repository.AgendaBoService;
48  import org.kuali.rice.krms.impl.repository.FunctionBoServiceImpl;
49  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
50  import org.kuali.rice.krms.impl.repository.RuleBoService;
51  import org.kuali.rice.krms.impl.repository.TermBo;
52  import org.kuali.rice.krms.impl.repository.TermBoService;
53  import org.kuali.rice.test.BaselineTestCase.BaselineMode;
54  import org.kuali.rice.test.BaselineTestCase.Mode;
55  import org.springframework.transaction.annotation.Transactional;
56  
57  import java.util.ArrayList;
58  import java.util.Collections;
59  import java.util.HashMap;
60  import java.util.List;
61  import java.util.Map;
62  
63  import static org.junit.Assert.*;
64  
65  @BaselineMode(Mode.CLEAR_DB)
66  public class RepositoryCreateAndExecuteIntegrationTest extends AbstractBoTest {
67  
68      public static final String CAMPUS_CODE_TERM_NAME = "campusCodeTermSpec";
69  
70      static final String NAMESPACE1 = "KRMS_TEST_1";
71      static final String NAMESPACE2 = "KRMS_TEST_2";
72      static final String TSUNAMI_EVENT = "Tsunami";
73      static final String EARTHQUAKE_EVENT = "Earthquake";
74      static final String CONTEXT1 = "Context1";
75      static final String CONTEXT2 = "Context2";
76      static final String CONTEXT3 = "Context3";
77      static final String NAME = "name";
78      static final String CONTEXT1_QUALIFIER = "Context1Qualifier";
79      static final String CONTEXT1_QUALIFIER_VALUE = "BLAH1";
80      static final String CONTEXT2_QUALIFIER = "Context2Qualifier";
81      static final String CONTEXT2_QUALIFIER_VALUE = "BLAH2";
82      static final String AGENDA1 = "TestAgenda1";
83      static final String AGENDA2 = "Agenda2";
84      static final String AGENDA3 = "Agenda3";
85      static final String AGENDA4 = "Agenda4";
86      static final String AGENDA5 = "Agenda5";
87      static final String PREREQ_TERM_NAME = "prereqTermSpec";
88      static final String PREREQ_TERM_VALUE = "prereqValue";
89      static final String NAMESPACE_CODE = "namespaceCode";
90      static final String BOOL1 = "bool1";
91      static final String BOOL2 = "bool2";
92      static final String NULL_FACT = "nullFact";
93  
94  //    // Services needed for creation:
95  	private TermBoService termBoService;
96  
97      private RuleBoService ruleBoService;
98      private AgendaBoService agendaBoService;
99      private ActionBoService actionBoService;
100     private FunctionBoServiceImpl functionBoService;
101 
102     /**
103      *
104      * Setting it up so that KRMS tables are not reset between test methods to make it run much faster
105      *
106      * @return
107      */
108     protected List<String> getPerTestTablesNotToClear() {
109         List<String> tablesNotToClear = super.getPerTestTablesNotToClear();
110 
111         tablesNotToClear.add("KRMS_.*");
112 
113         return tablesNotToClear;
114     }
115 
116 
117 
118 	@Before
119     public void setup() {
120         // Reset TestActionTypeService
121         TestActionTypeService.resetActionsFired();
122 
123         termBoService = KrmsRepositoryServiceLocator.getTermBoService();
124         contextRepository = KrmsRepositoryServiceLocator.getContextBoService();
125         krmsTypeRepository = KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService();
126 
127         ruleBoService = KrmsRepositoryServiceLocator.getRuleBoService();
128         agendaBoService = KrmsRepositoryServiceLocator.getAgendaBoService();
129         actionBoService = KrmsRepositoryServiceLocator.getBean("actionBoService");
130         functionBoService = KrmsRepositoryServiceLocator.getBean("functionRepositoryService");
131         krmsAttributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
132 
133         ContextDefinition contextDefintion1 = contextRepository.getContextByNameAndNamespace(CONTEXT1, NAMESPACE1);
134 
135         // only set this stuff up if we don't already have Context1 (we don't clear out KRMS tables between test methods)
136         if (contextDefintion1 == null) {
137             PerformanceLogger perfLog = new PerformanceLogger();
138             perfLog.log("starting agenda creation");
139 
140             contextDefintion1 = createContextDefinition(NAMESPACE1, CONTEXT1, Collections.singletonMap(
141                     CONTEXT1_QUALIFIER, CONTEXT1_QUALIFIER_VALUE));
142             createAgendaDefinition(AGENDA1, contextDefintion1, TSUNAMI_EVENT, NAMESPACE1);
143 
144             ContextDefinition contextDefinition2 = createContextDefinition(NAMESPACE2, CONTEXT2, Collections.singletonMap(
145                     CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE));
146 
147             ContextDefinition contextDefinition3 = createContextDefinition(NAMESPACE1, CONTEXT3,
148                     Collections.<String,String>emptyMap());
149 
150             // Create multiple agendas so that we can test selection
151             createAgendaDefinition(AGENDA2, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2);
152             createAgendaDefinition(AGENDA3, contextDefinition2, EARTHQUAKE_EVENT, NAMESPACE2);
153             createAgendaDefinition(AGENDA4, contextDefinition2, TSUNAMI_EVENT, NAMESPACE2);
154             createAgendaDefinition2(AGENDA5, contextDefinition3, NAMESPACE1);
155 
156             perfLog.log("finished agenda creation", true);
157         }
158     }
159 
160     @Transactional
161     @Test
162     public void testNullFact() {
163 
164         Map<String,String> contextQualifiers = new HashMap<String,String>();
165         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE1);
166         contextQualifiers.put(NAME, CONTEXT3);
167 
168         Map<String,String> agendaQualifiers = new HashMap<String,String>();
169         agendaQualifiers.put(NAME, AGENDA5);
170 
171         DateTime now = new DateTime();
172 
173         SelectionCriteria sc1 = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
174 
175         Facts.Builder factsBuilder1 = Facts.Builder.create();
176         factsBuilder1.addFact(NULL_FACT, null);
177 
178         ExecutionOptions xOptions1 = new ExecutionOptions();
179         xOptions1.setFlag(ExecutionFlag.LOG_EXECUTION, true);
180 
181         PerformanceLogger perfLog = new PerformanceLogger();
182         perfLog.log("starting rule execution");
183         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(sc1, factsBuilder1.build(), xOptions1);
184         perfLog.log("finished rule execution", true);
185         List<ResultEvent> rEvents1 = eResults1.getAllResults();
186 
187         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
188 
189         assertEquals("1 rules should have been evaluated", 1, ruleEvaluationResults1.size());
190 
191         assertTrue("rule 0 should have evaluated to true", ruleEvaluationResults1.get(0).getResult());
192 
193         // ONLY agenda 5 should have been selected
194         assertTrue(TestActionTypeService.actionFired("Agenda5::Rule5::TestAction"));
195 
196         assertAgendaDidNotExecute(AGENDA1);
197         assertAgendaDidNotExecute(AGENDA2);
198         assertAgendaDidNotExecute(AGENDA3);
199         assertAgendaDidNotExecute(AGENDA4);
200     }    
201 
202     @Transactional
203     @Test
204     public void testSelectAgendaByAttributeAndName() {
205 
206         Map<String,String> contextQualifiers = new HashMap<String,String>();
207         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE1);
208         contextQualifiers.put(NAME, CONTEXT1);
209         contextQualifiers.put(CONTEXT1_QUALIFIER, CONTEXT1_QUALIFIER_VALUE);
210 
211         Map<String,String> agendaQualifiers = new HashMap<String,String>();
212         agendaQualifiers.put(AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT);
213         agendaQualifiers.put(NAME, AGENDA1);
214 
215         DateTime now = new DateTime();
216 
217         SelectionCriteria sc1 = SelectionCriteria.createCriteria(now, contextQualifiers,
218                 Collections.singletonMap(AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT));
219 
220         Facts.Builder factsBuilder1 = Facts.Builder.create();
221         factsBuilder1.addFact(CAMPUS_CODE_TERM_NAME, "BL");
222         factsBuilder1.addFact(BOOL1, "true");
223         factsBuilder1.addFact(BOOL2, Boolean.TRUE);
224         factsBuilder1.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
225 
226         ExecutionOptions xOptions1 = new ExecutionOptions();
227         xOptions1.setFlag(ExecutionFlag.LOG_EXECUTION, true);
228 
229         PerformanceLogger perfLog = new PerformanceLogger();
230         perfLog.log("starting rule execution");
231         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(sc1, factsBuilder1.build(), xOptions1);
232         perfLog.log("finished rule execution", true);
233         List<ResultEvent> rEvents1 = eResults1.getAllResults();
234 
235         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
236 
237         assertEquals("4 rules should have been evaluated", 4, ruleEvaluationResults1.size());
238 
239         assertTrue("rule 0 should have evaluated to true", ruleEvaluationResults1.get(0).getResult());
240         assertFalse("rule 1 should have evaluated to false", ruleEvaluationResults1.get(1).getResult());
241         assertTrue("rule 2 should have evaluated to true", ruleEvaluationResults1.get(2).getResult());
242 
243         // ONLY agenda 1 should have been selected
244         assertTrue(TestActionTypeService.actionFired("TestAgenda1::Rule1::TestAction"));
245         assertFalse(TestActionTypeService.actionFired("TestAgenda1::Rule2::TestAction"));
246         assertTrue(TestActionTypeService.actionFired("TestAgenda1::Rule3::TestAction"));
247 
248         assertAgendaDidNotExecute(AGENDA2);
249         assertAgendaDidNotExecute(AGENDA3);
250         assertAgendaDidNotExecute(AGENDA4);
251         assertAgendaDidNotExecute(AGENDA5);
252     }
253 
254     @Transactional
255     @Test
256     public void testSelectAgendaByName() {
257         Map<String,String> contextQualifiers = new HashMap<String,String>();
258         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2);
259         contextQualifiers.put(NAME, CONTEXT2);
260         contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE);
261         Map<String,String> agendaQualifiers = new HashMap<String,String>();
262 
263         /*
264          * We'll specifically NOT select this attribute to make sure that matching only takes place against qualifiers
265          * in the selection criteria
266          */
267         // agendaQualifiers.put(AgendaDefinition.Constants.EVENT, EARTHQUAKE_EVENT);
268 
269         agendaQualifiers.put(NAME, AGENDA3);
270         DateTime now = new DateTime();
271 
272         SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
273 
274         Facts.Builder factsBuilder2 = Facts.Builder.create();
275         factsBuilder2.addFact(BOOL1, "true");
276         factsBuilder2.addFact(BOOL2, Boolean.TRUE);
277         factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL");
278         factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
279 
280         ExecutionOptions xOptions2 = new ExecutionOptions();
281         xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true);
282 
283 
284         PerformanceLogger perfLog = new PerformanceLogger();
285         perfLog.log("starting rule execution 1");
286         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(selectionCriteria, factsBuilder2.build(), xOptions2);
287         perfLog.log("finished rule execution 1");
288         List<ResultEvent> rEvents1 = eResults1.getAllResults();
289 
290         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
291 
292         selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
293 
294         assertEquals("4 rules should have been evaluated", 4, ruleEvaluationResults1.size());
295 
296         assertAgendaDidNotExecute(AGENDA1);
297         assertAgendaDidNotExecute(AGENDA2);
298 
299         // ONLY agenda 3 should have been selected
300         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule1::TestAction"));
301         assertFalse(TestActionTypeService.actionFired("Agenda3::Rule2::TestAction"));
302         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule3::TestAction"));
303 
304         assertAgendaDidNotExecute(AGENDA4);
305         assertAgendaDidNotExecute(AGENDA5);
306     }
307 
308 
309     @Transactional
310     @Test
311     public void testSelectMultipleAgendasByAttribute() {
312         Map<String,String> contextQualifiers = new HashMap<String,String>();
313         contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2);
314         contextQualifiers.put(NAME, CONTEXT2);
315         contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE);
316 
317         Map<String,String> agendaQualifiers = new HashMap<String,String>();
318         agendaQualifiers.put(AgendaDefinition.Constants.EVENT, EARTHQUAKE_EVENT);
319 
320         DateTime now = new DateTime();
321 
322         SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
323 
324         Facts.Builder factsBuilder2 = Facts.Builder.create();
325         factsBuilder2.addFact(BOOL1, "true");
326         factsBuilder2.addFact(BOOL2, Boolean.TRUE);
327         factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL");
328         factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
329 
330         ExecutionOptions xOptions2 = new ExecutionOptions();
331         xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true);
332 
333 
334         PerformanceLogger perfLog = new PerformanceLogger();
335         perfLog.log("starting rule execution 1");
336         EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(selectionCriteria, factsBuilder2.build(), xOptions2);
337         perfLog.log("finished rule execution 1");
338         List<ResultEvent> rEvents1 = eResults1.getAllResults();
339 
340         List<ResultEvent> ruleEvaluationResults1 = eResults1.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
341 
342         selectionCriteria = SelectionCriteria.createCriteria(now, contextQualifiers, agendaQualifiers);
343 
344         assertEquals("8 rules should have been evaluated", 8, ruleEvaluationResults1.size());
345 
346         assertAgendaDidNotExecute(AGENDA1);
347 
348         // ONLY agendas 2 & 3 should have been selected
349 
350         assertTrue(TestActionTypeService.actionFired("Agenda2::Rule1::TestAction"));
351         assertFalse(TestActionTypeService.actionFired("Agenda2::Rule2::TestAction"));
352         assertTrue(TestActionTypeService.actionFired("Agenda2::Rule3::TestAction"));
353 
354         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule1::TestAction"));
355         assertFalse(TestActionTypeService.actionFired("Agenda3::Rule2::TestAction"));
356         assertTrue(TestActionTypeService.actionFired("Agenda3::Rule3::TestAction"));
357 
358         assertAgendaDidNotExecute(AGENDA4);
359         assertAgendaDidNotExecute(AGENDA5);
360     }
361 
362     private void assertAgendaDidNotExecute(String agendaName) {
363         assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule1::TestAction"));
364         assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule2::TestAction"));
365         assertFalse(TestActionTypeService.actionFired(agendaName+"::Rule3::TestAction"));
366     }
367 
368     private void createAgendaDefinition(String agendaName, ContextDefinition contextDefinition, String eventName, String nameSpace ) {
369         KrmsTypeDefinition krmsGenericTypeDefinition = createKrmsGenericTypeDefinition(nameSpace, "testAgendaTypeService", "event name", "Event");
370 
371         AgendaDefinition agendaDef =
372             AgendaDefinition.Builder.create(null, agendaName, krmsGenericTypeDefinition.getId(), contextDefinition.getId()).build();
373         agendaDef = agendaBoService.createAgenda(agendaDef);
374 
375         AgendaItemDefinition.Builder agendaItemBuilder1 = AgendaItemDefinition.Builder.create(null, agendaDef.getId());
376         agendaItemBuilder1.setRuleId(createRuleDefinition1(contextDefinition, agendaName, nameSpace).getId());
377 
378         AgendaItemDefinition.Builder agendaItemBuilder2 = AgendaItemDefinition.Builder.create(null, agendaDef.getId());
379         agendaItemBuilder1.setAlways(agendaItemBuilder2);
380         agendaItemBuilder2.setRuleId(createRuleDefinition2(contextDefinition, agendaName, nameSpace).getId());
381 
382         AgendaItemDefinition.Builder agendaItemBuilder3 = AgendaItemDefinition.Builder.create(null, agendaDef.getId());
383         agendaItemBuilder2.setAlways(agendaItemBuilder3);
384         agendaItemBuilder3.setRuleId(createRuleDefinition3(contextDefinition, agendaName, nameSpace).getId());
385 
386         AgendaItemDefinition.Builder agendaItemBuilder4 = AgendaItemDefinition.Builder.create(null, agendaDef.getId());
387         agendaItemBuilder3.setAlways(agendaItemBuilder4);
388         agendaItemBuilder4.setRuleId(createRuleDefinition4(contextDefinition, agendaName, nameSpace).getId());
389 
390         // String these puppies together.  Kind of a PITA because you need the id from the next item before you insert the previous one
391         AgendaItemDefinition agendaItem4 = agendaBoService.createAgendaItem(agendaItemBuilder4.build());
392         agendaItemBuilder3.setAlwaysId(agendaItem4.getId());
393         AgendaItemDefinition agendaItem3 = agendaBoService.createAgendaItem(agendaItemBuilder3.build());
394         agendaItemBuilder2.setAlwaysId(agendaItem3.getId());
395         AgendaItemDefinition agendaItem2 = agendaBoService.createAgendaItem(agendaItemBuilder2.build());
396         agendaItemBuilder1.setAlwaysId(agendaItem2.getId());
397         AgendaItemDefinition agendaItem1 = agendaBoService.createAgendaItem(agendaItemBuilder1.build());
398 
399         AgendaDefinition.Builder agendaDefBuilder1 = AgendaDefinition.Builder.create(agendaDef);
400         agendaDefBuilder1.setAttributes(Collections.singletonMap("Event", eventName));
401         agendaDefBuilder1.setFirstItemId(agendaItem1.getId());
402         agendaDef = agendaDefBuilder1.build();
403 
404         agendaBoService.updateAgenda(agendaDef);
405     }
406 
407     private void createAgendaDefinition2(String agendaName, ContextDefinition contextDefinition, String nameSpace ) {
408 
409         AgendaDefinition agendaDef =
410                 AgendaDefinition.Builder.create(null, agendaName, null, contextDefinition.getId()).build();
411         agendaDef = agendaBoService.createAgenda(agendaDef);
412 
413         AgendaItemDefinition.Builder agendaItemBuilder1 = AgendaItemDefinition.Builder.create(null, agendaDef.getId());
414         agendaItemBuilder1.setRuleId(createRuleDefinition5(contextDefinition, agendaName, nameSpace).getId());
415 
416         AgendaItemDefinition agendaItem1 = agendaBoService.createAgendaItem(agendaItemBuilder1.build());
417 
418         AgendaDefinition.Builder agendaDefBuilder1 = AgendaDefinition.Builder.create(agendaDef);
419         agendaDefBuilder1.setFirstItemId(agendaItem1.getId());
420         agendaDef = agendaDefBuilder1.build();
421 
422         agendaBoService.updateAgenda(agendaDef);
423     }
424 
425     private KrmsTypeDefinition createKrmsActionTypeDefinition(String nameSpace) {
426         String ACTION_TYPE_NAME = "KrmsActionResolverType";
427         KrmsTypeDefinition krmsActionTypeDefinition =  krmsTypeRepository.getTypeByName(nameSpace, ACTION_TYPE_NAME);
428 
429         if (krmsActionTypeDefinition == null) {
430             KrmsTypeDefinition.Builder krmsActionTypeDefnBuilder = KrmsTypeDefinition.Builder.create(ACTION_TYPE_NAME, nameSpace);
431             krmsActionTypeDefnBuilder.setServiceName("testActionTypeService");
432             krmsActionTypeDefinition = krmsTypeRepository.createKrmsType(krmsActionTypeDefnBuilder.build());
433         }
434 
435         return krmsActionTypeDefinition;
436     }
437     
438 
439     private RuleDefinition createRuleDefinition(String nameSpace, String ruleName, ContextDefinition contextDefinition,
440             LogicalOperator operator, PropositionParametersBuilder ... pbs) {
441         RuleDefinition.Builder ruleDefBuilder =
442                 RuleDefinition.Builder.create(null, ruleName, nameSpace, null, null);
443         RuleDefinition ruleDef1 = ruleBoService.createRule(ruleDefBuilder.build());
444 
445         PropositionDefinition.Builder parentProposition =
446                 PropositionDefinition.Builder.create(null, PropositionType.COMPOUND.getCode(), ruleDef1.getId(), null, null);
447         parentProposition.setCompoundComponents(new ArrayList<PropositionDefinition.Builder>());
448 
449         if (operator != null ) { parentProposition.setCompoundOpCode(operator.getCode()); }
450 
451         ruleDefBuilder = RuleDefinition.Builder.create(ruleDef1);
452 
453         for (PropositionParametersBuilder params : pbs) {
454 
455             StringBuilder propositionNameBuilder = new StringBuilder(ruleName);
456 
457             propositionNameBuilder.append("::");
458             for (Object[] param : params.params) {
459                 propositionNameBuilder.append((param[0] == null) ? "null" : param[0].toString());
460                 propositionNameBuilder.append("--");
461             }
462 
463             PropositionDefinition.Builder propositionBuilder =
464                     createPropositionDefinition(propositionNameBuilder.toString(), params, ruleDef1);
465 
466             if (pbs.length > 1) {
467                 // add it to the compound prop
468                 parentProposition.getCompoundComponents().add(propositionBuilder);
469             } else {
470                 // if there is only one proposition to build, make it the parent
471                 parentProposition = propositionBuilder;
472             }
473         }
474 
475         ruleDefBuilder.setProposition(parentProposition);
476         ruleDef1 = ruleDefBuilder.build();
477         ruleBoService.updateRule(ruleDef1);
478 
479         // Action
480         ActionDefinition.Builder actionDefBuilder1 = ActionDefinition.Builder.create(null, ruleName + "::TestAction", nameSpace, createKrmsActionTypeDefinition(nameSpace).getId(), ruleDef1.getId(), 1);
481         ActionDefinition actionDef1 = actionBoService.createAction(actionDefBuilder1.build());
482 
483         return ruleDef1;
484     }
485 
486 
487 
488     private RuleDefinition createRuleDefinition1(ContextDefinition contextDefinition, String agendaName, String nameSpace) {
489 
490         PropositionParametersBuilder params1 = new PropositionParametersBuilder();
491         params1.add(createTermDefinition(CAMPUS_CODE_TERM_NAME, String.class, contextDefinition).getId(), PropositionParameterType.TERM);
492         params1.add("QC", PropositionParameterType.CONSTANT);
493         params1.add("=", PropositionParameterType.OPERATOR);
494 
495         PropositionParametersBuilder params2 = new PropositionParametersBuilder();
496         params2.add(createTermDefinition(CAMPUS_CODE_TERM_NAME, String.class, contextDefinition).getId(), PropositionParameterType.TERM);
497         params2.add("BL", PropositionParameterType.CONSTANT);
498         params2.add("=", PropositionParameterType.OPERATOR);
499 
500         return createRuleDefinition(nameSpace, agendaName+"::Rule1", contextDefinition, LogicalOperator.OR, params1, params2);
501     }
502 
503 
504     private PropositionDefinition.Builder createPropositionDefinition(String propDescription, PropositionParametersBuilder params, RuleDefinition parentRule) {
505         // Proposition for rule 2
506         PropositionDefinition.Builder propositionDefBuilder1 =
507                 PropositionDefinition.Builder.create(null, PropositionType.SIMPLE.getCode(), parentRule.getId(),
508                         null /* type code is only for custom props */, Collections.<PropositionParameter.Builder>emptyList());
509         propositionDefBuilder1.setDescription(propDescription);
510 
511         // PropositionParams for rule 2
512         List<PropositionParameter.Builder> propositionParams1 = params.build();
513 
514 
515         // set the parent proposition so the builder will not puke
516         for (PropositionParameter.Builder propositionParamBuilder : propositionParams1) {
517             propositionParamBuilder.setProposition(propositionDefBuilder1);
518         }
519 
520         propositionDefBuilder1.setParameters(propositionParams1);
521 
522         return propositionDefBuilder1;
523     }
524     
525     
526     
527     private TermDefinition createTermDefinition(String termName, Class termValueType, ContextDefinition contextDefinition) {
528 
529         // this may be called more than once, we only want to create one though
530         Map<String, String> queryArgs = new HashMap<String, String>();
531         queryArgs.put("specification.namespace", contextDefinition.getNamespace());
532         queryArgs.put("specification.name", termName);
533         TermBo termBo = getBoService().findByPrimaryKey(TermBo.class, queryArgs);
534         if (termBo != null) {
535             return TermBo.to(termBo);
536         }
537         
538         // campusCode TermSpec
539         TermSpecificationDefinition termSpec =
540             TermSpecificationDefinition.Builder.create(null, termName, contextDefinition.getNamespace(),
541                     termValueType.getCanonicalName()).build();
542 
543         termSpec = termBoService.createTermSpecification(termSpec);
544         
545         // Term 1
546         TermDefinition termDefinition =
547             TermDefinition.Builder.create(null, TermSpecificationDefinition.Builder.create(termSpec), null).build();
548         termDefinition = termBoService.createTerm(termDefinition);
549 
550         return termDefinition;
551     }
552 
553 
554     private RuleDefinition createRuleDefinition2(ContextDefinition contextDefinition, String agendaName, String nameSpace) {
555 
556         PropositionParametersBuilder params1 = new PropositionParametersBuilder();
557         params1.add(createTermDefinition2(contextDefinition, nameSpace).getId(), PropositionParameterType.TERM);
558         params1.add("RESULT1", PropositionParameterType.CONSTANT);
559         params1.add("=", PropositionParameterType.OPERATOR);
560 
561         PropositionParametersBuilder params2 = new PropositionParametersBuilder();
562         params2.add(createTermDefinition2(contextDefinition, nameSpace).getId(), PropositionParameterType.TERM);
563         params2.add("NotGonnaBeEqual", PropositionParameterType.CONSTANT);
564         params2.add("=", PropositionParameterType.OPERATOR);
565 
566         return createRuleDefinition(nameSpace, agendaName+"::Rule2", contextDefinition, LogicalOperator.AND, params1, params2);
567     }
568 
569     private RuleDefinition createRuleDefinition3(ContextDefinition contextDefinition, String agendaName, String nameSpace) {
570 
571         FunctionDefinition gcdFunction = functionBoService.getFunctionByNameAndNamespace("gcd", contextDefinition.getNamespace());
572 
573         if (null == gcdFunction) {
574             // better configure a custom fuction for this
575             // KrmsType for custom function
576             KrmsTypeDefinition.Builder krmsFunctionTypeDefnBuilder = KrmsTypeDefinition.Builder.create("KrmsTestFunctionType", nameSpace);
577             krmsFunctionTypeDefnBuilder.setServiceName("testFunctionTypeService");
578             KrmsTypeDefinition krmsFunctionTypeDefinition = krmsTypeRepository.createKrmsType(krmsFunctionTypeDefnBuilder.build());
579 
580             FunctionDefinition.Builder functionBuilder =
581                     FunctionDefinition.Builder.create(contextDefinition.getNamespace(), "gcd", Integer.class.getName(), krmsFunctionTypeDefinition.getId());
582 
583             functionBuilder.getParameters().add(FunctionParameterDefinition.Builder.create("arg0", Integer.class.getName(), 0));
584             functionBuilder.getParameters().add(FunctionParameterDefinition.Builder.create("arg1", Integer.class.getName(), 1));
585             functionBuilder.setReturnType(Integer.class.getName());
586 
587             gcdFunction = functionBoService.createFunction(functionBuilder.build());
588         }
589 
590         PropositionParametersBuilder params = new PropositionParametersBuilder();
591 
592         // leverage our stack based evaluation in reverse polish notation
593         params.add("1024", PropositionParameterType.CONSTANT);
594         params.add("768", PropositionParameterType.CONSTANT);
595         params.add(gcdFunction.getId(), PropositionParameterType.FUNCTION); // this should evaluate first: gcd(1024, 768)
596         params.add("256", PropositionParameterType.CONSTANT);
597         params.add("=", PropositionParameterType.OPERATOR); // this should evaluate second: gcdResult == 256
598 
599         return createRuleDefinition(nameSpace, agendaName+"::Rule3", contextDefinition, null, params);
600     }
601 
602 
603     private RuleDefinition createRuleDefinition4(ContextDefinition contextDefinition, String agendaName, String nameSpace) {
604 
605         PropositionParametersBuilder params1 = new PropositionParametersBuilder();
606         params1.add(createTermDefinition(BOOL1, Boolean.class, contextDefinition).getId(), PropositionParameterType.TERM);
607         params1.add(createTermDefinition(BOOL2, Boolean.class, contextDefinition).getId(), PropositionParameterType.TERM);
608         params1.add("=", PropositionParameterType.OPERATOR);
609 
610         PropositionParametersBuilder params2 = new PropositionParametersBuilder();
611         params2.add(createTermDefinition(BOOL2, Boolean.class, contextDefinition).getId(), PropositionParameterType.TERM);
612         params2.add(createTermDefinition(BOOL1, Boolean.class, contextDefinition).getId(), PropositionParameterType.TERM);
613         params2.add("=", PropositionParameterType.OPERATOR);
614 
615         return createRuleDefinition(nameSpace, agendaName+"::Rule4", contextDefinition, LogicalOperator.AND, params1, params2);
616     }
617 
618     private RuleDefinition createRuleDefinition5(ContextDefinition contextDefinition, String agendaName, String nameSpace) {
619 
620         PropositionParametersBuilder params1 = new PropositionParametersBuilder();
621         params1.add(createTermDefinition(NULL_FACT, Boolean.class, contextDefinition).getId(), PropositionParameterType.TERM);
622         params1.add(null, PropositionParameterType.CONSTANT);
623         params1.add("=", PropositionParameterType.OPERATOR);
624 
625         return createRuleDefinition(nameSpace, agendaName+"::Rule5", contextDefinition, LogicalOperator.AND, params1);
626     }
627 
628 
629     private TermDefinition createTermDefinition2(ContextDefinition contextDefinition, String nameSpace) {
630 
631         Map<String, String> queryArgs = new HashMap<String, String>();
632         queryArgs.put("specification.namespace", contextDefinition.getNamespace());
633         queryArgs.put("specification.name", "outputTermSpec");
634         TermBo result = getBoService().findByPrimaryKey(TermBo.class, queryArgs);
635         if (result != null) return TermBo.to(result);
636 
637         // output TermSpec
638         TermSpecificationDefinition outputTermSpec =
639             TermSpecificationDefinition.Builder.create(null, "outputTermSpec", contextDefinition.getNamespace(),
640                     "java.lang.String").build();
641         outputTermSpec = termBoService.createTermSpecification(outputTermSpec);
642 
643         // prereq TermSpec
644         TermSpecificationDefinition prereqTermSpec =
645             TermSpecificationDefinition.Builder.create(null, PREREQ_TERM_NAME, contextDefinition.getNamespace(),
646                     "java.lang.String").build();
647         prereqTermSpec = termBoService.createTermSpecification(prereqTermSpec);
648 
649         // Term Param
650         TermParameterDefinition.Builder termParamBuilder2 =
651             TermParameterDefinition.Builder.create(null, null, "testParamName", "testParamValue");
652 
653         // Term
654         TermDefinition termDefinition2 =
655             TermDefinition.Builder.create(null, TermSpecificationDefinition.Builder.create(outputTermSpec), Collections.singletonList(termParamBuilder2)).build();
656         termDefinition2 = termBoService.createTerm(termDefinition2);
657 
658 		// KrmsType for TermResolver
659 		KrmsTypeDefinition.Builder krmsTermResolverTypeDefnBuilder = KrmsTypeDefinition.Builder.create("KrmsTestResolverType", nameSpace);
660 		krmsTermResolverTypeDefnBuilder.setServiceName("testTermResolverTypeService");
661 
662 		KrmsTypeDefinition krmsTermResolverTypeDefinition = krmsTypeRepository.createKrmsType(krmsTermResolverTypeDefnBuilder.build());
663 
664         // TermResolver
665 		TermResolverDefinition termResolverDef =
666 			TermResolverDefinition.Builder.create(null, contextDefinition.getNamespace(), "testResolver1", krmsTermResolverTypeDefinition.getId(),
667 					TermSpecificationDefinition.Builder.create(outputTermSpec),
668 					Collections.singleton(TermSpecificationDefinition.Builder.create(prereqTermSpec)),
669 					null,
670 					Collections.singleton("testParamName")).build();
671 		termResolverDef = termBoService.createTermResolver(termResolverDef);
672 
673         return termDefinition2;
674     }
675 
676     private static class PropositionParametersBuilder {
677         
678         // poor OOD but this is quick and dirty :-P
679         private List<Object[]> params = new ArrayList<Object[]>();
680         
681         public PropositionParametersBuilder add(String value, PropositionParameterType type) {
682             if (type == null) throw new IllegalArgumentException("type must not be null");
683             params.add(new Object[]{value, type});
684             return this;
685         }
686         
687         public List<PropositionParameter.Builder> build() {
688             int seqCounter = 0;
689             
690             List<PropositionParameter.Builder> results = new ArrayList<PropositionParameter.Builder>();
691             
692             for (Object[] param : params) {
693                 results.add(PropositionParameter.Builder.create(null, null, (String)param[0], ((PropositionParameterType)param[1]).getCode(), seqCounter++));
694             }
695 
696             return results;
697         }
698     }
699 
700 }