001 /**
002 * Copyright 2005-2011 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.rice.krms.test;
017
018 import org.joda.time.DateTime;
019 import org.junit.Before;
020 import org.junit.Test;
021 import org.kuali.rice.core.api.lifecycle.Lifecycle;
022 import org.kuali.rice.kew.util.PerformanceLogger;
023 import org.kuali.rice.krms.api.KrmsApiServiceLocator;
024 import org.kuali.rice.krms.api.engine.EngineResults;
025 import org.kuali.rice.krms.api.engine.ExecutionFlag;
026 import org.kuali.rice.krms.api.engine.ExecutionOptions;
027 import org.kuali.rice.krms.api.engine.Facts;
028 import org.kuali.rice.krms.api.engine.ResultEvent;
029 import org.kuali.rice.krms.api.engine.SelectionCriteria;
030 import org.kuali.rice.krms.api.repository.LogicalOperator;
031 import org.kuali.rice.krms.api.repository.action.ActionDefinition;
032 import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
033 import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
034 import org.kuali.rice.krms.api.repository.context.ContextDefinition;
035 import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
036 import org.kuali.rice.krms.api.repository.function.FunctionParameterDefinition;
037 import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
038 import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
039 import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
040 import org.kuali.rice.krms.api.repository.proposition.PropositionType;
041 import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
042 import org.kuali.rice.krms.api.repository.term.TermDefinition;
043 import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
044 import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
045 import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
046 import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
047 import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
048 import org.kuali.rice.krms.impl.repository.ActionBoService;
049 import org.kuali.rice.krms.impl.repository.AgendaBoService;
050 import org.kuali.rice.krms.impl.repository.FunctionBoServiceImpl;
051 import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
052 import org.kuali.rice.krms.impl.repository.RuleBoService;
053 import org.kuali.rice.krms.impl.repository.TermBo;
054 import org.kuali.rice.krms.impl.repository.TermBoService;
055 import org.kuali.rice.krms.impl.repository.TermSpecificationBo;
056 import org.kuali.rice.test.BaselineTestCase.BaselineMode;
057 import org.kuali.rice.test.BaselineTestCase.Mode;
058 import org.kuali.rice.test.ClearDatabaseLifecycle;
059 import org.springframework.transaction.annotation.Transactional;
060
061 import java.util.ArrayList;
062 import java.util.Collections;
063 import java.util.HashMap;
064 import java.util.List;
065 import java.util.Map;
066
067 import static org.junit.Assert.*;
068
069 @BaselineMode(Mode.CLEAR_DB)
070 public class KSLumKRMSDataSetupTest extends KSLumAbstractBoTest {
071
072 public static final String CAMPUS_CODE_TERM_NAME = "campusCodeTermSpec";
073
074 static final String NAMESPACE1 = "KRMS_TEST_1";
075 static final String NAMESPACE2 = "KRMS_TEST_2";
076 static final String KSNAMESPACE = "KR-RULE-TEST";
077 static final String TSUNAMI_EVENT = "Tsunami";
078 static final String EARTHQUAKE_EVENT = "Earthquake";
079 static final String KSContextRepeatableforCredit = "Repeatable for Credit";
080 static final String CONTEXT2 = "Context2";
081 static final String NAME = "name";
082 static final String CONTEXT1_QUALIFIER = "KSLum Qualifer 1";
083 static final String CONTEXT1_QUALIFIER_VALUE = "KSLum Qualifer 1 - Value";
084 static final String CONTEXT2_QUALIFIER = "KSLum Qualifer 1";
085 static final String CONTEXT2_QUALIFIER_VALUE = "KSLum Qualifer 2 - Value";
086 static final String AGENDA1 = "TestAgenda1";
087 static final String AGENDA2 = "Agenda2";
088 static final String AGENDA3 = "Agenda3";
089 static final String AGENDA4 = "Agenda4";
090 static final String AGENDA_MayBeRepeatedForAMaxOfnCredits = "May be repeated for a maximum of <n> credits";
091 static final String AGENDA_MustNotHaveSuccessfullyCompletedCourse = "Must not have successfully completed <course>";
092 static final String AGENDA_MustHaveSuccessfullyCompletedAMinOfnCreditsFromCoursesInTheOrg = "Must have successfully completed a minimum of <n> credits from courses in the <org>";
093
094 static final String PREREQ_TERM_NAME = "prereqTermSpec";
095 static final String PREREQ_TERM_VALUE = "prereqValue";
096 static final String NAMESPACE_CODE = "namespaceCode";
097 static final String BOOL1 = "bool1";
098 static final String BOOL2 = "bool2";
099
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 }