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