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    }