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