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.core.api.lifecycle.Lifecycle;
22  import org.kuali.rice.kew.util.PerformanceLogger;
23  import org.kuali.rice.krms.api.KrmsApiServiceLocator;
24  import org.kuali.rice.krms.api.engine.EngineResults;
25  import org.kuali.rice.krms.api.engine.ExecutionFlag;
26  import org.kuali.rice.krms.api.engine.ExecutionOptions;
27  import org.kuali.rice.krms.api.engine.Facts;
28  import org.kuali.rice.krms.api.engine.ResultEvent;
29  import org.kuali.rice.krms.api.engine.SelectionCriteria;
30  import org.kuali.rice.krms.api.repository.LogicalOperator;
31  import org.kuali.rice.krms.api.repository.action.ActionDefinition;
32  import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
33  import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
34  import org.kuali.rice.krms.api.repository.context.ContextDefinition;
35  import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
36  import org.kuali.rice.krms.api.repository.function.FunctionParameterDefinition;
37  import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
38  import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
39  import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
40  import org.kuali.rice.krms.api.repository.proposition.PropositionType;
41  import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
42  import org.kuali.rice.krms.api.repository.term.TermDefinition;
43  import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
44  import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
45  import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
46  import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
47  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
48  import org.kuali.rice.krms.impl.repository.ActionBoService;
49  import org.kuali.rice.krms.impl.repository.AgendaBoService;
50  import org.kuali.rice.krms.impl.repository.FunctionBoServiceImpl;
51  import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
52  import org.kuali.rice.krms.impl.repository.RuleBoService;
53  import org.kuali.rice.krms.impl.repository.TermBo;
54  import org.kuali.rice.krms.impl.repository.TermBoService;
55  import org.kuali.rice.krms.impl.repository.TermSpecificationBo;
56  import org.kuali.rice.test.BaselineTestCase.BaselineMode;
57  import org.kuali.rice.test.BaselineTestCase.Mode;
58  import org.kuali.rice.test.ClearDatabaseLifecycle;
59  import org.springframework.transaction.annotation.Transactional;
60  
61  import java.util.ArrayList;
62  import java.util.Collections;
63  import java.util.HashMap;
64  import java.util.List;
65  import java.util.Map;
66  
67  import static org.junit.Assert.*;
68  
69  @BaselineMode(Mode.CLEAR_DB)
70  public class KSLumKRMSDataSetupTest extends KSLumAbstractBoTest {
71  
72  	public static final String CAMPUS_CODE_TERM_NAME = "campusCodeTermSpec";
73  
74  	static final String NAMESPACE1 = "KRMS_TEST_1";
75  	static final String NAMESPACE2 = "KRMS_TEST_2";
76  	static final String KSNAMESPACE = "KR-RULE-TEST";
77  	static final String TSUNAMI_EVENT = "Tsunami";
78  	static final String EARTHQUAKE_EVENT = "Earthquake";
79  	static final String KSContextRepeatableforCredit = "Repeatable for Credit";
80  	static final String CONTEXT2 = "Context2";
81  	static final String NAME = "name";
82  	static final String CONTEXT1_QUALIFIER = "KSLum Qualifer 1";
83  	static final String CONTEXT1_QUALIFIER_VALUE = "KSLum Qualifer 1 - Value";
84  	static final String CONTEXT2_QUALIFIER = "KSLum Qualifer 1";
85  	static final String CONTEXT2_QUALIFIER_VALUE = "KSLum Qualifer 2 - Value";
86  	static final String AGENDA1 = "TestAgenda1";
87  	static final String AGENDA2 = "Agenda2";
88  	static final String AGENDA3 = "Agenda3";
89  	static final String AGENDA4 = "Agenda4";
90  	static final String AGENDA_MayBeRepeatedForAMaxOfnCredits = "May be repeated for a maximum of <n> credits";
91  	static final String AGENDA_MustNotHaveSuccessfullyCompletedCourse = "Must not have successfully completed <course>";
92  	static final String AGENDA_MustHaveSuccessfullyCompletedAMinOfnCreditsFromCoursesInTheOrg = "Must have successfully completed a minimum of <n> credits from courses in the <org>";
93  
94  	static final String PREREQ_TERM_NAME = "prereqTermSpec";
95  	static final String PREREQ_TERM_VALUE = "prereqValue";
96  	static final String NAMESPACE_CODE = "namespaceCode";
97  	static final String BOOL1 = "bool1";
98  	static final String BOOL2 = "bool2";
99  
100 	// // Services needed for creation:
101 	private TermBoService termBoService;
102 
103 	private RuleBoService ruleBoService;
104 	private AgendaBoService agendaBoService;
105 	private ActionBoService actionBoService;
106 	private FunctionBoServiceImpl functionBoService;
107 
108 	private static final String ATTR_NUMBER_OF_CREDITS = "Number of Credits";
109 	private static final String ATTR_DEPT_ORG_NUMBER = "Dept Org Number";
110 	private static final String ATTR_PROPOSED_COURSE = "Proposed Course";
111 	private static final String ATTR_APPROVED_COURSE = "Approved Course";
112 
113 	private static final String TERM_SPEC_CREDITS = "Credits";
114 	private static final String TERM_SPEC_ORG_NUMBER = "Org Number";
115 	private static final String TERM_SPEC_COURSE = "Course";
116 	private static final String TERM_SPEC_COURSE_NUMBER = "Course Number";
117 	private static final String TERM_SPEC_DATE = "Date";
118 	private static final String TERM_SPEC_GPA = "GPA";
119 	private static final String TERM_SPEC_GRADE = "Grade";
120 	private static final String TERM_SPEC_GRADE_TYPE = "GradeType";
121 	private static final String TERM_SPEC_LEARNING_OBJECTIVES = "Learning Objectives";
122 	
123 	/**
124 	 * 
125 	 * Setting it up so that KRMS tables are not reset between test methods to
126 	 * make it run much faster
127 	 * 
128 	 * @return
129 	 */
130 	protected List<String> getPerTestTablesNotToClear() {
131 		List<String> tablesNotToClear = super.getPerTestTablesNotToClear();
132 
133 		tablesNotToClear.add("KRMS_.*");
134 
135 		return tablesNotToClear;
136 	}
137 
138 	@Before
139 	public void setup() {
140 		// Reset TestActionTypeService
141 		TestActionTypeService.resetActionsFired();
142 
143 		termBoService = KrmsRepositoryServiceLocator.getTermBoService();
144 		contextRepository = KrmsRepositoryServiceLocator.getContextBoService();
145 		krmsTypeRepository = KrmsRepositoryServiceLocator
146 				.getKrmsTypeRepositoryService();
147 
148 		ruleBoService = KrmsRepositoryServiceLocator.getRuleBoService();
149 		agendaBoService = KrmsRepositoryServiceLocator.getAgendaBoService();
150 		actionBoService = KrmsRepositoryServiceLocator
151 				.getBean("actionBoService");
152 		functionBoService = KrmsRepositoryServiceLocator
153 				.getBean("functionRepositoryService");
154 		krmsAttributeDefinitionService = KrmsRepositoryServiceLocator
155 				.getKrmsAttributeDefinitionService();
156 
157 		boolean doTermDefinitions = true;
158 		if (doTermDefinitions ) {
159 			// createAllLumTermDefinitions(KSNAMESPACE);
160 		} else {
161 
162 			ContextDefinition contextRecommendedPreparation = contextRepository
163 					.getContextByNameAndNamespace(KSContextRepeatableforCredit,
164 							KSNAMESPACE);
165 			ContextDefinition contextRepeatableForCredit = contextRepository
166 					.getContextByNameAndNamespace(KSContextRepeatableforCredit,
167 							KSNAMESPACE);
168 
169 			// only set this stuff up if we don't already have Context1 (we
170 			// don't clear out KRMS tables between test methods)
171 			if (contextRecommendedPreparation == null) {
172 
173 				PerformanceLogger perfLog = new PerformanceLogger();
174 				perfLog.log("starting agenda creation");
175 
176 				createAllLumAttributeDefinitions(KSNAMESPACE);
177 				createAllLumTermDefinitions(KSNAMESPACE);
178 				KrmsTypeDefinition krmsContextTypeDefinition = createContextType(KSNAMESPACE);
179 
180 				contextRepeatableForCredit = createContext(KSNAMESPACE,
181 						"Repeatable for Credit", krmsContextTypeDefinition);
182 
183 				contextRecommendedPreparation = createContext(KSNAMESPACE,
184 						"Recommended Preparation", krmsContextTypeDefinition);
185 
186 				// Term Specifications
187 
188 				// Term Definitions
189 				createAllLumTermDefinitions(KSNAMESPACE);
190 
191 				// createRulesForAgenda(agendaName, contextDefinition,
192 				// eventName,
193 				// nameSpace, agendaDef);
194 
195 				// contextDefintion1 = createContextDefinition(KSNAMESPACE,
196 				// KSContextRepeatableforCredit, Collections.singletonMap(
197 				// CONTEXT1_QUALIFIER, CONTEXT1_QUALIFIER_VALUE));
198 
199 				// createAgendaDefinition(AGENDA1, contextDefintion1,
200 				// TSUNAMI_EVENT, KSNAMESPACE);
201 
202 				// ContextDefinition contextDefinition2 =
203 				// createContextDefinition(NAMESPACE2, CONTEXT2,
204 				// Collections.singletonMap(
205 				// CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE));
206 				//
207 				// // Create multiple agendas so that we can test selection
208 				// createAgendaDefinition(AGENDA2, contextDefinition2,
209 				// EARTHQUAKE_EVENT, NAMESPACE2);
210 				// createAgendaDefinition(AGENDA3, contextDefinition2,
211 				// EARTHQUAKE_EVENT, NAMESPACE2);
212 				// createAgendaDefinition(AGENDA4, contextDefinition2,
213 				// TSUNAMI_EVENT, NAMESPACE2);
214 
215 				perfLog.log("finished agenda creation", true);
216 			}
217 
218 			// KrmsTypeDefinition krmsGenericTypeDefinition =
219 			// createKrmsGenericTypeDefinition(KSNAMESPACE,
220 			// "testAgendaTypeService", "event name", "Event");
221 			//
222 			// createAgendaDefinition(AGENDA_MayBeRepeatedForAMaxOfnCredits,
223 			// contextRepeatableForCredit, TSUNAMI_EVENT, KSNAMESPACE,
224 			// krmsGenericTypeDefinition);
225 			// createAgendaDefinition(AGENDA_MustNotHaveSuccessfullyCompletedCourse,
226 			// contextRecommendedPreparation, TSUNAMI_EVENT, KSNAMESPACE,
227 			// krmsGenericTypeDefinition);
228 			// createAgendaDefinition(AGENDA_MustHaveSuccessfullyCompletedAMinOfnCreditsFromCoursesInTheOrg,
229 			// contextRecommendedPreparation, TSUNAMI_EVENT, KSNAMESPACE,
230 			// krmsGenericTypeDefinition);
231 		}
232 	}
233 
234 	private void createTerms() {
235 
236 	}
237 
238 	@Test
239 	public void testNothing() {
240 		System.out.println("Tested setup");
241 	}
242 
243 	@Transactional
244 	// @Test
245 	public void testSelectAgendaByAttributeAndName() {
246 
247 		Map<String, String> contextQualifiers = new HashMap<String, String>();
248 		contextQualifiers.put(NAMESPACE_CODE, NAMESPACE1);
249 		contextQualifiers.put(NAME, KSContextRepeatableforCredit);
250 		contextQualifiers.put(CONTEXT1_QUALIFIER, CONTEXT1_QUALIFIER_VALUE);
251 
252 		Map<String, String> agendaQualifiers = new HashMap<String, String>();
253 		agendaQualifiers.put(AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT);
254 		agendaQualifiers.put(NAME, AGENDA1);
255 
256 		DateTime now = new DateTime();
257 
258 		SelectionCriteria sc1 = SelectionCriteria.createCriteria(now,
259 				contextQualifiers, Collections.singletonMap(
260 						AgendaDefinition.Constants.EVENT, TSUNAMI_EVENT));
261 
262 		Facts.Builder factsBuilder1 = Facts.Builder.create();
263 		factsBuilder1.addFact(CAMPUS_CODE_TERM_NAME, "BL");
264 		factsBuilder1.addFact(BOOL1, "true");
265 		factsBuilder1.addFact(BOOL2, Boolean.TRUE);
266 		factsBuilder1.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
267 
268 		ExecutionOptions xOptions1 = new ExecutionOptions();
269 		xOptions1.setFlag(ExecutionFlag.LOG_EXECUTION, true);
270 
271 		PerformanceLogger perfLog = new PerformanceLogger();
272 		perfLog.log("starting rule execution");
273 		EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(
274 				sc1, factsBuilder1.build(), xOptions1);
275 		perfLog.log("finished rule execution", true);
276 		List<ResultEvent> rEvents1 = eResults1.getAllResults();
277 
278 		List<ResultEvent> ruleEvaluationResults1 = eResults1
279 				.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
280 
281 		assertEquals("4 rules should have been evaluated", 4,
282 				ruleEvaluationResults1.size());
283 
284 		assertTrue("rule 0 should have evaluated to true",
285 				ruleEvaluationResults1.get(0).getResult());
286 		assertFalse("rule 1 should have evaluated to false",
287 				ruleEvaluationResults1.get(1).getResult());
288 		assertTrue("rule 2 should have evaluated to true",
289 				ruleEvaluationResults1.get(2).getResult());
290 
291 		// ONLY agenda 1 should have been selected
292 		assertTrue(TestActionTypeService
293 				.actionFired("TestAgenda1::Rule1::TestAction"));
294 		assertFalse(TestActionTypeService
295 				.actionFired("TestAgenda1::Rule2::TestAction"));
296 		assertTrue(TestActionTypeService
297 				.actionFired("TestAgenda1::Rule3::TestAction"));
298 
299 		assertAgendaDidNotExecute(AGENDA2);
300 		assertAgendaDidNotExecute(AGENDA3);
301 		assertAgendaDidNotExecute(AGENDA4);
302 	}
303 
304 	@Transactional
305 	// @Test
306 	public void testSelectAgendaByName() {
307 		Map<String, String> contextQualifiers = new HashMap<String, String>();
308 		contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2);
309 		contextQualifiers.put(NAME, CONTEXT2);
310 		contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE);
311 		Map<String, String> agendaQualifiers = new HashMap<String, String>();
312 
313 		/*
314 		 * We'll specifically NOT select this attribute to make sure that
315 		 * matching only takes place against qualifiers in the selection
316 		 * criteria
317 		 */
318 		// agendaQualifiers.put(AgendaDefinition.Constants.EVENT,
319 		// EARTHQUAKE_EVENT);
320 
321 		agendaQualifiers.put(NAME, AGENDA3);
322 		DateTime now = new DateTime();
323 
324 		SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(
325 				now, contextQualifiers, agendaQualifiers);
326 
327 		Facts.Builder factsBuilder2 = Facts.Builder.create();
328 		factsBuilder2.addFact(BOOL1, "true");
329 		factsBuilder2.addFact(BOOL2, Boolean.TRUE);
330 		factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL");
331 		factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
332 
333 		ExecutionOptions xOptions2 = new ExecutionOptions();
334 		xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true);
335 
336 		PerformanceLogger perfLog = new PerformanceLogger();
337 		perfLog.log("starting rule execution 1");
338 		EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(
339 				selectionCriteria, factsBuilder2.build(), xOptions2);
340 		perfLog.log("finished rule execution 1");
341 		List<ResultEvent> rEvents1 = eResults1.getAllResults();
342 
343 		List<ResultEvent> ruleEvaluationResults1 = eResults1
344 				.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
345 
346 		selectionCriteria = SelectionCriteria.createCriteria(now,
347 				contextQualifiers, agendaQualifiers);
348 
349 		assertEquals("4 rules should have been evaluated", 4,
350 				ruleEvaluationResults1.size());
351 
352 		assertAgendaDidNotExecute(AGENDA1);
353 		assertAgendaDidNotExecute(AGENDA2);
354 
355 		// ONLY agenda 3 should have been selected
356 		assertTrue(TestActionTypeService
357 				.actionFired("Agenda3::Rule1::TestAction"));
358 		assertFalse(TestActionTypeService
359 				.actionFired("Agenda3::Rule2::TestAction"));
360 		assertTrue(TestActionTypeService
361 				.actionFired("Agenda3::Rule3::TestAction"));
362 
363 		assertAgendaDidNotExecute(AGENDA4);
364 	}
365 
366 	@Transactional
367 	// @Test
368 	public void testSelectMultipleAgendasByAttribute() {
369 		Map<String, String> contextQualifiers = new HashMap<String, String>();
370 		contextQualifiers.put(NAMESPACE_CODE, NAMESPACE2);
371 		contextQualifiers.put(NAME, CONTEXT2);
372 		contextQualifiers.put(CONTEXT2_QUALIFIER, CONTEXT2_QUALIFIER_VALUE);
373 
374 		Map<String, String> agendaQualifiers = new HashMap<String, String>();
375 		agendaQualifiers
376 				.put(AgendaDefinition.Constants.EVENT, EARTHQUAKE_EVENT);
377 
378 		DateTime now = new DateTime();
379 
380 		SelectionCriteria selectionCriteria = SelectionCriteria.createCriteria(
381 				now, contextQualifiers, agendaQualifiers);
382 
383 		Facts.Builder factsBuilder2 = Facts.Builder.create();
384 		factsBuilder2.addFact(BOOL1, "true");
385 		factsBuilder2.addFact(BOOL2, Boolean.TRUE);
386 		factsBuilder2.addFact(CAMPUS_CODE_TERM_NAME, "BL");
387 		factsBuilder2.addFact(PREREQ_TERM_NAME, PREREQ_TERM_VALUE);
388 
389 		ExecutionOptions xOptions2 = new ExecutionOptions();
390 		xOptions2.setFlag(ExecutionFlag.LOG_EXECUTION, true);
391 
392 		PerformanceLogger perfLog = new PerformanceLogger();
393 		perfLog.log("starting rule execution 1");
394 		EngineResults eResults1 = KrmsApiServiceLocator.getEngine().execute(
395 				selectionCriteria, factsBuilder2.build(), xOptions2);
396 		perfLog.log("finished rule execution 1");
397 		List<ResultEvent> rEvents1 = eResults1.getAllResults();
398 
399 		List<ResultEvent> ruleEvaluationResults1 = eResults1
400 				.getResultsOfType(ResultEvent.RULE_EVALUATED.toString());
401 
402 		selectionCriteria = SelectionCriteria.createCriteria(now,
403 				contextQualifiers, agendaQualifiers);
404 
405 		assertEquals("8 rules should have been evaluated", 8,
406 				ruleEvaluationResults1.size());
407 
408 		assertAgendaDidNotExecute(AGENDA1);
409 
410 		// ONLY agendas 2 & 3 should have been selected
411 
412 		assertTrue(TestActionTypeService
413 				.actionFired("Agenda2::Rule1::TestAction"));
414 		assertFalse(TestActionTypeService
415 				.actionFired("Agenda2::Rule2::TestAction"));
416 		assertTrue(TestActionTypeService
417 				.actionFired("Agenda2::Rule3::TestAction"));
418 
419 		assertTrue(TestActionTypeService
420 				.actionFired("Agenda3::Rule1::TestAction"));
421 		assertFalse(TestActionTypeService
422 				.actionFired("Agenda3::Rule2::TestAction"));
423 		assertTrue(TestActionTypeService
424 				.actionFired("Agenda3::Rule3::TestAction"));
425 
426 		assertAgendaDidNotExecute(AGENDA4);
427 	}
428 
429 	private void assertAgendaDidNotExecute(String agendaName) {
430 		assertFalse(TestActionTypeService.actionFired(agendaName
431 				+ "::Rule1::TestAction"));
432 		assertFalse(TestActionTypeService.actionFired(agendaName
433 				+ "::Rule2::TestAction"));
434 		assertFalse(TestActionTypeService.actionFired(agendaName
435 				+ "::Rule3::TestAction"));
436 	}
437 
438 	private void createAgendaDefinition(String agendaName,
439 			ContextDefinition contextDefinition, String eventName,
440 			String nameSpace, KrmsTypeDefinition krmsGenericTypeDefinition) {
441 		AgendaDefinition agendaDef = AgendaDefinition.Builder.create(null,
442 				agendaName, krmsGenericTypeDefinition.getId(),
443 				contextDefinition.getId()).build();
444 		agendaDef = agendaBoService.createAgenda(agendaDef);
445 	}
446 
447 	private void createRulesForAgenda(String agendaName,
448 			ContextDefinition contextDefinition, String eventName,
449 			String nameSpace, AgendaDefinition agendaDef) {
450 		AgendaItemDefinition.Builder agendaItemBuilder1 = AgendaItemDefinition.Builder
451 				.create(null, agendaDef.getId());
452 		agendaItemBuilder1.setRuleId(createRuleDefinition1(contextDefinition,
453 				agendaName, nameSpace).getId());
454 
455 		AgendaItemDefinition.Builder agendaItemBuilder2 = AgendaItemDefinition.Builder
456 				.create(null, agendaDef.getId());
457 		agendaItemBuilder1.setAlways(agendaItemBuilder2);
458 		agendaItemBuilder2.setRuleId(createRuleDefinition2(contextDefinition,
459 				agendaName, nameSpace).getId());
460 
461 		AgendaItemDefinition.Builder agendaItemBuilder3 = AgendaItemDefinition.Builder
462 				.create(null, agendaDef.getId());
463 		agendaItemBuilder2.setAlways(agendaItemBuilder3);
464 		agendaItemBuilder3.setRuleId(createRuleDefinition3(contextDefinition,
465 				agendaName, nameSpace).getId());
466 
467 		AgendaItemDefinition.Builder agendaItemBuilder4 = AgendaItemDefinition.Builder
468 				.create(null, agendaDef.getId());
469 		agendaItemBuilder3.setAlways(agendaItemBuilder4);
470 		agendaItemBuilder4.setRuleId(createRuleDefinition4(contextDefinition,
471 				agendaName, nameSpace).getId());
472 
473 		// String these puppies together. Kind of a PITA because you need the id
474 		// from the next item before you insert the previous one
475 		AgendaItemDefinition agendaItem4 = agendaBoService
476 				.createAgendaItem(agendaItemBuilder4.build());
477 		agendaItemBuilder3.setAlwaysId(agendaItem4.getId());
478 		AgendaItemDefinition agendaItem3 = agendaBoService
479 				.createAgendaItem(agendaItemBuilder3.build());
480 		agendaItemBuilder2.setAlwaysId(agendaItem3.getId());
481 		AgendaItemDefinition agendaItem2 = agendaBoService
482 				.createAgendaItem(agendaItemBuilder2.build());
483 		agendaItemBuilder1.setAlwaysId(agendaItem2.getId());
484 		AgendaItemDefinition agendaItem1 = agendaBoService
485 				.createAgendaItem(agendaItemBuilder1.build());
486 
487 		AgendaDefinition.Builder agendaDefBuilder1 = AgendaDefinition.Builder
488 				.create(agendaDef);
489 		agendaDefBuilder1.setAttributes(Collections.singletonMap("Event",
490 				eventName));
491 		agendaDefBuilder1.setFirstItemId(agendaItem1.getId());
492 		agendaDef = agendaDefBuilder1.build();
493 
494 		agendaBoService.updateAgenda(agendaDef);
495 	}
496 
497 	private KrmsTypeDefinition createKrmsActionTypeDefinition(String nameSpace) {
498 		String ACTION_TYPE_NAME = "KrmsActionResolverType";
499 		KrmsTypeDefinition krmsActionTypeDefinition = krmsTypeRepository
500 				.getTypeByName(nameSpace, ACTION_TYPE_NAME);
501 
502 		if (krmsActionTypeDefinition == null) {
503 			KrmsTypeDefinition.Builder krmsActionTypeDefnBuilder = KrmsTypeDefinition.Builder
504 					.create(ACTION_TYPE_NAME, nameSpace);
505 			krmsActionTypeDefnBuilder.setServiceName("testActionTypeService");
506 			krmsActionTypeDefinition = krmsTypeRepository
507 					.createKrmsType(krmsActionTypeDefnBuilder.build());
508 		}
509 
510 		return krmsActionTypeDefinition;
511 	}
512 
513 	private RuleDefinition createRuleDefinition(String nameSpace,
514 			String ruleName, ContextDefinition contextDefinition,
515 			LogicalOperator operator, PropositionParametersBuilder... pbs) {
516 		RuleDefinition.Builder ruleDefBuilder = RuleDefinition.Builder.create(
517 				null, ruleName, nameSpace, null, null);
518 		RuleDefinition ruleDef1 = ruleBoService.createRule(ruleDefBuilder
519 				.build());
520 
521 		PropositionDefinition.Builder parentProposition = PropositionDefinition.Builder
522 				.create(null, PropositionType.COMPOUND.getCode(),
523 						ruleDef1.getId(), null, null);
524 		parentProposition
525 				.setCompoundComponents(new ArrayList<PropositionDefinition.Builder>());
526 
527 		if (operator != null) {
528 			parentProposition.setCompoundOpCode(operator.getCode());
529 		}
530 
531 		ruleDefBuilder = RuleDefinition.Builder.create(ruleDef1);
532 
533 		for (PropositionParametersBuilder params : pbs) {
534 
535 			StringBuilder propositionNameBuilder = new StringBuilder(ruleName);
536 
537 			propositionNameBuilder.append("::");
538 			for (Object[] param : params.params) {
539 				propositionNameBuilder.append(param[0].toString());
540 				propositionNameBuilder.append("--");
541 			}
542 
543 			PropositionDefinition.Builder propositionBuilder = createPropositionDefinition(
544 					propositionNameBuilder.toString(), params, ruleDef1);
545 
546 			if (pbs.length > 1) {
547 				// add it to the compound prop
548 				parentProposition.getCompoundComponents().add(
549 						propositionBuilder);
550 			} else {
551 				// if there is only one proposition to build, make it the parent
552 				parentProposition = propositionBuilder;
553 			}
554 		}
555 
556 		ruleDefBuilder.setProposition(parentProposition);
557 		ruleDef1 = ruleDefBuilder.build();
558 		ruleBoService.updateRule(ruleDef1);
559 
560 		// Action
561 		ActionDefinition.Builder actionDefBuilder1 = ActionDefinition.Builder
562 				.create(null, ruleName + "::TestAction", nameSpace,
563 						createKrmsActionTypeDefinition(nameSpace).getId(),
564 						ruleDef1.getId(), 1);
565 		ActionDefinition actionDef1 = actionBoService
566 				.createAction(actionDefBuilder1.build());
567 
568 		return ruleDef1;
569 	}
570 
571 	private RuleDefinition createRuleDefinition1(
572 			ContextDefinition contextDefinition, String agendaName,
573 			String nameSpace) {
574 
575 		PropositionParametersBuilder params1 = new PropositionParametersBuilder();
576 		params1.add(
577 				createTermDefinition(CAMPUS_CODE_TERM_NAME, String.class,
578 						contextDefinition).getId(),
579 				PropositionParameterType.TERM);
580 		params1.add("QC", PropositionParameterType.CONSTANT);
581 		params1.add("=", PropositionParameterType.OPERATOR);
582 
583 		PropositionParametersBuilder params2 = new PropositionParametersBuilder();
584 		params2.add(
585 				createTermDefinition(CAMPUS_CODE_TERM_NAME, String.class,
586 						contextDefinition).getId(),
587 				PropositionParameterType.TERM);
588 		params2.add("BL", PropositionParameterType.CONSTANT);
589 		params2.add("=", PropositionParameterType.OPERATOR);
590 
591 		return createRuleDefinition(nameSpace, agendaName + "::Rule1",
592 				contextDefinition, LogicalOperator.OR, params1, params2);
593 	}
594 
595 	private PropositionDefinition.Builder createPropositionDefinition(
596 			String propDescription, PropositionParametersBuilder params,
597 			RuleDefinition parentRule) {
598 		// Proposition for rule 2
599 		PropositionDefinition.Builder propositionDefBuilder1 = PropositionDefinition.Builder
600 				.create(null, PropositionType.SIMPLE.getCode(),
601 						parentRule.getId(), null /*
602 												 * type code is only for custom
603 												 * props
604 												 */,
605 						Collections.<PropositionParameter.Builder> emptyList());
606 		propositionDefBuilder1.setDescription(propDescription);
607 
608 		// PropositionParams for rule 2
609 		List<PropositionParameter.Builder> propositionParams1 = params.build();
610 
611 		// set the parent proposition so the builder will not puke
612 		for (PropositionParameter.Builder propositionParamBuilder : propositionParams1) {
613 			propositionParamBuilder.setProposition(propositionDefBuilder1);
614 		}
615 
616 		propositionDefBuilder1.setParameters(propositionParams1);
617 
618 		return propositionDefBuilder1;
619 	}
620 
621 	private TermDefinition createTermDefinition(String termName,
622 			Class termValueType, ContextDefinition contextDefinition) {
623 
624 		// this may be called more than once, we only want to create one though
625 		Map<String, String> queryArgs = new HashMap<String, String>();
626 		queryArgs.put("specification.namespace",
627 				contextDefinition.getNamespace());
628 		queryArgs.put("specification.name", termName);
629 		TermBo termBo = getBoService()
630 				.findByPrimaryKey(TermBo.class, queryArgs);
631 		if (termBo != null) {
632 			return TermBo.to(termBo);
633 		}
634 
635 		// campusCode TermSpec
636 		TermSpecificationDefinition termSpec = TermSpecificationDefinition.Builder
637 				.create(null, termName, contextDefinition.getNamespace(),
638 						termValueType.getCanonicalName()).build();
639 
640 		termSpec = termBoService.createTermSpecification(termSpec);
641 
642 		// Term 1
643 		TermDefinition termDefinition = TermDefinition.Builder.create(null,
644 				TermSpecificationDefinition.Builder.create(termSpec), null)
645 				.build();
646 		termDefinition = termBoService.createTerm(termDefinition);
647 
648 		return termDefinition;
649 	}
650 
651 	private RuleDefinition createRuleDefinition2(
652 			ContextDefinition contextDefinition, String agendaName,
653 			String nameSpace) {
654 
655 		PropositionParametersBuilder params1 = new PropositionParametersBuilder();
656 		params1.add(
657 				createTermDefinition2(contextDefinition, nameSpace).getId(),
658 				PropositionParameterType.TERM);
659 		params1.add("RESULT1", PropositionParameterType.CONSTANT);
660 		params1.add("=", PropositionParameterType.OPERATOR);
661 
662 		PropositionParametersBuilder params2 = new PropositionParametersBuilder();
663 		params2.add(
664 				createTermDefinition2(contextDefinition, nameSpace).getId(),
665 				PropositionParameterType.TERM);
666 		params2.add("NotGonnaBeEqual", PropositionParameterType.CONSTANT);
667 		params2.add("=", PropositionParameterType.OPERATOR);
668 
669 		return createRuleDefinition(nameSpace, agendaName + "::Rule2",
670 				contextDefinition, LogicalOperator.AND, params1, params2);
671 	}
672 
673 	private RuleDefinition createRuleDefinition3(
674 			ContextDefinition contextDefinition, String agendaName,
675 			String nameSpace) {
676 
677 		FunctionDefinition gcdFunction = functionBoService
678 				.getFunctionByNameAndNamespace("gcd",
679 						contextDefinition.getNamespace());
680 
681 		if (null == gcdFunction) {
682 			// better configure a custom fuction for this
683 			// KrmsType for custom function
684 			KrmsTypeDefinition.Builder krmsFunctionTypeDefnBuilder = KrmsTypeDefinition.Builder
685 					.create("KrmsTestFunctionType", nameSpace);
686 			krmsFunctionTypeDefnBuilder
687 					.setServiceName("testFunctionTypeService");
688 			KrmsTypeDefinition krmsFunctionTypeDefinition = krmsTypeRepository
689 					.createKrmsType(krmsFunctionTypeDefnBuilder.build());
690 
691 			FunctionDefinition.Builder functionBuilder = FunctionDefinition.Builder
692 					.create(contextDefinition.getNamespace(), "gcd",
693 							Integer.class.getName(),
694 							krmsFunctionTypeDefinition.getId());
695 
696 			functionBuilder.getParameters().add(
697 					FunctionParameterDefinition.Builder.create("arg0",
698 							Integer.class.getName(), 0));
699 			functionBuilder.getParameters().add(
700 					FunctionParameterDefinition.Builder.create("arg1",
701 							Integer.class.getName(), 1));
702 			functionBuilder.setReturnType(Integer.class.getName());
703 
704 			gcdFunction = functionBoService.createFunction(functionBuilder
705 					.build());
706 		}
707 
708 		PropositionParametersBuilder params = new PropositionParametersBuilder();
709 
710 		// leverage our stack based evaluation in reverse polish notation
711 		params.add("1024", PropositionParameterType.CONSTANT);
712 		params.add("768", PropositionParameterType.CONSTANT);
713 		params.add(gcdFunction.getId(), PropositionParameterType.FUNCTION); // this
714 																			// should
715 																			// evaluate
716 																			// first:
717 																			// gcd(1024,
718 																			// 768)
719 		params.add("256", PropositionParameterType.CONSTANT);
720 		params.add("=", PropositionParameterType.OPERATOR); // this should
721 															// evaluate second:
722 															// gcdResult == 256
723 
724 		return createRuleDefinition(nameSpace, agendaName + "::Rule3",
725 				contextDefinition, null, params);
726 	}
727 
728 	private RuleDefinition createRuleDefinition4(
729 			ContextDefinition contextDefinition, String agendaName,
730 			String nameSpace) {
731 
732 		PropositionParametersBuilder params1 = new PropositionParametersBuilder();
733 		params1.add(
734 				createTermDefinition(BOOL1, Boolean.class, contextDefinition)
735 						.getId(), PropositionParameterType.TERM);
736 		params1.add(
737 				createTermDefinition(BOOL2, Boolean.class, contextDefinition)
738 						.getId(), PropositionParameterType.TERM);
739 		params1.add("=", PropositionParameterType.OPERATOR);
740 
741 		PropositionParametersBuilder params2 = new PropositionParametersBuilder();
742 		params2.add(
743 				createTermDefinition(BOOL2, Boolean.class, contextDefinition)
744 						.getId(), PropositionParameterType.TERM);
745 		params2.add(
746 				createTermDefinition(BOOL1, Boolean.class, contextDefinition)
747 						.getId(), PropositionParameterType.TERM);
748 		params2.add("=", PropositionParameterType.OPERATOR);
749 
750 		return createRuleDefinition(nameSpace, agendaName + "::Rule4",
751 				contextDefinition, LogicalOperator.AND, params1, params2);
752 	}
753 
754 	private TermDefinition createTermDefinition2(
755 			ContextDefinition contextDefinition, String nameSpace) {
756 
757 		Map<String, String> queryArgs = new HashMap<String, String>();
758 		queryArgs.put("specification.namespace",
759 				contextDefinition.getNamespace());
760 		queryArgs.put("specification.name", "outputTermSpec");
761 		TermBo result = getBoService()
762 				.findByPrimaryKey(TermBo.class, queryArgs);
763 		if (result != null)
764 			return TermBo.to(result);
765 
766 		// output TermSpec
767 		TermSpecificationDefinition outputTermSpec = TermSpecificationDefinition.Builder
768 				.create(null, "outputTermSpec",
769 						contextDefinition.getNamespace(), "java.lang.String")
770 				.build();
771 		outputTermSpec = termBoService.createTermSpecification(outputTermSpec);
772 
773 		// prereq TermSpec
774 		TermSpecificationDefinition prereqTermSpec = TermSpecificationDefinition.Builder
775 				.create(null, PREREQ_TERM_NAME,
776 						contextDefinition.getNamespace(), "java.lang.String")
777 				.build();
778 		prereqTermSpec = termBoService.createTermSpecification(prereqTermSpec);
779 
780 		// Term Param
781 		TermParameterDefinition.Builder termParamBuilder2 = TermParameterDefinition.Builder
782 				.create(null, null, "testParamName", "testParamValue");
783 
784 		// Term
785 		TermDefinition termDefinition2 = TermDefinition.Builder.create(null,
786 				TermSpecificationDefinition.Builder.create(outputTermSpec),
787 				Collections.singletonList(termParamBuilder2)).build();
788 		termDefinition2 = termBoService.createTerm(termDefinition2);
789 
790 		// KrmsType for TermResolver
791 		KrmsTypeDefinition.Builder krmsTermResolverTypeDefnBuilder = KrmsTypeDefinition.Builder
792 				.create("KrmsTestResolverType", nameSpace);
793 		krmsTermResolverTypeDefnBuilder
794 				.setServiceName("testTermResolverTypeService");
795 
796 		KrmsTypeDefinition krmsTermResolverTypeDefinition = krmsTypeRepository
797 				.createKrmsType(krmsTermResolverTypeDefnBuilder.build());
798 
799 		// TermResolver
800 		TermResolverDefinition termResolverDef = TermResolverDefinition.Builder
801 				.create(null,
802 						contextDefinition.getNamespace(),
803 						"testResolver1",
804 						krmsTermResolverTypeDefinition.getId(),
805 						TermSpecificationDefinition.Builder
806 								.create(outputTermSpec),
807 						Collections
808 								.singleton(TermSpecificationDefinition.Builder
809 										.create(prereqTermSpec)), null,
810 						Collections.singleton("testParamName")).build();
811 		termResolverDef = termBoService.createTermResolver(termResolverDef);
812 
813 		return termDefinition2;
814 	}
815 
816 	private static class PropositionParametersBuilder {
817 
818 		// poor OOD but this is quick and dirty :-P
819 		private List<Object[]> params = new ArrayList<Object[]>();
820 
821 		public PropositionParametersBuilder add(String value,
822 				PropositionParameterType type) {
823 			if (type == null)
824 				throw new IllegalArgumentException("type must not be null");
825 			params.add(new Object[] { value, type });
826 			return this;
827 		}
828 
829 		public List<PropositionParameter.Builder> build() {
830 			int seqCounter = 0;
831 
832 			List<PropositionParameter.Builder> results = new ArrayList<PropositionParameter.Builder>();
833 
834 			for (Object[] param : params) {
835 				results.add(PropositionParameter.Builder.create(null, null,
836 						(String) param[0],
837 						((PropositionParameterType) param[1]).getCode(),
838 						seqCounter++));
839 			}
840 
841 			return results;
842 		}
843 	}
844 
845 	@Override
846 	protected List<Lifecycle> getSuiteLifecycles() {
847 		// TODO Auto-generated method stub
848 		List<Lifecycle> steps = super.getSuiteLifecycles();
849 		int cnt = -1;
850 		for (int i = 0; i < steps.size(); i++) {
851 			if (steps.get(i) instanceof ClearDatabaseLifecycle) {
852 				cnt = i;
853 			}
854 		}
855 		if (cnt > 0) {
856 			steps.remove(cnt + 1);
857 			steps.remove(cnt);
858 
859 		}
860 		return steps;
861 	}
862 
863 	protected void createAllLumTermDefinitions(String nameSpace) {
864 		// Create all the terms...
865 		createNumberOfCreditsTermDefinition(nameSpace);
866 		createDeptOrgNumberTermDefinition(nameSpace);
867 		createProposedCourseTermDefinition(nameSpace);
868 		createApprovedCourseTermDefinition(nameSpace);
869 	}
870 
871 	//
872 	private void createNumberOfCreditsTermDefinition(String nameSpace) {
873 		// TODO NINA Add the context link to the Term Specification
874 		TermSpecificationDefinition termSpec = createTermSpecification(nameSpace, TERM_SPEC_CREDITS);
875 
876 		TermDefinition termDefinition = TermDefinition.Builder.create(
877 				null,
878 				TermSpecificationDefinition.Builder.create(termSpec), null).build();
879 		
880 		termDefinition = termBoService.createTerm(termDefinition);
881 
882 	}
883 
884 	private TermSpecificationDefinition createTermSpecification(String nameSpace, String termSpecName) {
885 		Map<String, String> queryArgs = new HashMap<String, String>();
886 		queryArgs.put("namespace", nameSpace);
887 		queryArgs.put("name", termSpecName);
888 		TermSpecificationBo termSpecBo = getBoService().findByPrimaryKey(
889 				TermSpecificationBo.class, queryArgs);
890 		//
891 		TermSpecificationDefinition termSpec = null;
892 		if (termSpecBo == null) {
893 			 termSpec = TermSpecificationDefinition.Builder
894 					.create(null, termSpecName, nameSpace,
895 							String.class.getCanonicalName()).build();
896 
897 			termSpec = termBoService.createTermSpecification(termSpec);
898 			
899 		} else {
900 			termSpec = termSpecBo.to(termSpecBo);
901 		}
902 		return termSpec;
903 	}
904 
905 	private void createDeptOrgNumberTermDefinition(String nameSpace) {
906 
907 		Map<String, String> queryArgs = new HashMap<String, String>();
908 		queryArgs.put("namespace", nameSpace);
909 		queryArgs.put("name", TERM_SPEC_ORG_NUMBER);
910 		TermSpecificationBo termSpecBo = getBoService().findByPrimaryKey(
911 				TermSpecificationBo.class, queryArgs);
912 		//
913 		TermSpecificationDefinition termSpec = null;
914 		if (termSpecBo == null) {
915 			 termSpec = TermSpecificationDefinition.Builder
916 					.create(null, TERM_SPEC_ORG_NUMBER, nameSpace,
917 							String.class.getCanonicalName()).build();
918 
919 			termSpec = termBoService.createTermSpecification(termSpec);
920 			
921 		} else {
922 			termSpec = termSpecBo.to(termSpecBo);
923 		}
924 
925 		TermDefinition termDefinition = TermDefinition.Builder.create(
926 				null,
927 				TermSpecificationDefinition.Builder.create(termSpec), null)
928 				.build();
929 		
930 		termDefinition = termBoService.createTerm(termDefinition);
931 
932 	}
933 
934 	private void createProposedCourseTermDefinition(String nameSpace) {
935 
936 		Map<String, String> queryArgs = new HashMap<String, String>();
937 		queryArgs.put("namespace", nameSpace);
938 		queryArgs.put("name", TERM_SPEC_COURSE);
939 		TermSpecificationBo termSpecBo = getBoService().findByPrimaryKey(
940 				TermSpecificationBo.class, queryArgs);
941 		//
942 		TermSpecificationDefinition termSpec = null;
943 		if (termSpecBo == null) {
944 			 termSpec = TermSpecificationDefinition.Builder
945 					.create(null, TERM_SPEC_COURSE, nameSpace,
946 							String.class.getCanonicalName()).build();
947 
948 			termSpec = termBoService.createTermSpecification(termSpec);
949 			
950 		} else {
951 			termSpec = termSpecBo.to(termSpecBo);
952 		}
953 
954 		TermDefinition termDefinition = TermDefinition.Builder.create(
955 				null,
956 				TermSpecificationDefinition.Builder.create(termSpec), null)
957 				.build();
958 		
959 		termDefinition = termBoService.createTerm(termDefinition);
960 
961 	}
962 
963 	private void createApprovedCourseTermDefinition(String nameSpace) {
964 
965 		Map<String, String> queryArgs = new HashMap<String, String>();
966 		queryArgs.put("namespace", nameSpace);
967 		queryArgs.put("name", TERM_SPEC_COURSE);
968 		TermSpecificationBo termSpecBo = getBoService().findByPrimaryKey(
969 				TermSpecificationBo.class, queryArgs);
970 		//
971 		TermSpecificationDefinition termSpec = null;
972 		if (termSpecBo == null) {
973 			 termSpec = TermSpecificationDefinition.Builder
974 					.create(null, TERM_SPEC_COURSE, nameSpace,
975 							String.class.getCanonicalName()).build();
976 
977 			termSpec = termBoService.createTermSpecification(termSpec);
978 			
979 		} else {
980 			termSpec = termSpecBo.to(termSpecBo);
981 		}
982 
983 		TermDefinition termDefinition = TermDefinition.Builder.create(
984 				null,
985 				TermSpecificationDefinition.Builder.create(termSpec), null)
986 				.build();
987 		
988 		termDefinition = termBoService.createTerm(termDefinition);
989 
990 	}
991 }