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 }