001/*
002 * To change this template, choose Tools | Templates
003 * and open the template in the editor.
004 */
005package org.kuali.rice.krms.impl.repository;
006
007import java.util.ArrayList;
008import java.util.Date;
009import java.util.LinkedHashMap;
010import java.util.LinkedHashSet;
011import java.util.List;
012import java.util.Map;
013import java.util.Set;
014import javax.xml.namespace.QName;
015import org.junit.After;
016import org.junit.AfterClass;
017import static org.junit.Assert.*;
018import org.junit.Before;
019import org.junit.BeforeClass;
020import org.junit.Test;
021import org.junit.Ignore;
022import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
023import org.kuali.rice.krms.api.repository.LogicalOperator;
024import org.kuali.rice.krms.api.repository.RuleManagementService;
025import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
026import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
027import org.kuali.rice.krms.api.repository.context.ContextDefinition;
028import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate;
029import org.kuali.rice.krms.api.repository.language.NaturalLanguageUsage;
030import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
031import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
032import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
033import org.kuali.rice.krms.api.repository.proposition.PropositionType;
034import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
035import org.kuali.rice.krms.api.repository.term.TermDefinition;
036import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
037import org.kuali.rice.krms.api.repository.term.TermRepositoryService;
038import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
039import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
040import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
041import org.kuali.rice.krms.impl.repository.mock.KrmsConfigurationLoader;
042import org.kuali.student.common.util.UUIDHelper;
043import org.kuali.student.r2.common.dto.ContextInfo;
044import org.kuali.student.r2.common.exceptions.*;
045import org.kuali.student.r2.common.util.constants.LuiServiceConstants;
046import org.kuali.student.r2.core.constants.KSKRMSServiceConstants;
047import org.kuali.student.r2.core.process.krms.KSKRMSTestCase;
048import org.kuali.student.r2.core.versionmanagement.dto.VersionDisplayInfo;
049import org.kuali.student.r2.lum.clu.dto.CluInfo;
050import org.kuali.student.r2.lum.clu.dto.CluSetInfo;
051import org.kuali.student.r2.lum.clu.service.CluService;
052import org.kuali.student.r2.lum.lu.service.impl.CluDataLoader;
053import org.kuali.student.r2.lum.lu.service.impl.CluServiceMockImpl;
054import org.kuali.student.r2.lum.util.constants.CluServiceConstants;
055import java.util.Arrays;
056import org.kuali.rice.krms.api.repository.reference.ReferenceObjectBinding;
057import org.kuali.rice.krms.impl.util.KrmsRuleManagementCopyMethods;
058import org.kuali.rice.krms.impl.util.KrmsRuleManagementCopyMethodsImpl;
059
060/**
061 *
062 * @author nwright
063 */
064// TODO: KSENROLL-7265  remove ignore per larry's request that all @Ignore's have an associated jira 
065@Ignore
066public class RuleManagementServiceImplTest extends KSKRMSTestCase {
067
068    private KrmsTypeRepositoryService krmsTypeRepositoryService = null;
069    private RuleManagementService ruleManagementService = null;
070    private TermRepositoryService termRepositoryService = null;
071    private CluService cluService = null;
072    private KrmsRuleManagementCopyMethods krmsRuleManagementCopyMethods = null;
073
074    @BeforeClass
075    public static void setUpClass() {
076    }
077
078    @AfterClass
079    public static void tearDownClass() {
080    }
081    private ContextInfo contextInfo;
082
083    @Before
084    public void setUp() throws Exception {
085        super.setUp();
086        contextInfo = new ContextInfo();
087        contextInfo.setPrincipalId("TESTUSER");
088        contextInfo.setCurrentDate(new Date());
089
090        this.krmsTypeRepositoryService = (KrmsTypeRepositoryService) GlobalResourceLoader.getService(QName.valueOf("krmsTypeRepositoryService"));
091        this.termRepositoryService = (TermRepositoryService) GlobalResourceLoader.getService(QName.valueOf("termRepositoryService"));
092        this.ruleManagementService = (RuleManagementService) GlobalResourceLoader.getService(QName.valueOf("ruleManagementService"));
093        KrmsRuleManagementCopyMethodsImpl copyImpl = new KrmsRuleManagementCopyMethodsImpl();
094//        copyImpl.setKrmsTypeRepositoryService(krmsTypeRepositoryService);
095        copyImpl.setRuleManagementService(ruleManagementService);
096        this.krmsRuleManagementCopyMethods = copyImpl;
097        KrmsConfigurationLoader loader = new KrmsConfigurationLoader();
098//        loader.setKrmsTypeRepositoryService(this.krmsTypeRepositoryService);
099//        loader.setRuleManagementService(this.ruleManagementService);
100//        loader.setTermRepositoryService(this.termRepositoryService);
101//        loader.loadConfiguration();
102
103        this.cluService = new CluServiceMockImpl();
104        CluDataLoader cluDataLoader = new CluDataLoader();
105        cluDataLoader.setCluService(cluService);
106        cluDataLoader.setContextInfo(contextInfo);
107        cluDataLoader.load();
108
109    }
110
111    @After
112    public void tearDown() {
113    }
114
115    @Test
116    public void testCreateSimpleProposition() {
117        this.createCheckBasicAgendaFor1OfCluSet23();
118    }
119
120    @Test
121    public void testCopyingSimpleProposition() {
122        String namespace = KSKRMSServiceConstants.NAMESPACE_CODE;
123        String fromReferenceDiscriminatorType = CluServiceConstants.CREDIT_COURSE_LU_TYPE_KEY;
124        String fromReferenceObjectId = "COURSE1";
125        String toReferenceDiscriminatorType = LuiServiceConstants.COURSE_OFFERING_TYPE_KEY;
126        String toReferenceObjectId = "COURSEOFFERING1";
127
128        // delete any rules if there are any
129        int bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(fromReferenceDiscriminatorType, fromReferenceObjectId);
130        System.out.println("number of existing bindings deleted for " + fromReferenceObjectId + " count=" + bindingsDeleted);
131        bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(toReferenceDiscriminatorType, toReferenceObjectId);
132        System.out.println("number of existing bindings deleted for " + toReferenceObjectId + " count=" + bindingsDeleted);
133
134
135        AgendaDefinition agenda = this.createCheckBasicAgendaFor1OfCluSet23();
136        String krmsDiscriminatorType = KSKRMSServiceConstants.KRMS_DISCRIMINATOR_TYPE_AGENDA;
137        String krmsObjectId = agenda.getId();
138
139        ReferenceObjectBinding.Builder bindingBldr = ReferenceObjectBinding.Builder.create(krmsDiscriminatorType,
140                krmsObjectId,
141                namespace,
142                fromReferenceDiscriminatorType,
143                fromReferenceObjectId);
144        ReferenceObjectBinding binding = this.ruleManagementService.createReferenceObjectBinding(bindingBldr.build());
145
146        List<String> optionKeys = new ArrayList<String>();
147        List<ReferenceObjectBinding> list = null;
148        try {
149            list = this.krmsRuleManagementCopyMethods.deepCopyReferenceObjectBindingsFromTo(
150                    fromReferenceDiscriminatorType,
151                    fromReferenceObjectId,
152                    toReferenceDiscriminatorType,
153                    toReferenceObjectId,
154                    optionKeys);
155        } catch (Exception e) {
156            throw new RuntimeException(e);
157        }
158
159        assertNotNull(list);
160        assertEquals(1, list.size());
161        ReferenceObjectBinding copy = list.get(0);
162        assertEquals(toReferenceObjectId, copy.getReferenceObjectId());
163        assertEquals(LuiServiceConstants.COURSE_OFFERING_TYPE_KEY, copy.getReferenceDiscriminatorType());
164        checkCopy(binding, list.get(0));
165
166
167        // delete any rules that were created
168        bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(fromReferenceDiscriminatorType,
169                fromReferenceObjectId);
170        System.out.println("number of existing bindings deleted for " + fromReferenceObjectId + " count=" + bindingsDeleted);
171        bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(toReferenceDiscriminatorType,
172                toReferenceObjectId);
173        System.out.println("number of existing bindings deleted for " + toReferenceObjectId + " count=" + bindingsDeleted);
174    }
175
176    @Test
177    public void testCopyingCompoundProposition() {
178        String namespace = KSKRMSServiceConstants.NAMESPACE_CODE;
179        // TODO: KSENROLL-7291 convert the discriminator type to use the ref object uri instead of the lu type type
180//        String fromReferenceDiscriminatorType = CourseServiceConstants.COURSE_NAMESPACE_URI;
181        String fromReferenceDiscriminatorType = CluServiceConstants.CREDIT_COURSE_LU_TYPE_KEY;
182        String fromReferenceObjectId = "COURSE2";
183        // TODO: KSENROLL-7291 convert the discriminator type to use the ref object uri instead of the lu type type
184//        String toReferenceDiscriminatorType = CourseOfferingServiceConstants.REF_OBJECT_URI_COURSE_OFFERING,
185        String toReferenceDiscriminatorType = LuiServiceConstants.COURSE_OFFERING_TYPE_KEY;
186        String toReferenceObjectId = "COURSEOFFERING2";
187
188        // delete any rules if there are any
189        int bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(fromReferenceDiscriminatorType,
190                fromReferenceObjectId);
191        System.out.println("number of existing bindings deleted for " + fromReferenceObjectId + " count=" + bindingsDeleted);
192        bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(toReferenceDiscriminatorType,
193                toReferenceObjectId);
194        System.out.println("number of existing bindings deleted for " + toReferenceObjectId + " count=" + bindingsDeleted);
195
196
197        ContextDefinition context = this.findCreateContext();
198        AgendaDefinition agenda = createCheckEmptyAgenda(context);
199        agenda = updateCheckAgendaFirstItemAddingEmptyRule(agenda);
200
201        PropositionDefinition.Builder propBldr1 = this.constructFreeFormTextPropositionBulider("My first Text Value");
202        CluSetInfo cluSet = this.findCreateCluSet23();
203        PropositionDefinition.Builder propBldr2 = createNOfCluSetPropositionBuilder(1, cluSet);
204        cluSet = this.findCreateCluSet456();
205        PropositionDefinition.Builder propBldr3 = createNOfCluSetPropositionBuilder(2, cluSet);
206
207        PropositionDefinition.Builder andPropBldr = this.makeAndCompoundProposition(propBldr2, propBldr3);
208        PropositionDefinition.Builder orPropBldr = this.makeOrCompoundProposition(propBldr1, andPropBldr);
209        agenda = updateCheckFirstItemSettingPropositionOnRule(agenda, orPropBldr);
210
211        String krmsDiscriminatorType = KSKRMSServiceConstants.KRMS_DISCRIMINATOR_TYPE_AGENDA;
212        String krmsObjectId = agenda.getId();
213
214        ReferenceObjectBinding.Builder bindingBldr = ReferenceObjectBinding.Builder.create(krmsDiscriminatorType,
215                krmsObjectId,
216                namespace,
217                fromReferenceDiscriminatorType,
218                fromReferenceObjectId);
219        ReferenceObjectBinding binding = this.ruleManagementService.createReferenceObjectBinding(bindingBldr.build());
220
221        List<String> optionKeys = new ArrayList<String>();
222        List<ReferenceObjectBinding> list = null;
223        try {
224            list = this.krmsRuleManagementCopyMethods.deepCopyReferenceObjectBindingsFromTo(
225                    fromReferenceDiscriminatorType,
226                    fromReferenceObjectId,
227                    toReferenceDiscriminatorType,
228                    toReferenceObjectId,
229                    optionKeys);
230        } catch (Exception e) {
231            throw new RuntimeException(e);
232        }
233
234        assertNotNull(list);
235        assertEquals(1, list.size());
236        ReferenceObjectBinding copy = list.get(0);
237        assertEquals(toReferenceObjectId, copy.getReferenceObjectId());
238        assertEquals(LuiServiceConstants.COURSE_OFFERING_TYPE_KEY, copy.getReferenceDiscriminatorType());
239        checkCopy(binding, list.get(0));
240
241        // delete any rules that were created
242        bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(fromReferenceDiscriminatorType,
243                fromReferenceObjectId);
244        System.out.println("number of existing bindings deleted for " + fromReferenceObjectId + " count=" + bindingsDeleted);
245        bindingsDeleted = this.krmsRuleManagementCopyMethods.deleteReferenceObjectBindingsCascade(toReferenceDiscriminatorType,
246                toReferenceObjectId);
247        System.out.println("number of existing bindings deleted for " + toReferenceObjectId + " count=" + bindingsDeleted);
248
249    }
250
251    private void checkCopy(ReferenceObjectBinding orig, ReferenceObjectBinding copy) {
252        assertNotEquals(orig.getId(), copy.getId());
253        assertEquals(orig.getKrmsDiscriminatorType(), copy.getKrmsDiscriminatorType());
254        assertNotEquals(orig.getKrmsObjectId(), copy.getKrmsObjectId());
255        AgendaDefinition origAgenda = this.ruleManagementService.getAgenda(orig.getKrmsObjectId());
256        AgendaDefinition copyAgenda = this.ruleManagementService.getAgenda(copy.getKrmsObjectId());
257        checkCopy(origAgenda, copyAgenda);
258    }
259
260    private void checkCopy(AgendaDefinition orig, AgendaDefinition copy) {
261        if (orig == null && copy == null) {
262            return;
263        }
264        assertNotEquals(orig.getId(), copy.getId());
265        assertEquals(orig.getContextId(), copy.getContextId());
266        // names have to be different but shouldn't they be similar?
267        assertNotEquals(orig.getName(), copy.getName());
268        assertEquals(orig.getTypeId(), copy.getTypeId());
269        assertEquals(orig.isActive(), copy.isActive());
270        assertEquals(orig.getAttributes(), copy.getAttributes());
271        assertNotEquals(orig.getFirstItemId(), copy.getFirstItemId());
272        AgendaItemDefinition origItem = this.ruleManagementService.getAgendaItem(orig.getFirstItemId());
273        AgendaItemDefinition copyItem = this.ruleManagementService.getAgendaItem(copy.getFirstItemId());
274        checkCopy(origItem, copyItem);
275    }
276
277    private void checkCopy(AgendaItemDefinition orig, AgendaItemDefinition copy) {
278        if (orig == null && copy == null) {
279            return;
280        }
281        assertNotEquals(orig.getId(), copy.getId());
282        assertNotEquals(orig.getAgendaId(), copy.getAgendaId());
283        checkCopy(orig.getAlwaysId(), copy.getAlwaysId());
284        checkCopy(orig.getAlways(), copy.getAlways());
285        checkCopy(orig.getRuleId(), copy.getRuleId());
286        checkCopy(orig.getRule(), copy.getRule());
287        checkCopy(orig.getSubAgendaId(), copy.getSubAgendaId());
288        checkCopy(orig.getSubAgenda(), copy.getSubAgenda());
289        checkCopy(orig.getWhenFalseId(), copy.getWhenFalseId());
290        checkCopy(orig.getWhenFalse(), copy.getWhenFalse());
291        checkCopy(orig.getWhenTrueId(), copy.getWhenTrueId());
292        checkCopy(orig.getWhenTrue(), copy.getWhenTrue());
293    }
294
295    private void checkCopy(String orig, String copy) {
296        if (orig == null && copy == null) {
297            return;
298        }
299        assertNotEquals(orig, copy);
300    }
301
302    private void checkCopy(RuleDefinition orig, RuleDefinition copy) {
303        if (orig == null && copy == null) {
304            return;
305        }
306        assertNotEquals(orig.getId(), copy.getId());
307        assertEquals(orig.getAttributes(), copy.getAttributes());
308        assertEquals(orig.getActions(), copy.getActions());
309        assertEquals(orig.getDescription(), copy.getDescription());
310        // names have to be different but shouldn't they be similar?
311        assertNotEquals(orig.getName(), copy.getName());
312        assertEquals(orig.getNamespace(), copy.getNamespace());
313        if (orig.getPropId() != null) {
314            checkCopy(orig.getPropId(), copy.getPropId());
315        }
316        checkCopy(orig.getProposition(), copy.getProposition());
317        assertEquals(orig.getTypeId(), copy.getTypeId());
318        assertEquals(orig.isActive(), copy.isActive());
319    }
320
321    private void checkCopy(PropositionDefinition orig, PropositionDefinition copy) {
322        if (orig == null && copy == null) {
323            return;
324        }
325        assertNotEquals(orig.getId(), copy.getId());
326        assertNotEquals(orig.getRuleId(), copy.getRuleId());
327        assertEquals(orig.getTypeId(), copy.getTypeId());
328        assertEquals(orig.getDescription(), copy.getDescription());
329        assertEquals(orig.getPropositionTypeCode(), copy.getPropositionTypeCode());
330        assertEquals(orig.getCompoundOpCode(), copy.getCompoundOpCode());
331        assertEquals(orig.getCompoundSequenceNumber(), copy.getCompoundSequenceNumber());
332        if (orig.getCompoundComponents() != null) {
333            assertEquals(orig.getCompoundComponents().size(), copy.getCompoundComponents().size());
334            for (int i = 0; i < orig.getCompoundComponents().size(); i++) {
335                PropositionDefinition origCompoundComponent = orig.getCompoundComponents().get(i);
336                PropositionDefinition copyCompoundComponent = copy.getCompoundComponents().get(i);
337                checkCopy(origCompoundComponent, copyCompoundComponent);
338            }
339        }
340        if (orig.getParameters() != null) {
341            assertEquals(orig.getParameters().size(), copy.getParameters().size());
342            for (int i = 0; i < orig.getParameters().size(); i++) {
343                PropositionParameter origParam = orig.getParameters().get(i);
344                PropositionParameter copyParam = copy.getParameters().get(i);
345                checkCopy(origParam, copyParam);
346            }
347        }
348    }
349
350    private void checkCopy(PropositionParameter orig, PropositionParameter copy) {
351        if (orig == null && copy == null) {
352            return;
353        }
354        assertNotEquals(orig.getId(), copy.getId());
355        assertEquals(orig.getParameterType(), copy.getParameterType());
356        assertNotEquals(orig.getPropId(), copy.getPropId());
357        assertEquals(orig.getSequenceNumber(), copy.getSequenceNumber());
358        if (orig.getParameterType().equals(PropositionParameterType.TERM.getCode())) {
359            checkCopy(orig.getTermValue(), copy.getTermValue());
360        } else {
361            assertEquals(orig.getValue(), copy.getValue());
362            assertNull (copy.getTermValue());
363        }
364    }
365
366    private void checkCopy(TermDefinition orig, TermDefinition copy) {
367        if (orig == null && copy == null) {
368            return;
369        }
370        assertNotEquals(orig.getId(), copy.getId());
371        assertEquals(orig.getDescription(), copy.getDescription());
372        checkCopy(orig.getSpecification(), copy.getSpecification());
373        if (orig.getParameters() != null) {
374            assertEquals(orig.getParameters().size(), copy.getParameters().size());
375            // Might have order the lists by Name to make sure they compare properly
376            for (int i = 0; i < orig.getParameters().size(); i++) {
377                TermParameterDefinition origParam = orig.getParameters().get(i);
378                TermParameterDefinition copyParam = copy.getParameters().get(i);
379                checkCopy(origParam, copyParam);
380            }
381        }
382    }
383
384    private void checkCopy(TermSpecificationDefinition orig, TermSpecificationDefinition copy) {
385        if (orig == null && copy == null) {
386            return;
387        }
388        // term spec should NOT be copied so the ids should be the same!
389        assertEquals(orig.getId(), copy.getId());
390        assertEquals(orig.getDescription(), copy.getDescription());
391        assertEquals(orig.getName(), copy.getName());
392        assertEquals(orig.getNamespace(), copy.getNamespace());
393        assertEquals(orig.getDescription(), copy.getDescription());
394    }
395
396    private void checkCopy(TermParameterDefinition orig, TermParameterDefinition copy) {
397        if (orig == null && copy == null) {
398            return;
399        }
400        // term spec should NOT be copied so the ids should be the same!
401        assertNotEquals(orig.getId(), copy.getId());
402        assertNotEquals(orig.getTermId(), copy.getTermId());
403        assertEquals(orig.getName(), copy.getName());
404        assertEquals(orig.getValue(), copy.getValue());
405    }
406
407    @Test
408    public void testBasicCreateCompoundProposition() {
409        ContextDefinition context = this.findCreateContext();
410        AgendaDefinition agenda = createCheckEmptyAgenda(context);
411        agenda = updateCheckAgendaFirstItemAddingEmptyRule(agenda);
412
413        PropositionDefinition.Builder propBldr1 = this.constructFreeFormTextPropositionBulider("My first Text Value");
414        CluSetInfo cluSet = this.findCreateCluSet23();
415        PropositionDefinition.Builder propBldr2 = createNOfCluSetPropositionBuilder(1, cluSet);
416        cluSet = this.findCreateCluSet456();
417        PropositionDefinition.Builder propBldr3 = createNOfCluSetPropositionBuilder(2, cluSet);
418
419        PropositionDefinition.Builder andPropBldr = this.makeAndCompoundProposition(propBldr2, propBldr3);
420        PropositionDefinition.Builder orPropBldr = this.makeOrCompoundProposition(propBldr1, andPropBldr);
421        agenda = updateCheckFirstItemSettingPropositionOnRule(agenda, orPropBldr);
422    }
423
424    @Test
425    public void testChangeFromSimple2CompoundProposition() {
426        ContextDefinition context = this.findCreateContext();
427        AgendaDefinition agenda = createCheckEmptyAgenda(context);
428        agenda = updateCheckAgendaFirstItemAddingEmptyRule(agenda);
429
430        PropositionDefinition.Builder propBldr1 = this.constructFreeFormTextPropositionBulider("My first Text Value");
431        CluSetInfo cluSet = this.findCreateCluSet23();
432        PropositionDefinition.Builder propBldr2 = createNOfCluSetPropositionBuilder(1, cluSet);
433
434        cluSet = this.findCreateCluSet456();
435        PropositionDefinition.Builder propBldr3 = createNOfCluSetPropositionBuilder(2, cluSet);
436
437        agenda = updateCheckFirstItemSettingPropositionOnRule(agenda, propBldr3);
438
439        AgendaItemDefinition firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
440        PropositionDefinition prop = firstItem.getRule().getProposition();
441        propBldr3 = PropositionDefinition.Builder.create(prop);
442        PropositionDefinition.Builder andPropBldr = this.makeAndCompoundProposition(propBldr2, propBldr3);
443        PropositionDefinition.Builder orPropBldr = this.makeOrCompoundProposition(propBldr1, andPropBldr);
444        agenda = updateCheckFirstItemSettingPropositionOnRule(agenda, orPropBldr);
445    }
446
447    private PropositionDefinition.Builder makeAndCompoundProposition(PropositionDefinition.Builder... childPropBldrs) {
448        String propId = null;
449        String propTypeCode = PropositionType.COMPOUND.getCode();
450        String ruleId = null;
451        KrmsTypeDefinition type = this.krmsTypeRepositoryService.getTypeByName(KSKRMSServiceConstants.NAMESPACE_CODE,
452                KSKRMSServiceConstants.PROPOSITION_TYPE_COMPOUND_AND);
453        String typeId = type.getId();
454        List<PropositionParameter.Builder> parameters = new ArrayList<PropositionParameter.Builder>();
455        PropositionDefinition.Builder mainBldr = PropositionDefinition.Builder.create(propId, propTypeCode, ruleId, typeId, parameters);
456        mainBldr.setCompoundOpCode(LogicalOperator.AND.getCode());
457        List<PropositionDefinition.Builder> childList = Arrays.asList(childPropBldrs);
458//        System.out.println ("order for AND is:");
459//        for (PropositionDefinition.Builder childBldr : childList) {
460//            System.out.println ("order is " + childBldr);
461//        }
462        mainBldr.setCompoundComponents(childList);
463        return mainBldr;
464    }
465
466    private PropositionDefinition.Builder makeOrCompoundProposition(PropositionDefinition.Builder... childPropBldrs) {
467        String propId = null;
468        String propTypeCode = PropositionType.COMPOUND.getCode();
469        String ruleId = null;
470        KrmsTypeDefinition type = this.krmsTypeRepositoryService.getTypeByName(KSKRMSServiceConstants.NAMESPACE_CODE,
471                KSKRMSServiceConstants.PROPOSITION_TYPE_COMPOUND_OR);
472        String typeId = type.getId();
473        List<PropositionParameter.Builder> parameters = new ArrayList<PropositionParameter.Builder>();
474        PropositionDefinition.Builder mainBldr = PropositionDefinition.Builder.create(propId, propTypeCode, ruleId, typeId, parameters);
475        mainBldr.setCompoundOpCode(LogicalOperator.OR.getCode());
476        List<PropositionDefinition.Builder> childList = Arrays.asList(childPropBldrs);
477//        System.out.println ("order for OR is:");
478//        for (PropositionDefinition.Builder childBldr : childList) {
479//            System.out.println ("order is " + childBldr);
480//        }
481        mainBldr.setCompoundComponents(childList);
482        return mainBldr;
483    }
484
485    @Test
486    public void testUpdateChangingPropositionConstantValuefrom1To2() {
487        AgendaDefinition agenda = createCheckBasicAgendaFor1OfCluSet23();
488
489        AgendaItemDefinition firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
490        PropositionDefinition prop = firstItem.getRule().getProposition();
491        PropositionDefinition.Builder propBldr = PropositionDefinition.Builder.create(prop);
492        propBldr = this.updateNOfCluSetProposition(propBldr, 2);
493        this.updateCheckFirstItemSettingPropositionOnRule(agenda, propBldr);
494    }
495
496    @Test
497    public void testUpdateCompletelyReplacingExistingPropositionCreatingOrphan() {
498        AgendaDefinition agenda = createCheckBasicAgendaFor1OfCluSet23();
499
500        PropositionDefinition.Builder propBldr = this.constructFreeFormTextPropositionBulider("My first Text Value");
501        updateCheckFirstItemSettingPropositionOnRule(agenda, propBldr);
502    }
503
504    @Test
505    public void testCreateMultiAgendaItems() {
506        //Create agenda
507        ContextDefinition context = this.findCreateContext();
508        AgendaDefinition agenda = createCheckEmptyAgenda(context);
509        AgendaItemDefinition firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
510        AgendaItemDefinition.Builder firstItemBldr = createMultiAgendaItems(firstItem);
511
512        this.ruleManagementService.updateAgendaItem(firstItemBldr.build());
513        AgendaItemDefinition returnItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
514        checkMultiAgendaItem(firstItemBldr, returnItem);
515
516    }
517
518    @Test
519    public void testUpdateChangingTermParameters() {
520        //Create agenda
521        ContextDefinition context = this.findCreateContext();
522        AgendaDefinition agenda = createCheckEmptyAgenda(context);
523        AgendaItemDefinition firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
524        this.ruleManagementService.updateAgendaItem(createMultiAgendaItems(firstItem).build());
525
526        firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
527        AgendaItemDefinition.Builder itemBuilder = AgendaItemDefinition.Builder.create(firstItem);
528        PropositionParameter.Builder propParameter = null;
529        for(PropositionParameter.Builder parameter : itemBuilder.getWhenTrue().getRule().getProposition().getParameters()){
530            if(parameter.getTermValue()!=null){
531                propParameter = parameter;
532            }
533        }
534
535        TermDefinition.Builder term = TermDefinition.Builder.create(propParameter.getTermValue());
536        for(TermParameterDefinition.Builder parameter : term.getParameters()){
537            parameter.setValue("The updated free form proposition");
538            break;
539        }
540        propParameter.setTermValue(term.build());
541
542        this.ruleManagementService.updateAgendaItem(itemBuilder.build());
543        AgendaItemDefinition returnItem = this.ruleManagementService.getAgendaItem(itemBuilder.getId());
544        checkMultiAgendaItem(itemBuilder, returnItem);
545
546    }
547
548    private AgendaItemDefinition.Builder createMultiAgendaItems(AgendaItemDefinition firstItem){
549        //Add first item details.
550        PropositionDefinition.Builder firstPropBldr = this.constructFreeFormTextPropositionBulider("The first free form proposition");
551        RuleDefinition.Builder firstRuleBldr = this.constructEmptyRuleBuilder();
552        firstRuleBldr.setProposition(firstPropBldr);
553        AgendaItemDefinition.Builder firstItemBldr = AgendaItemDefinition.Builder.create(firstItem);
554        firstItemBldr.setRule(firstRuleBldr);
555
556        //Add second item details.
557        PropositionDefinition.Builder secondPropBldr = this.constructFreeFormTextPropositionBulider("The second free form proposition");
558        RuleDefinition.Builder secondRuleBldr = this.constructEmptyRuleBuilder();
559        secondRuleBldr.setProposition(secondPropBldr);
560        AgendaItemDefinition.Builder secondItemBldr = AgendaItemDefinition.Builder.create(null, firstItem.getAgendaId());
561        secondItemBldr.setRule(secondRuleBldr);
562        firstItemBldr.setWhenTrue(secondItemBldr);
563
564        return firstItemBldr;
565    }
566
567    private void checkMultiAgendaItem(AgendaItemDefinition.Builder itemBuilder, AgendaItemDefinition item){
568        this.checkRule(itemBuilder.getRule(), item.getRule());
569        assertNotNull(item.getWhenTrue());
570        this.checkRule(itemBuilder.getWhenTrue().getRule(), item.getWhenTrue().getRule());
571    }
572
573    private AgendaDefinition createCheckBasicAgendaFor1OfCluSet23() {
574        ContextDefinition context = this.findCreateContext();
575        AgendaDefinition agenda = createCheckEmptyAgenda(context);
576        agenda = updateCheckAgendaFirstItemAddingEmptyRule(agenda);
577        CluSetInfo cluSet = this.findCreateCluSet23();
578        PropositionDefinition.Builder propBldr = createNOfCluSetPropositionBuilder(1, cluSet);
579        agenda = updateCheckFirstItemSettingPropositionOnRule(agenda, propBldr);
580        return agenda;
581    }
582
583    private CluSetInfo findCreateCluSet23() {
584        // create the cluset
585        CluInfo courseClu2 = this.getClu("COURSE2");
586        CluInfo courseClu3 = this.getClu("COURSE3");
587        List<String> versionIndIds = this.getVersionIndIds(courseClu2, courseClu3);
588        CluSetInfo cluSet = findCreateCluSet("cluSet23", "Courses 2 & 3", versionIndIds);
589        return cluSet;
590    }
591
592    private CluSetInfo findCreateCluSet456() {
593        // create the cluset
594        CluInfo courseClu4 = this.getClu("COURSE4");
595        CluInfo courseClu5 = this.getClu("COURSE5");
596        CluInfo courseClu6 = this.getClu("COURSE6");
597        List<String> versionIndIds = this.getVersionIndIds(courseClu4, courseClu5, courseClu6);
598        CluSetInfo cluSet = findCreateCluSet("cluSet456", "Courses 4, 5 & 6", versionIndIds);
599        return cluSet;
600    }
601
602    private ContextDefinition findCreateContext() {
603        // find/create the context corresponding to this context type.
604        ContextDefinition.Builder contextBldr = ContextDefinition.Builder.create(KSKRMSServiceConstants.NAMESPACE_CODE,
605                KSKRMSServiceConstants.CONTEXT_COURSE_REQUIREMENTS);
606        contextBldr.setTypeId(KSKRMSServiceConstants.CONTEXT_TYPE_DEFAULT);
607        contextBldr.setDescription(KSKRMSServiceConstants.CONTEXT_COURSE_REQUIREMENTS);
608        contextBldr.setActive(true);
609        ContextDefinition context = this.ruleManagementService.findCreateContext(contextBldr.build());
610        this.checkContext(contextBldr, context);
611        return context;
612    }
613
614    private void checkContext(ContextDefinition.Builder contextBldr, ContextDefinition context) {
615        assertNotNull(context);
616        assertNotNull(context.getId());
617        assertEquals(contextBldr.getName(), context.getName());
618        assertEquals(contextBldr.getNamespace(), context.getNamespace());
619        assertEquals(contextBldr.getTypeId(), context.getTypeId());
620        assertEquals(contextBldr.isActive(), context.isActive());
621    }
622
623    private AgendaDefinition createCheckEmptyAgenda(ContextDefinition context) {
624        // find/create the context corresponding to this context type.
625        // create the agenda
626        KrmsTypeDefinition agendaType = this.krmsTypeRepositoryService.getTypeByName(KSKRMSServiceConstants.NAMESPACE_CODE,
627                KSKRMSServiceConstants.AGENDA_TYPE_COURSE_ENROLLMENTELIGIBILITY);
628        assertNotNull(agendaType);
629        String id = null; // set by service when create is called
630        // For testing use a GUID instead of anchorClu.getId () so we always get a new one for testing
631        String name = UUIDHelper.genStringUUID();
632//        String name = agendaType.getName() + " for " + anchorClu.getOfficialIdentifier().getCode() + " (" + anchorClu.getId() + ")";
633        String typeId = agendaType.getId();
634        String contextId = context.getId();
635        AgendaDefinition.Builder agendaBldr = AgendaDefinition.Builder.create(id, name, typeId, contextId);
636        agendaBldr.setActive(false);
637        AgendaDefinition agenda = this.ruleManagementService.findCreateAgenda(agendaBldr.build());
638        this.checkAgenda(agendaBldr, agenda);
639        return agenda;
640    }
641
642    private void checkAgenda(AgendaDefinition.Builder agendaBldr, AgendaDefinition agenda) {
643        assertNotNull(agenda);
644        assertNotNull(agenda.getId());
645        assertEquals(agendaBldr.getName(), agenda.getName());
646        assertEquals(agendaBldr.getContextId(), agenda.getContextId());
647        assertEquals(agendaBldr.getTypeId(), agenda.getTypeId());
648        assertEquals(agendaBldr.isActive(), agenda.isActive());
649        if (agendaBldr.getFirstItemId() == null) {
650            assertNotNull(agenda.getFirstItemId());
651        } else {
652            assertEquals(agendaBldr.getFirstItemId(), agenda.getFirstItemId());
653        }
654    }
655
656    private AgendaDefinition updateCheckAgendaFirstItemAddingEmptyRule(AgendaDefinition agenda) {
657        AgendaItemDefinition firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
658        assertNull(firstItem.getRule());
659        RuleDefinition.Builder ruleBldr = null;
660        ruleBldr = this.constructEmptyRuleBuilder();
661        AgendaItemDefinition.Builder itemBldr = AgendaItemDefinition.Builder.create(firstItem);
662        itemBldr.setRule(ruleBldr);
663        this.ruleManagementService.updateAgendaItem(itemBldr.build());
664        agenda = this.ruleManagementService.getAgenda(agenda.getId());
665        firstItem = this.ruleManagementService.getAgendaItem(firstItem.getId());
666        checkAgendaItem(agenda, itemBldr, firstItem);
667        return agenda;
668    }
669
670    private void checkAgendaItem(AgendaDefinition agenda, AgendaItemDefinition.Builder itemBldr, AgendaItemDefinition item) {
671        assertNotNull(item);
672        assertNotNull(item.getId());
673        assertNotNull(agenda.getId(), item.getAgendaId());
674        if (item.getRule() == null) {
675            assertNull(item.getRuleId());
676        }
677        if (item.getRuleId() == null) {
678            assertNull(item.getRule());
679        }
680        if (item.getRule() != null) {
681            assertEquals(item.getRuleId(), item.getRule().getId());
682            checkRule(itemBldr.getRule(), item.getRule());
683        }
684    }
685
686    private RuleDefinition.Builder constructEmptyRuleBuilder() {
687        // make rule
688        KrmsTypeDefinition ruleType = this.krmsTypeRepositoryService.getTypeByName(KSKRMSServiceConstants.NAMESPACE_CODE,
689                KSKRMSServiceConstants.RULE_TYPE_COURSE_ACADEMICREADINESS_STUDENTELIGIBILITYPREREQ);
690        String ruleId = null; // sevice sets id
691
692        // name has to be unique within namespace and max 100 characters.
693        // For testing use a GUID instead of anchorClu.getId () so we always get a new one for testing
694        String name = UUIDHelper.genStringUUID();
695//        name = anchorClu.getOfficialIdentifier().getCode() + " " + ruleType.getName() + " (" + anchorClu.getId() + ")";
696        String namespace = KSKRMSServiceConstants.NAMESPACE_CODE;
697        String typeId = ruleType.getId();
698        String propId = null;
699        RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(ruleId, name, namespace, typeId, propId);
700        ruleBldr.setActive(true);
701        return ruleBldr;
702    }
703
704    private AgendaDefinition updateCheckFirstItemSettingPropositionOnRule(AgendaDefinition agenda, PropositionDefinition.Builder propBldr) {
705        AgendaItemDefinition firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
706        RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(firstItem.getRule());
707        ruleBldr.setProposition(propBldr);
708
709        AgendaItemDefinition.Builder itemBldr = AgendaItemDefinition.Builder.create(firstItem);
710        itemBldr.setRule(ruleBldr);
711        AgendaItemDefinition item2Update = itemBldr.build();
712        this.ruleManagementService.updateAgendaItem(item2Update);
713        agenda = this.ruleManagementService.getAgenda(agenda.getId());
714        firstItem = this.ruleManagementService.getAgendaItem(firstItem.getId());
715        this.checkAgendaItem(agenda, itemBldr, firstItem);
716        return agenda;
717    }
718
719    private void checkRule(RuleDefinition.Builder ruleBldr, RuleDefinition rule) {
720        assertNotNull(rule.getId());
721        assertEquals(ruleBldr.getName(), rule.getName());
722        assertEquals(ruleBldr.getNamespace(), rule.getNamespace());
723        assertEquals(ruleBldr.getTypeId(), rule.getTypeId());
724        if (ruleBldr.getProposition() == null) {
725            assertNull(rule.getProposition());
726        } else {
727            this.checkProposition(rule.getId(), ruleBldr.getProposition(), rule.getProposition());
728        }
729    }
730
731    private void checkProposition(String ruleId, PropositionDefinition.Builder propBldr, PropositionDefinition prop) {
732        assertEquals(ruleId, prop.getRuleId());
733//        assertEquals(propBldr.getCompoundSequenceNumber(), prop.getCompoundSequenceNumber());
734        assertEquals(propBldr.getPropositionTypeCode(), prop.getPropositionTypeCode());
735        assertEquals(propBldr.getTypeId(), prop.getTypeId());
736        if (propBldr.getPropositionTypeCode().equals(PropositionType.SIMPLE.getCode())) {
737            this.checkSimpleProposition(propBldr, prop);
738        } else if (propBldr.getPropositionTypeCode().equals(PropositionType.COMPOUND.getCode())) {
739            this.checkCompoundProposition(ruleId, propBldr, prop);
740        } else {
741            fail("unknown proposition type " + propBldr.getPropositionTypeCode());
742        }
743    }
744
745    private void checkCompoundProposition(String ruleId, PropositionDefinition.Builder propBldr, PropositionDefinition prop) {
746        assertEquals(PropositionType.COMPOUND.getCode(), propBldr.getPropositionTypeCode());
747        assertEquals(propBldr.getPropositionTypeCode(), prop.getPropositionTypeCode());
748//        assertEquals(propBldr.getDescription(), prop.getDescription());
749        assertNotNull(propBldr.getCompoundOpCode());
750        assertEquals(propBldr.getCompoundOpCode(), prop.getCompoundOpCode());
751        // should not have parameters those are for simple propositions
752        assertTrue(propBldr.getParameters().isEmpty());
753        assertTrue(prop.getParameters().isEmpty());
754        assertEquals(propBldr.getCompoundComponents().size(), prop.getCompoundComponents().size());
755
756        if (propBldr.getCompoundComponents().size() < 2) {
757            fail("there must be at least 2 compound components " + propBldr.getCompoundComponents().size());
758        }
759        for (int i = 0; i < propBldr.getCompoundComponents().size(); i++) {
760            PropositionDefinition childProp = prop.getCompoundComponents().get(i);
761            PropositionDefinition.Builder childPropBldr = propBldr.getCompoundComponents().get(i);
762            this.checkProposition(ruleId, childPropBldr, childProp);
763        }
764    }
765
766    private void checkSimpleProposition(PropositionDefinition.Builder propBldr, PropositionDefinition prop) {
767
768        assertEquals(PropositionType.SIMPLE.getCode(), propBldr.getPropositionTypeCode());
769        assertEquals(propBldr.getPropositionTypeCode(), prop.getPropositionTypeCode());
770        // should not have compound stuff those are for compound propositions
771        assertNull(propBldr.getCompoundOpCode());
772        assertNull(prop.getCompoundOpCode());
773        if (propBldr.getCompoundComponents() != null) {
774            assertTrue(propBldr.getCompoundComponents().isEmpty());
775            assertTrue(prop.getCompoundComponents().isEmpty());
776        }
777        assertEquals(propBldr.getParameters().size(),
778                prop.getParameters().size());
779        for (int i = 0; i < propBldr.getParameters().size(); i++) {
780            PropositionParameter.Builder propParamBldr = propBldr.getParameters().get(0);
781            PropositionParameter propParam = prop.getParameters().get(0);
782
783            assertNotNull(propParam.getId());
784            assertNotNull(propParamBldr.getParameterType());
785            assertNotNull(propParamBldr.getSequenceNumber());
786            assertEquals(propParamBldr.getSequenceNumber(),
787                    propParam.getSequenceNumber());
788            assertEquals(propParamBldr.getParameterType(),
789                    propParam.getParameterType());
790            assertEquals(prop.getId(), propParam.getPropId());
791            if (propParamBldr.getParameterType().equals(PropositionParameterType.TERM.getCode())) {
792                this.checkTerm(propParam.getValue(), propParamBldr.getTermValue(), propParam.getTermValue());
793            } else {
794                assertEquals(propParamBldr.getValue(), propParam.getValue());
795                assertNull(propParam.getTermValue());
796            }
797        }
798    }
799
800    private void checkTerm(String value, TermDefinition termBldr, TermDefinition term) {
801        assertNotNull(termBldr);
802        assertNotNull(term);
803        assertNotNull(term.getId());
804        assertEquals(value, term.getId());
805        assertNotNull(termBldr.getSpecification());
806        assertNotNull(term.getSpecification());
807        assertEquals(termBldr.getSpecification().getName(),
808                term.getSpecification().getName());
809        assertEquals(termBldr.getSpecification().getNamespace(),
810                term.getSpecification().getNamespace());
811        assertEquals(termBldr.getParameters().size(),
812                term.getParameters().size());
813        for (int i = 0; i < term.getParameters().size(); i++) {
814            TermParameterDefinition termParamBldr = termBldr.getParameters().get(i);
815            TermParameterDefinition termParam = term.getParameters().get(i);
816            this.checkTermParam(term.getId(), termParamBldr, termParam);
817        }
818    }
819
820    private void checkTermParam(String termId, TermParameterDefinition termParamBldr, TermParameterDefinition termParam) {
821        assertNotNull(termParam.getId());
822        assertEquals(termId, termParam.getTermId());
823        assertNotNull(termParam.getName());
824        assertEquals(termParamBldr.getName(), termParam.getName());
825        assertEquals(termParamBldr.getValue(), termParam.getValue());
826    }
827    private static final String N_OF_CLU_SET_TERM_NAME = "NumberOfCompletedCourses";
828    private static final String N_OF_CLU_SET_OPERATOR = "<=";
829
830    private PropositionDefinition.Builder createNOfCluSetPropositionBuilder(int n, CluSetInfo cluSet) {
831
832        // create all the parameters
833        List<PropositionParameter.Builder> parameters = new ArrayList<PropositionParameter.Builder>();
834        String constantValue = "" + n;
835
836        // first the parameter to the parameter! (actually the term parameter to the proposition parameter that is a term!
837        List<TermParameterDefinition.Builder> termParameters = new ArrayList<TermParameterDefinition.Builder>();
838        String id = null; //set by service
839        String termId = null;
840        String name = "CourseSetId";
841        String value = cluSet.getId(); // this was created when the cluSet was built
842        TermParameterDefinition.Builder termParamBldr = TermParameterDefinition.Builder.create(id, termId, name, value);
843        termParameters.add(termParamBldr);
844
845        id = null; // set by service
846        TermSpecificationDefinition termSpec =
847                this.termRepositoryService.getTermSpecificationByNameAndNamespace(N_OF_CLU_SET_TERM_NAME,
848                        KSKRMSServiceConstants.NAMESPACE_CODE);
849        assertNotNull(termSpec);
850        assertEquals(N_OF_CLU_SET_TERM_NAME, termSpec.getName());
851        TermSpecificationDefinition.Builder termSpecBldr = TermSpecificationDefinition.Builder.create(termSpec);
852        String description = termSpec.getName() + " for " + cluSet.getId();
853        TermDefinition.Builder termBldr = TermDefinition.Builder.create(id, termSpecBldr, termParameters);
854        termBldr.setDescription(description);
855
856
857        // do the term parameter first
858        id = null; // should be set by service
859        String propId = null; // should also be set by the service when the create on the proposition happens
860        value = null;  // set by service
861        String parameterType = PropositionParameterType.TERM.getCode();
862        Integer sequenceNumber = 1;
863        PropositionParameter.Builder propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
864        propParamBldr.setTermValue(termBldr.build());
865        parameters.add(propParamBldr);
866
867
868        // do the constant value next
869        id = null; // should be set by service
870        propId = null; // should also be set by the service when the create on the proposition happens
871        value = constantValue;
872        parameterType = PropositionParameterType.CONSTANT.getCode();
873        sequenceNumber = 2;
874        propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
875        parameters.add(propParamBldr);
876
877        // do the operator 
878        id = null; // should be set by service
879        propId = null; // should also be set by the service when the create on the proposition happens
880        value = N_OF_CLU_SET_OPERATOR;
881        parameterType = PropositionParameterType.OPERATOR.getCode();
882        sequenceNumber = 3;
883        propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
884        parameters.add(propParamBldr);
885
886        propId = null; // should be null until assigned by service
887        String propTypeCode = PropositionType.SIMPLE.getCode();
888        String ruleId = null;  // assigned by service
889        KrmsTypeDefinition propType = this.krmsTypeRepositoryService.getTypeByName(KSKRMSServiceConstants.NAMESPACE_CODE, KSKRMSServiceConstants.PROPOSITION_TYPE_COURSE_COURSESET_COMPLETED_NOF);
890        String typeId = propType.getId();
891        PropositionDefinition.Builder propBldr = PropositionDefinition.Builder.create(propId, propTypeCode, ruleId, typeId, parameters);
892//        propBldr.setDescription(propType.getName());
893        return propBldr;
894    }
895
896    private PropositionDefinition.Builder updateNOfCluSetProposition(PropositionDefinition.Builder propBldr, int n) {
897        PropositionParameter.Builder propParamBldr = propBldr.getParameters().get(1);
898        propParamBldr.setValue("" + n);
899        return propBldr;
900    }
901    private static final String FREE_FORM_TEXT_TERM_NAME = "FreeFormText";
902    private static final String FREE_FORM_TEXT_TERM_PARAM_NAME = "Text";
903    private static final String FREE_FORM_TEXT_CONSTANT_VALUE = "true";
904    private static final String FREE_FORM_TEXT_OPERATOR = "=";
905
906    private PropositionDefinition.Builder constructFreeFormTextPropositionBulider(String myText) {
907        // create all the parameters
908        List<PropositionParameter.Builder> parameters = new ArrayList<PropositionParameter.Builder>();
909
910
911        // first the parameter to the parameter! (actually the term parameter to the proposition parameter that is a term!
912        List<TermParameterDefinition.Builder> termParameters = new ArrayList<TermParameterDefinition.Builder>();
913        String id = null; //set by service
914        String termId = null;
915        TermParameterDefinition.Builder termParamBldr = TermParameterDefinition.Builder.create(id, termId, FREE_FORM_TEXT_TERM_PARAM_NAME, myText);
916        termParameters.add(termParamBldr);
917
918        id = null; // set by service
919        TermSpecificationDefinition termSpec =
920                this.termRepositoryService.getTermSpecificationByNameAndNamespace(FREE_FORM_TEXT_TERM_NAME,
921                        KSKRMSServiceConstants.NAMESPACE_CODE);
922        assertNotNull(termSpec);
923        assertEquals(FREE_FORM_TEXT_TERM_NAME, termSpec.getName());
924        TermSpecificationDefinition.Builder termSpecBldr = TermSpecificationDefinition.Builder.create(termSpec);
925        String description = termSpec.getName();
926        TermDefinition.Builder termBldr = TermDefinition.Builder.create(id, termSpecBldr, termParameters);
927        termBldr.setDescription(description);
928
929        // do the term parameter first
930        id = null; // should be set by service
931        String propId = null; // should also be set by the service when the create on the proposition happens
932        String value = null;  // set by service
933        String parameterType = PropositionParameterType.TERM.getCode();
934        Integer sequenceNumber = 1;
935        PropositionParameter.Builder propParamBldr = PropositionParameter.Builder.create(id,
936                propId, value, parameterType, sequenceNumber);
937        propParamBldr.setTermValue(termBldr.build());
938        parameters.add(propParamBldr);
939
940
941        // do the constant value next
942        id = null; // should be set by service
943        propId = null; // should also be set by the service when the create on the proposition happens
944        value = FREE_FORM_TEXT_CONSTANT_VALUE;
945        parameterType = PropositionParameterType.CONSTANT.getCode();
946        sequenceNumber = 2;
947        propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
948        parameters.add(propParamBldr);
949
950        // do the operator 
951        id = null; // should be set by service
952        propId = null; // should also be set by the service when the create on the proposition happens
953        value = FREE_FORM_TEXT_OPERATOR;
954        parameterType = PropositionParameterType.OPERATOR.getCode();
955        sequenceNumber = 3;
956        propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
957        parameters.add(propParamBldr);
958
959        propId = null; // should be null until assigned by service
960        String propTypeCode = PropositionType.SIMPLE.getCode();
961        String ruleId = null;  // assigned by service
962        KrmsTypeDefinition propType = this.krmsTypeRepositoryService.getTypeByName(KSKRMSServiceConstants.NAMESPACE_CODE, KSKRMSServiceConstants.PROPOSITION_TYPE_FREEFORM_TEXT);
963        String typeId = propType.getId();
964        PropositionDefinition.Builder propBldr = PropositionDefinition.Builder.create(propId, propTypeCode, ruleId, typeId, parameters);
965//        propBldr.setDescription(propType.getName());
966        return propBldr;
967    }
968
969    private CluSetInfo findCreateCluSet(String id, String name, List<String> versionIndIds) {
970        CluSetInfo cluSetInfo;
971        try {
972            cluSetInfo = this.cluService.getCluSet(id, contextInfo);
973            return cluSetInfo;
974        } catch (DoesNotExistException ex) {
975            // does not exist so create
976        } catch (Exception ex) {
977            throw new IllegalArgumentException(ex);
978        }
979        cluSetInfo = new CluSetInfo();
980        cluSetInfo.setId(id);
981        cluSetInfo.setTypeKey(CluServiceConstants.CLUSET_TYPE_CREDIT_COURSE);
982        cluSetInfo.setStateKey("Active");
983        cluSetInfo.setName(name);
984        cluSetInfo.setEffectiveDate(new Date());
985        cluSetInfo.setIsReferenceable(Boolean.TRUE);
986        cluSetInfo.setIsReusable(Boolean.FALSE);
987        cluSetInfo.setCluIds(versionIndIds);
988        try {
989            cluSetInfo = this.cluService.createCluSet(cluSetInfo.getTypeKey(), cluSetInfo, contextInfo);
990        } catch (Exception ex) {
991            throw new IllegalArgumentException(ex);
992        }
993        return cluSetInfo;
994    }
995
996    private List<String> getVersionIndIds(CluInfo... clus) {
997        List<String> list = new ArrayList<String>();
998        for (CluInfo clu : clus) {
999            list.add(clu.getVersion().getVersionIndId());
1000        }
1001        return list;
1002    }
1003
1004    private CluInfo getClu(String id) {
1005        try {
1006            return this.cluService.getClu(id, contextInfo);
1007        } catch (Exception ex) {
1008            throw new RuntimeException(ex);
1009        }
1010    }
1011    // cache
1012    private transient Map<String, NaturalLanguageUsage> name2NaturalLanguageUsageCache = null;
1013
1014    private NaturalLanguageUsage getNaturalLanguageUsage(String name, String namespace) {
1015        if (name2NaturalLanguageUsageCache == null) {
1016            name2NaturalLanguageUsageCache = new LinkedHashMap<String, NaturalLanguageUsage>();
1017        }
1018        String key = namespace + ":" + name;
1019        NaturalLanguageUsage usage = name2NaturalLanguageUsageCache.get(key);
1020        if (usage != null) {
1021            return usage;
1022        }
1023        // get the usage
1024        usage = this.ruleManagementService.getNaturalLanguageUsageByNameAndNamespace(name, namespace);
1025        assertNotNull(usage);
1026        assertEquals(name, usage.getName());
1027        assertEquals(namespace, usage.getNamespace());
1028        name2NaturalLanguageUsageCache.put(key, usage);
1029        return usage;
1030    }
1031
1032    private NaturalLanguageUsage getTypeDescriptionUsage() {
1033        return this.getNaturalLanguageUsage(KSKRMSServiceConstants.KRMS_NL_TYPE_DESCRIPTION, KSKRMSServiceConstants.NAMESPACE_CODE);
1034    }
1035
1036    private NaturalLanguageUsage getRuleEditUsage() {
1037        return this.getNaturalLanguageUsage(KSKRMSServiceConstants.KRMS_NL_RULE_EDIT, KSKRMSServiceConstants.NAMESPACE_CODE);
1038    }
1039
1040    private NaturalLanguageUsage getPreviewUsage() {
1041        return this.getNaturalLanguageUsage(KSKRMSServiceConstants.KRMS_NL_PREVIEW, KSKRMSServiceConstants.NAMESPACE_CODE);
1042    }
1043
1044    private KrmsTypeDefinition simulateGettingCourseAgendaType() {
1045        KrmsTypeDefinition type = this.krmsTypeRepositoryService.getTypeByName(KSKRMSServiceConstants.NAMESPACE_CODE, KSKRMSServiceConstants.AGENDA_TYPE_COURSE);
1046        assertNotNull(type);
1047        assertEquals(KSKRMSServiceConstants.AGENDA_TYPE_COURSE, type.getName());
1048        assertEquals(KSKRMSServiceConstants.NAMESPACE_CODE, type.getNamespace());
1049        return type;
1050    }
1051
1052    private KrmsTypeDefinition simulateUserChoosingType(String title, List<KrmsTypeDefinition> types, String languageCode, int defaultIndex) {
1053        System.out.println(title);
1054        this.displayScreenDescriptions(types, languageCode);
1055        System.out.print("==> Choose: ");
1056        KrmsTypeDefinition selected = types.get(defaultIndex);
1057        System.out.println(selected.getName());
1058        return selected;
1059    }
1060
1061    private void displayScreenDescriptions(List<KrmsTypeDefinition> types, String languageCode) {
1062        for (KrmsTypeDefinition type : types) {
1063            System.out.println(this.getScreenDescription(type.getId(), languageCode));
1064        }
1065    }
1066
1067    private String getScreenDescription(String typeId, String languageCode) {
1068        // check there is a corresponding template so we can display on the screen what kind of rule this is
1069        NaturalLanguageTemplate template =
1070                this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
1071                typeId,
1072                this.getTypeDescriptionUsage().getId());
1073        if (template == null) {
1074            System.out.println("could not find template for " + typeId + " with language " + languageCode + " and for type description usage");
1075        }
1076        assertNotNull(template);
1077        assertEquals(languageCode, template.getLanguageCode());
1078        assertEquals(typeId, template.getTypeId());
1079        assertEquals(getTypeDescriptionUsage().getId(), template.getNaturalLanguageUsageId());
1080        return template.getTemplate();
1081    }
1082
1083    private NaturalLanguageTemplate getRuleEditUsageNaturalLanguageTemplate(String typeId, String languageCode) {
1084        // check there is a corresponding template so we can display on the screen what kind of rule this is
1085        NaturalLanguageTemplate template =
1086                this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
1087                typeId,
1088                this.getRuleEditUsage().getId());
1089        if (template == null) {
1090            System.out.println("could not find template for " + typeId + " with language " + languageCode + " and for rule edit usage");
1091        }
1092        assertNotNull(template);
1093        assertEquals(languageCode, template.getLanguageCode());
1094        assertEquals(typeId, template.getTypeId());
1095        assertEquals(getRuleEditUsage().getId(), template.getNaturalLanguageUsageId());
1096        return template;
1097    }
1098
1099    private void checkTypeNamesAnyOrder(Set<String> expected, List<KrmsTypeDefinition> types) {
1100        List<String> unexpected = new ArrayList<String>();
1101        for (KrmsTypeDefinition type : types) {
1102            if (!expected.remove(type.getName())) {
1103                unexpected.add(type.getName());
1104            }
1105        }
1106        if (!expected.isEmpty() || !unexpected.isEmpty()) {
1107            fail(expected.size() + " types expected that were not found " + expected
1108                    + " and "
1109                    + unexpected.size() + " types were found but not expected " + unexpected);
1110        }
1111    }
1112
1113    private void checkTypeNamesOrdered(Set<String> expected, List<KrmsTypeDefinition> types) {
1114        List<String> expectedOrdered = new ArrayList(expected);
1115        this.checkTypeNamesAnyOrder(expected, types);
1116        for (int i = 0; i < types.size(); i++) {
1117            if (!expectedOrdered.get(i).equals(types.get(i).getName())) {
1118                fail("Expected " + i + "th position to have " + expectedOrdered.get(i) + " but found " + types.get(i).getName());
1119            }
1120        }
1121    }
1122
1123    private CluInfo getCurrentCluInfoByVersionIndId(String id, ContextInfo contextInfo) {
1124        VersionDisplayInfo versionDisplayInfo = null;
1125        try {
1126            versionDisplayInfo = this.cluService.getCurrentVersion(CluServiceConstants.CLU_NAMESPACE_URI, id, contextInfo);
1127        } catch (Exception ex) {
1128            throw new IllegalArgumentException("Unexpected", ex);
1129        }
1130        try {
1131            return this.cluService.getClu(versionDisplayInfo.getId(), contextInfo);
1132        } catch (Exception ex) {
1133            throw new IllegalArgumentException("Unexpected", ex);
1134        }
1135    }
1136
1137    // commented out this test because it is brittle and what gets returned changes as the configuration changes
1138//    @Test
1139    public void testBasicTypeConfiguration() {
1140
1141        List<KrmsTypeDefinition> types = null;
1142        Set<String> expected = null;
1143        String languageCode = KSKRMSServiceConstants.LANGUAGE_CODE_ENGLISH;
1144        // check that we can get all the different context types
1145        types = this.krmsTypeRepositoryService.findAllContextTypes();
1146        expected = new LinkedHashSet<String>();
1147        // TODO: find out why all the context's were removed!
1148//        expected.add(KsKrmsConstants.CONTEXT_TYPE_COURSE);
1149//        expected.add(KsKrmsConstants.CONTEXT_TYPE_PROGRAM);
1150//        expected.add(KsKrmsConstants.CONTEXT_TYPE_COURSE_OFFERING);
1151        this.checkTypeNamesAnyOrder(expected, types);
1152
1153        // Typically the user does not actually select the context but it is
1154        // hardwired into the program, so the "context" is taken from where 
1155        // we are within the application, i.e. are we on the course requisites screen?
1156        System.out.println("Please choose which context of rules that you want to work on:");
1157        for (KrmsTypeDefinition type : types) {
1158            System.out.println("     " + this.getScreenDescription(type.getId(), languageCode));
1159        }
1160//        System.out.print("==> Choose: ");
1161//        String selectedId = this.simulateUserChoosingContextTypeId();
1162//        System.out.println(selectedId);
1163//        KrmsTypeDefinition selectedContextType = this.krmsTypeRepositoryService.getTypeById(selectedId);
1164//        description = this.getScreenDescription(selectedContextType.getId(), languageCode);
1165//        System.out.println("Editing Rules for Context: " + description);
1166
1167
1168        // 
1169        KrmsTypeDefinition courseAgendaType = this.simulateGettingCourseAgendaType();
1170        assertNotNull(courseAgendaType);
1171
1172        // Get all the agenda types for this course context type
1173
1174        types = this.krmsTypeRepositoryService.findAgendaTypesForAgendaType(courseAgendaType.getId());
1175        expected = new LinkedHashSet<String>();
1176        expected.add(KSKRMSServiceConstants.AGENDA_TYPE_COURSE_ENROLLMENTELIGIBILITY);
1177        expected.add(KSKRMSServiceConstants.AGENDA_TYPE_COURSE_CREDITCONSTRAINTS);
1178        this.checkTypeNamesOrdered(expected, types);
1179
1180        String title = "Please choose which type of rule you want to work on:";
1181        int defaultIndex = 0;
1182        KrmsTypeDefinition courseEligAgendaType = this.simulateUserChoosingType(title, types, languageCode, defaultIndex);
1183
1184        // Get all the agenda types for the main agenda type
1185        // Right now we don't do this we just have rule types so this should return an empty list
1186        types = this.krmsTypeRepositoryService.findAgendaTypesForAgendaType(courseEligAgendaType.getId());
1187        expected = new LinkedHashSet<String>();
1188        this.checkTypeNamesOrdered(expected, types);
1189
1190        // Get all the RULE types for the main agenda type
1191        types = this.krmsTypeRepositoryService.findRuleTypesForAgendaType(courseEligAgendaType.getId());
1192        expected = new LinkedHashSet<String>();
1193        expected.add(KSKRMSServiceConstants.RULE_TYPE_COURSE_ACADEMICREADINESS_STUDENTELIGIBILITYPREREQ);
1194        expected.add(KSKRMSServiceConstants.RULE_TYPE_COURSE_ACADEMICREADINESS_COREQ);
1195        expected.add(KSKRMSServiceConstants.RULE_TYPE_COURSE_RECOMMENDEDPREPARATION);
1196        expected.add(KSKRMSServiceConstants.RULE_TYPE_COURSE_ACADEMICREADINESS_ANTIREQ);
1197        this.checkTypeNamesOrdered(expected, types);
1198
1199        title = "Please choose which type of rule you want to work on:";
1200        defaultIndex = 0;
1201        KrmsTypeDefinition eligPrereqRuleType = this.simulateUserChoosingType(title, types, languageCode, defaultIndex);
1202
1203        // Get all the Proposition types for the rule type
1204        types = this.krmsTypeRepositoryService.findPropositionTypesForRuleType(eligPrereqRuleType.getId());
1205        expected = new LinkedHashSet<String>();
1206        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_FREEFORM_TEXT);
1207        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_SUCCESS_COMPL_COURSE);
1208        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_CUMULATIVE_GPA_MIN);
1209        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_ADMITTED_TO_PROGRAM);
1210        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_SUCCESS_CREDIT_COURSESET_COMPLETED_NOF);
1211        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_SUCCESS_CREDITS_COURSESET_COMPLETED_NOF_ORG);
1212        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_SUCCESS_COURSE_COURSESET_COMPLETED_ALL);
1213        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_SUCCESS_COURSE_COURSESET_COMPLETED_NOF);
1214        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_COURSE_COURSESET_GPA_MIN);
1215        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_COURSE_COURSESET_GRADE_MIN);
1216        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_COURSE_COURSESET_NOF_GRADE_MIN);
1217//        expected.add(KsKrmsConstants.PROPOSITION_TYPE_COURSE_COURSESET_GRADE_MAX);
1218        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_ADMITTED_TO_PROGRAM_CAMPUS);
1219//        expected.add(KsKrmsConstants.PROPOSITION_TYPE_NOTADMITTED_TO_PROGRAM);
1220        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_PERMISSION_INSTRUCTOR_REQUIRED);
1221        expected.add(KSKRMSServiceConstants.PROPOSITION_TYPE_PERMISSION_ADMIN_ORG);
1222//        expected.add(KsKrmsConstants.PROPOSITION_TYPE_COURSE_TEST_SCORE_MIN);
1223//        expected.add(KsKrmsConstants.PROPOSITION_TYPE_TEST_SCORE_BETWEEN_VALUES);
1224//        expected.add(KsKrmsConstants.PROPOSITION_TYPE_TEST_SCORE);
1225        this.checkTypeNamesOrdered(expected, types);
1226
1227        title = "Please choose which type of rule you want to work on:";
1228        defaultIndex = 7;
1229        KrmsTypeDefinition nOfCoursesPropositionType = this.simulateUserChoosingType(title, types, languageCode, defaultIndex);
1230        NaturalLanguageTemplate nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(nOfCoursesPropositionType.getId(), languageCode);
1231        assertNotNull(nlTemplate);
1232        assertEquals("#if($intValue == 1 && $courseCluSet.getCluList().size() == 1)Must have successfully completed $courseCluSet.getCluSetAsCode()#{else}Must have successfully completed a minimum of $intValue $NLHelper.getProperGrammar($intValue, \"course\") from $courseCluSet.getCluSetAsCode()#end", nlTemplate.getTemplate());
1233
1234//                <entry key="kuali.krms.proposition.type.success.course.courseset.completed.nof">
1235//                    <bean parent="TemplateInfo-parent"
1236//                          p:termSpecName="NumberOfCompletedCourses" p:operator="&lt;=" p:value="n">
1237//                        <property name="componentId" value="KRMS-MultiCourse-Section"/>
1238//                        <property name="constantComponentId" value="KRMS-NumberOfCourses-ConstantValue"/>
1239//                        <property name="componentBuilderClass" value="org.kuali.student.lum.lu.ui.krms.builder.MultiCourseComponentBuilder"/>
1240//                    </bean>
1241//                </entry>
1242
1243
1244        // Get all the parameter types for the proposition type
1245        types = this.krmsTypeRepositoryService.findPropositionParameterTypesForPropositionType(nOfCoursesPropositionType.getId());
1246        expected = new LinkedHashSet<String>();
1247        this.checkTypeNamesOrdered(expected, types);
1248
1249//        TermResolverDefinition termResolver =
1250//                this.termRepositoryService.getTermResolverByNameAndNamespace(termName,
1251//                KsKrmsConstants.NAMESPACE_CODE);
1252//        assertNotNull(termResolver);
1253//        assertEquals (termName, termResolver.getName());
1254    }
1255
1256    @Test
1257    public void testTranslateNaturalLanguageForProposition() {
1258        ContextDefinition context = this.findCreateContext();
1259        AgendaDefinition agenda = createCheckEmptyAgenda(context);
1260        agenda = updateCheckAgendaFirstItemAddingEmptyRule(agenda);
1261
1262        PropositionDefinition.Builder propBldr1 = this.constructFreeFormTextPropositionBulider("My first Text Value");
1263        CluSetInfo cluSet = this.findCreateCluSet23();
1264        PropositionDefinition.Builder propBldr2 = createNOfCluSetPropositionBuilder(1, cluSet);
1265        cluSet = this.findCreateCluSet456();
1266        PropositionDefinition.Builder propBldr3 = createNOfCluSetPropositionBuilder(2, cluSet);
1267
1268        PropositionDefinition.Builder andPropBldr = this.makeAndCompoundProposition(propBldr2, propBldr3);
1269        PropositionDefinition.Builder orPropBldr = this.makeOrCompoundProposition(propBldr1, andPropBldr);
1270
1271        AgendaItemDefinition firstItem = this.ruleManagementService.getAgendaItem(agenda.getFirstItemId());
1272        RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(firstItem.getRule());
1273        ruleBldr.setProposition(orPropBldr);
1274
1275        AgendaItemDefinition.Builder itemBldr = AgendaItemDefinition.Builder.create(firstItem);
1276        itemBldr.setRule(ruleBldr);
1277        AgendaItemDefinition item2Update = itemBldr.build();
1278        this.ruleManagementService.updateAgendaItem(item2Update);
1279        agenda = this.ruleManagementService.getAgenda(agenda.getId());
1280        firstItem = this.ruleManagementService.getAgendaItem(firstItem.getId());
1281
1282        List<NaturalLanguageUsage> usages = this.ruleManagementService.getNaturalLanguageUsagesByNamespace(KSKRMSServiceConstants.NAMESPACE_CODE);
1283
1284        System.out.println(this.ruleManagementService.translateNaturalLanguageForObject("KS-KRMS-NL-USAGE-1000", "agenda", agenda.getId(), "en"));
1285        System.out.println(this.ruleManagementService.translateNaturalLanguageForObject("KS-KRMS-NL-USAGE-1000", "rule", firstItem.getRule().getId(), "en"));
1286        System.out.println(this.ruleManagementService.translateNaturalLanguageForObject("KS-KRMS-NL-USAGE-1000", "proposition", firstItem.getRule().getProposition().getId(), "en"));
1287
1288    }
1289}