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.kew.util.PerformanceLogger;
022 import org.kuali.rice.krms.api.KrmsApiServiceLocator;
023 import org.kuali.rice.krms.api.engine.EngineResults;
024 import org.kuali.rice.krms.api.engine.ExecutionFlag;
025 import org.kuali.rice.krms.api.engine.ExecutionOptions;
026 import org.kuali.rice.krms.api.engine.Facts;
027 import org.kuali.rice.krms.api.engine.ResultEvent;
028 import org.kuali.rice.krms.api.engine.SelectionCriteria;
029 import org.kuali.rice.krms.api.repository.LogicalOperator;
030 import org.kuali.rice.krms.api.repository.action.ActionDefinition;
031 import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
032 import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
033 import org.kuali.rice.krms.api.repository.context.ContextDefinition;
034 import org.kuali.rice.krms.api.repository.function.FunctionDefinition;
035 import org.kuali.rice.krms.api.repository.function.FunctionParameterDefinition;
036 import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
037 import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
038 import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
039 import org.kuali.rice.krms.api.repository.proposition.PropositionType;
040 import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
041 import org.kuali.rice.krms.api.repository.term.TermDefinition;
042 import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
043 import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
044 import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
045 import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
046 import org.kuali.rice.krms.impl.repository.ActionBoService;
047 import org.kuali.rice.krms.impl.repository.AgendaBoService;
048 import org.kuali.rice.krms.impl.repository.FunctionBoServiceImpl;
049 import org.kuali.rice.krms.impl.repository.KrmsRepositoryServiceLocator;
050 import org.kuali.rice.krms.impl.repository.RuleBoService;
051 import org.kuali.rice.krms.impl.repository.TermBo;
052 import org.kuali.rice.krms.impl.repository.TermBoService;
053 import org.kuali.rice.test.BaselineTestCase.BaselineMode;
054 import org.kuali.rice.test.BaselineTestCase.Mode;
055 import org.springframework.transaction.annotation.Transactional;
056
057 import java.util.ArrayList;
058 import java.util.Collections;
059 import java.util.HashMap;
060 import java.util.List;
061 import java.util.Map;
062
063 import static org.junit.Assert.*;
064
065 @BaselineMode(Mode.CLEAR_DB)
066 public class RepositoryCreateAndExecuteIntegrationTest extends AbstractBoTest {
067
068 public static final String CAMPUS_CODE_TERM_NAME = "campusCodeTermSpec";
069
070 static final String NAMESPACE1 = "KRMS_TEST_1";
071 static final String NAMESPACE2 = "KRMS_TEST_2";
072 static final String KSNAMESPACE = "KS-SYS";
073 static final String TSUNAMI_EVENT = "Tsunami";
074 static final String EARTHQUAKE_EVENT = "Earthquake";
075 static final String CONTEXT1 = "Context1 Nina";
076 static final String CONTEXT2 = "Context2";
077 static final String NAME = "name";
078 static final String CONTEXT1_QUALIFIER = "Context1Qualifier";
079 static final String CONTEXT1_QUALIFIER_VALUE = "BLAH1";
080 static final String CONTEXT2_QUALIFIER = "Context2Qualifier";
081 static final String CONTEXT2_QUALIFIER_VALUE = "BLAH2";
082 static final String AGENDA1 = "TestAgenda1";
083 static final String AGENDA2 = "Agenda2";
084 static final String AGENDA3 = "Agenda3";
085 static final String AGENDA4 = "Agenda4";
086 static final String PREREQ_TERM_NAME = "prereqTermSpec";
087 static final String PREREQ_TERM_VALUE = "prereqValue";
088 static final String NAMESPACE_CODE = "namespaceCode";
089 static final String BOOL1 = "bool1";
090 static final String BOOL2 = "bool2";
091
092 // // Services needed for creation:
093 private TermBoService termBoService;
094
095 private RuleBoService ruleBoService;
096 private AgendaBoService agendaBoService;
097 private ActionBoService actionBoService;
098 private FunctionBoServiceImpl functionBoService;
099
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 }