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.mock;
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 org.junit.After;
015import org.junit.AfterClass;
016import org.junit.Before;
017import org.junit.BeforeClass;
018import org.junit.Test;
019import static org.junit.Assert.*;
020import org.kuali.rice.krms.api.repository.RuleManagementService;
021import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
022import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
023import org.kuali.rice.krms.api.repository.context.ContextDefinition;
024import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate;
025import org.kuali.rice.krms.api.repository.language.NaturalLanguageUsage;
026import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
027import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
028import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
029import org.kuali.rice.krms.api.repository.proposition.PropositionType;
030import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
031import org.kuali.rice.krms.api.repository.term.TermDefinition;
032import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
033import org.kuali.rice.krms.api.repository.term.TermRepositoryService;
034import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
035import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
036import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
037import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
038import org.kuali.rice.krms.impl.repository.language.SimpleNaturalLanguageTemplater;
039import org.kuali.student.krms.naturallanguage.util.KsKrmsConstants;
040import org.kuali.student.r2.common.dto.ContextInfo;
041import org.kuali.student.r2.core.versionmanagement.dto.VersionDisplayInfo;
042import org.kuali.student.r2.lum.clu.dto.CluInfo;
043import org.kuali.student.r2.lum.clu.dto.CluSetInfo;
044import org.kuali.student.r2.lum.clu.service.CluService;
045import org.kuali.student.r2.lum.lu.service.impl.CluDataLoader;
046import org.kuali.student.r2.lum.lu.service.impl.CluServiceMockImpl;
047import org.kuali.student.r2.lum.util.constants.CluServiceConstants;
048
049/**
050 *
051 * @author nwright
052 */
053public class RuleManagementServiceMockImplTest {
054
055    public RuleManagementServiceMockImplTest() {
056    }
057    private KrmsTypeRepositoryService krmsTypeRepositoryService = null;
058    private RuleManagementService ruleManagementService = null;
059    private TermRepositoryService termRepositoryService = null;
060    private CluService cluService = null;
061
062    @BeforeClass
063    public static void setUpClass() {
064    }
065
066    @AfterClass
067    public static void tearDownClass() {
068    }
069    private ContextInfo contextInfo;
070
071    @Before
072    public void setUp() {
073        contextInfo = new ContextInfo();
074        contextInfo.setPrincipalId("TESTUSER");
075        contextInfo.setCurrentDate(new Date());
076
077        this.krmsTypeRepositoryService = new KrmsTypeRepositoryServiceMockImpl();
078        this.termRepositoryService = new TermRepositoryServiceMockImpl();
079        this.ruleManagementService = new RuleManagementServiceMockImpl();
080        ((RuleManagementServiceMockImpl) this.ruleManagementService).setTemplater(new SimpleNaturalLanguageTemplater());
081        ((RuleManagementServiceMockImpl) this.ruleManagementService).setTermRepositoryService(termRepositoryService);
082        KrmsConfigurationLoader loader = new KrmsConfigurationLoader();
083        loader.setKrmsTypeRepositoryService(this.krmsTypeRepositoryService);
084        loader.setRuleManagementService(this.ruleManagementService);
085        loader.setTermRepositoryService(this.termRepositoryService);
086        loader.loadConfiguration();
087
088        this.cluService = new CluServiceMockImpl();
089        CluDataLoader cluDataLoader = new CluDataLoader();
090        cluDataLoader.setCluService(cluService);
091        cluDataLoader.setContextInfo(contextInfo);
092        cluDataLoader.load();
093
094    }
095
096    @After
097    public void tearDown() {
098    }
099
100    @Test
101    public void testStadardAuthoringUsageCase() {
102        System.out.println("testStadardAuthoringUsageCase");
103
104        List<KrmsTypeDefinition> types = null;
105        Set<String> expected = null;
106        String languageCode = KsKrmsConstants.LANGUAGE_CODE_ENGLISH;
107
108        // check that we can get all the different context types
109        types = this.krmsTypeRepositoryService.findAllContextTypes();
110        expected = new LinkedHashSet<String>();
111        expected.add(KsKrmsConstants.CONTEXT_TYPE_COURSE);
112        expected.add(KsKrmsConstants.CONTEXT_TYPE_PROGRAM);
113        expected.add(KsKrmsConstants.CONTEXT_TYPE_COURSE_OFFERING);
114        this.checkTypeNamesAnyOrder(expected, types);
115
116        // Typically the user does not actually select the context but it is
117        // hardwired into the program, so the "context" is taken from where 
118        // we are within the application, i.e. are we on the course requisites screen?
119        System.out.println("Please choose which context of rules that you want to work on:");
120        for (KrmsTypeDefinition type : types) {
121            System.out.println("     " + this.getScreenDescription(type.getId(), languageCode));
122        }
123        System.out.print("==> Choose: ");
124        String selectedId = this.simulateUserChoosingContextTypeId();
125        System.out.println(selectedId);
126        KrmsTypeDefinition selectedContextType = this.krmsTypeRepositoryService.getTypeById(selectedId);
127        String description = this.getScreenDescription(selectedContextType.getId(), languageCode);
128        System.out.println("Editing Rules for Context: " + description);
129
130
131        // Get all the agenda types for this course context type
132        types = this.krmsTypeRepositoryService.findAgendaTypesForContextType(selectedContextType.getId());
133        expected = new LinkedHashSet<String>();
134        expected.add(KsKrmsConstants.AGENDA_TYPE_COURSE_ENROLLMENTELIGIBILITY);
135        expected.add(KsKrmsConstants.AGENDA_TYPE_COURSE_CREDITCONSTRAINTS);
136        this.checkTypeNamesOrdered(expected, types);
137
138        String title = "Please choose which type of rule you want to work on:";
139        int defaultIndex = 0;
140        KrmsTypeDefinition courseEligAgendaType = this.simulateUserChoosingType(title, types, languageCode, defaultIndex);
141
142        // Get all the agenda types for the main agenda type
143        // Right now we don't do this we just have rule types so this should return an empty list
144        types = this.krmsTypeRepositoryService.findAgendaTypesForAgendaType(courseEligAgendaType.getId());
145        expected = new LinkedHashSet<String>();
146        this.checkTypeNamesOrdered(expected, types);
147
148        // Get all the RULE types for the main agenda type
149        types = this.krmsTypeRepositoryService.findRuleTypesForAgendaType(courseEligAgendaType.getId());
150        expected = new LinkedHashSet<String>();
151        expected.add(KsKrmsConstants.RULE_TYPE_COURSE_ACADEMICREADINESS_STUDENTELIGIBILITYPREREQ);
152        expected.add(KsKrmsConstants.RULE_TYPE_COURSE_ACADEMICREADINESS_COREQ);
153        expected.add(KsKrmsConstants.RULE_TYPE_COURSE_RECOMMENDEDPREPARATION);
154        expected.add(KsKrmsConstants.RULE_TYPE_COURSE_ACADEMICREADINESS_ANTIREQ);
155        this.checkTypeNamesOrdered(expected, types);
156
157        title = "Please choose which type of rule you want to work on:";
158        defaultIndex = 0;
159        KrmsTypeDefinition eligPrereqRuleType = this.simulateUserChoosingType(title, types, languageCode, defaultIndex);
160
161        // Get all the Proposition types for the rule type
162        types = this.krmsTypeRepositoryService.findPropositionTypesForRuleType(eligPrereqRuleType.getId());
163        expected = new LinkedHashSet<String>();
164        expected.add(KsKrmsConstants.PROPOSITION_TYPE_FREEFORM_TEXT);
165        expected.add(KsKrmsConstants.PROPOSITION_TYPE_SUCCESS_COMPL_COURSE);
166        expected.add(KsKrmsConstants.PROPOSITION_TYPE_CUMULATIVE_GPA_MIN);
167        expected.add(KsKrmsConstants.PROPOSITION_TYPE_ADMITTED_TO_PROGRAM);
168        expected.add(KsKrmsConstants.PROPOSITION_TYPE_SUCCESS_CREDIT_COURSESET_COMPLETED_NOF);
169        expected.add(KsKrmsConstants.PROPOSITION_TYPE_SUCCESS_CREDITS_COURSESET_COMPLETED_NOF_ORG);
170        expected.add(KsKrmsConstants.PROPOSITION_TYPE_SUCCESS_COURSE_COURSESET_COMPLETED_ALL);
171        expected.add(KsKrmsConstants.PROPOSITION_TYPE_SUCCESS_COURSE_COURSESET_COMPLETED_NOF);
172        expected.add(KsKrmsConstants.PROPOSITION_TYPE_COURSE_COURSESET_GPA_MIN);
173        expected.add(KsKrmsConstants.PROPOSITION_TYPE_COURSE_COURSESET_GRADE_MIN);
174        expected.add(KsKrmsConstants.PROPOSITION_TYPE_COURSE_COURSESET_NOF_GRADE_MIN);
175        expected.add(KsKrmsConstants.PROPOSITION_TYPE_COURSE_COURSESET_GRADE_MAX);
176        expected.add(KsKrmsConstants.PROPOSITION_TYPE_ADMITTED_TO_PROGRAM_CAMPUS);
177        expected.add(KsKrmsConstants.PROPOSITION_TYPE_NOTADMITTED_TO_PROGRAM);
178        expected.add(KsKrmsConstants.PROPOSITION_TYPE_PERMISSION_INSTRUCTOR_REQUIRED);
179        expected.add(KsKrmsConstants.PROPOSITION_TYPE_PERMISSION_ADMIN_ORG);
180        expected.add(KsKrmsConstants.PROPOSITION_TYPE_COURSE_TEST_SCORE_MIN);
181        expected.add(KsKrmsConstants.PROPOSITION_TYPE_TEST_SCORE_BETWEEN_VALUES);
182        expected.add(KsKrmsConstants.PROPOSITION_TYPE_TEST_SCORE);
183        this.checkTypeNamesOrdered(expected, types);
184
185        title = "Please choose which type of rule you want to work on:";
186        defaultIndex = 7;
187        KrmsTypeDefinition nOfCoursesPropositionType = this.simulateUserChoosingType(title, types, languageCode, defaultIndex);
188        NaturalLanguageTemplate nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(nOfCoursesPropositionType.getId(), languageCode);
189        assertNotNull(nlTemplate);
190        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());
191
192//                <entry key="kuali.krms.proposition.type.success.course.courseset.completed.nof">
193//                    <bean parent="TemplateInfo-parent"
194//                          p:termSpecName="NumberOfCompletedCourses" p:operator="&lt;=" p:value="n">
195//                        <property name="componentId" value="KRMS-MultiCourse-Section"/>
196//                        <property name="constantComponentId" value="KRMS-NumberOfCourses-ConstantValue"/>
197//                        <property name="componentBuilderClass" value="org.kuali.student.enrollment.class1.krms.builder.MultiCourseComponentBuilder"/>
198//                    </bean>
199//                </entry>
200
201
202        // Get all the parameter types for the proposition type
203        types = this.krmsTypeRepositoryService.findPropositionParameterTypesForPropositionType(nOfCoursesPropositionType.getId());
204        expected = new LinkedHashSet<String>();
205        expected.add(KsKrmsConstants.PROPOSITION_PARAMETER_TYPE_TERM_NUMBER_OF_COMPLETED_COURSES);
206        expected.add(KsKrmsConstants.PROPOSITION_PARAMETER_TYPE_CONSTANT_VALUE_N);
207        expected.add(KsKrmsConstants.PROPOSITION_PARAMETER_TYPE_OPERATOR_LESS_THAN_OR_EQUAL_TO);
208        this.checkTypeNamesOrdered(expected, types);
209
210        // make sure we have descriptions for all of the parameters
211        this.displayScreenDescriptions(types, languageCode);
212        // now check the krad implementations
213        // check the term
214        KrmsTypeDefinition nOfCoursesTermType = types.get(0);
215        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(nOfCoursesTermType.getId(), languageCode);
216        assertNotNull(nlTemplate);
217        String termName = nlTemplate.getTemplate();
218        assertEquals("NumberOfCompletedCourses", termName);
219        assertNull(this.getComponentId(nlTemplate));
220
221        // constant value N
222        KrmsTypeDefinition constantValueN = types.get(1);
223        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(constantValueN.getId(), languageCode);
224        assertNotNull(nlTemplate);
225        String constantValue = nlTemplate.getTemplate();
226        assertEquals("1", constantValue);
227        String constantValueComponentId = this.getComponentId(nlTemplate);
228        assertEquals("KRMS-NumberOfCourses-ConstantValue", constantValueComponentId);
229
230        // operator
231        KrmsTypeDefinition lessThanEqualOperatorType = types.get(2);
232        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(lessThanEqualOperatorType.getId(), languageCode);
233        assertNotNull(nlTemplate);
234        String operator = nlTemplate.getTemplate();
235        assertEquals("<=", operator);
236        assertNull(this.getComponentId(nlTemplate));
237
238        // Get all the term parameter types for the TERM proposition parameter type
239        types = this.krmsTypeRepositoryService.findTermParameterTypesForTermPropositionParameterType(nOfCoursesTermType.getId());
240        expected = new LinkedHashSet<String>();
241        expected.add(KsKrmsConstants.TERM_PARAMETER_TYPE_COURSE_CLUSET_ID);
242        this.checkTypeNamesOrdered(expected, types);
243        this.displayScreenDescriptions(types, languageCode);
244        KrmsTypeDefinition cluSetIdType = types.get(0);
245        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(cluSetIdType.getId(), languageCode);
246        assertNotNull(nlTemplate);
247        assertEquals("CourseSetId", nlTemplate.getTemplate());
248        String cluSetIdComponentId = this.getComponentId(nlTemplate);
249        assertEquals("KRMS-MultiCourse-Section", cluSetIdComponentId);
250        String componentBuilderClass = this.getComponentBuilderClass(nlTemplate);
251        assertEquals("org.kuali.student.enrollment.class1.krms.builder.MultiCourseComponentBuilder", componentBuilderClass);
252
253//      TermSpec 
254        TermSpecificationDefinition termSpec =
255                this.termRepositoryService.getTermSpecificationByNameAndNamespace(termName,
256                KsKrmsConstants.NAMESPACE_CODE);
257        assertNotNull(termSpec);
258
259        TermResolverDefinition termResolver =
260                this.termRepositoryService.getTermResolverByNameAndNamespace(termName,
261                KsKrmsConstants.NAMESPACE_CODE);
262        assertNotNull(termResolver);
263
264        //
265        // ok now actually start creating rule
266        //
267
268
269        // this is the course to which we are going to attach the agenda
270        // NOTE: this will be a COURSE not a CLU but I don't want to mock the course impl
271        CluInfo anchorClu = this.getClu("COURSE1");
272
273        // find/create the context corresponding to this context type.
274        // TODO: Confirm convention that we are creating a single context for all rules of that particular context type, right?
275        ContextDefinition.Builder bldr = ContextDefinition.Builder.create(KsKrmsConstants.NAMESPACE_CODE, selectedContextType.getName());
276        // TODO: find out what this typeId is really supposed to be.
277        // I thought it would be the selected context type but in the existing configured data it has a value T1004?!? 
278        bldr.setTypeId(selectedContextType.getId());
279        bldr.setDescription(description); // set the description to be the template description of the type
280        bldr.setActive(true);
281        ContextDefinition context = this.ruleManagementService.findCreateContext(bldr.build());
282        assertNotNull(context);
283        assertEquals(context.getName(), selectedContextType.getName());
284        assertEquals(context.getNamespace(), selectedContextType.getNamespace());
285        // TODO: worry that this context could have been created with a different type and/or description
286        assertEquals(context.getTypeId(), selectedContextType.getId());
287        assertEquals(context.getDescription(), description);
288
289        // create the agenda
290        String id = null; // set by service when create is called
291        String name = courseEligAgendaType.getName() + " for " + anchorClu.getOfficialIdentifier().getCode() + " " + anchorClu.getId();
292        String typeId = courseEligAgendaType.getId();
293        String contextId = context.getId();
294        AgendaDefinition.Builder agendaBldr = AgendaDefinition.Builder.create(id, name, typeId, contextId);
295        agendaBldr.setActive(false);
296        AgendaDefinition agenda = this.ruleManagementService.createAgenda(agendaBldr.build());
297
298        // create the rule
299        String ruleId = null; // sevice sets id
300        // TODO: find out if this really needs to be unique.. if not remove the actual internal Id of the course from the end 
301        name = eligPrereqRuleType.getName() + " for " + anchorClu.getOfficialIdentifier().getCode() + " " + anchorClu.getId();
302        String namespace = KsKrmsConstants.NAMESPACE_CODE;
303        typeId = eligPrereqRuleType.getId();
304        String propId = null;
305        RuleDefinition.Builder ruleBldr = RuleDefinition.Builder.create(ruleId, name, namespace, typeId, propId);
306        ruleBldr.setActive(true);
307        RuleDefinition rule = this.ruleManagementService.createRule(ruleBldr.build());
308
309        // bind the rule to the agenda via the item
310        id = null;
311        String agendaId = agenda.getId();
312        AgendaItemDefinition.Builder itemBldr = AgendaItemDefinition.Builder.create(id, agendaId);
313        itemBldr.setRuleId(ruleId);
314        AgendaItemDefinition item = this.ruleManagementService.createAgendaItem(itemBldr.build());
315        // now go back and mark the agenda with the item and make it active
316        agendaBldr = AgendaDefinition.Builder.create(agenda);
317        agendaBldr.setActive(true);
318        agendaBldr.setFirstItemId(item.getId());
319        this.ruleManagementService.updateAgenda(agendaBldr.build());
320        agenda = this.ruleManagementService.getAgenda(agenda.getId());
321
322        // create the cluset
323        CluInfo courseClu2 = this.getClu("COURSE2");
324        CluInfo courseClu3 = this.getClu("COURSE3");
325        CluInfo courseClu4 = this.getClu("COURSE4");
326        List<String> versionIndIds = this.getVersionIndIds(anchorClu, courseClu2, courseClu3);
327        CluSetInfo cluSet = createCourseSet("Courses 1, 2, & 3", versionIndIds);
328
329        propId = null; // should be null until assigned by service
330        String propTypeCode = PropositionType.SIMPLE.getCode();
331        ruleId = rule.getId();
332        typeId = nOfCoursesPropositionType.getId();
333        List<PropositionParameter.Builder> parameters = new ArrayList<PropositionParameter.Builder>();
334
335        // do the term parameter first
336        //        nOfCoursesTermType.getId();
337        KrmsTypeDefinition type = nOfCoursesTermType;
338        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(type.getId(), languageCode);
339        id = null; // should be set by service
340        propId = null; // should also be set by the service when the create on the proposition happens
341        String value = null;
342        String parameterType = serviceName2PropositionParameterType(type.getServiceName()).getCode();
343        Integer sequenceNumber = 1;
344        PropositionParameter.Builder propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
345
346        // now the parameter to the parameter! (actually the term parameter to the proposition parameter that is a term!
347        id = null; // set by service
348        TermSpecificationDefinition.Builder termSpecBldr = TermSpecificationDefinition.Builder.create(termSpec);
349        List<TermParameterDefinition.Builder> termParameters = new ArrayList<TermParameterDefinition.Builder>();
350        description = termSpec.getName() + " for " + cluSet.getId();
351        TermDefinition.Builder termBldr = TermDefinition.Builder.create(id, termSpecBldr, termParameters);
352        termBldr.setDescription(description);
353
354        id = null; //set by service
355        typeId = cluSetIdType.getId();
356        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(typeId, languageCode);
357        name = nlTemplate.getTemplate(); // this should be CourseSetId 
358        value = cluSet.getId(); // this was created when the cluSet was built
359        TermParameterDefinition.Builder termParamBldr = TermParameterDefinition.Builder.create(id, typeId, name, value);
360        termParameters.add(termParamBldr);
361        propParamBldr.setTermValue(termBldr.build());
362        parameters.add(propParamBldr);
363
364        // do the 2nd parameter
365        type = constantValueN;
366        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(type.getId(), languageCode);
367        id = null; // should be set by service
368        propId = null; // should also be set by the service when the create on the proposition happens
369        value = nlTemplate.getTemplate(); // this should be default of 1 but use can change to be 2 or 3 or...
370        parameterType = serviceName2PropositionParameterType(type.getServiceName()).getCode();
371        sequenceNumber = 2;
372        propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
373        parameters.add(propParamBldr);
374
375        // do the 3rd parameter
376        type = lessThanEqualOperatorType;
377        nlTemplate = this.getRuleEditUsageNaturalLanguageTemplate(type.getId(), languageCode);
378        id = null; // should be set by service
379        propId = null; // should also be set by the service when the create on the proposition happens
380        value = nlTemplate.getTemplate(); // this should be default of <=..
381        parameterType = serviceName2PropositionParameterType(type.getServiceName()).getCode();
382        sequenceNumber = 3;
383        propParamBldr = PropositionParameter.Builder.create(id, propId, value, parameterType, sequenceNumber);
384        parameters.add(propParamBldr);
385
386        PropositionDefinition.Builder propBldr = PropositionDefinition.Builder.create(propId, propTypeCode, ruleId, typeId, parameters);
387
388        String enDescription = this.ruleManagementService.translateNaturalLanguageForProposition(getTypeDescriptionUsage ().getId(), propBldr.build(), languageCode);
389        System.out.println ("description=" + enDescription);
390        
391//        String enPreview = this.ruleManagementService.translateNaturalLanguageForProposition(getPreviewUsage ().getId(), propBldr.build(), languageCode);
392//        System.out.println (enPreview);
393     
394        
395        PropositionDefinition propositon = this.ruleManagementService.createProposition(propBldr.build());
396
397
398    }
399
400    ////
401    ////
402    ////
403    ////
404    ////
405    private PropositionParameterType serviceName2PropositionParameterType(String serviceTypeName) {
406        if (serviceTypeName.equals(KrmsTypeRepositoryService.TERM_PROPOSITION_PARAMETER_SERVICE_NAME)) {
407            return PropositionParameterType.TERM;
408        }
409        if (serviceTypeName.equals(KrmsTypeRepositoryService.CONSTANT_VALUE_PROPOSITION_PARAMETER_SERVICE_NAME)) {
410            return PropositionParameterType.CONSTANT;
411        }
412        if (serviceTypeName.equals(KrmsTypeRepositoryService.OPERATOR_PROPOSITION_PARAMETER_SERVICE_NAME)) {
413            return PropositionParameterType.OPERATOR;
414        }
415        if (serviceTypeName.equals(KrmsTypeRepositoryService.FUNCTION_PROPOSITION_PARAMETER_SERVICE_NAME)) {
416            return PropositionParameterType.FUNCTION;
417        }
418        throw new IllegalArgumentException(serviceTypeName);
419    }
420
421    public CluSetInfo createCourseSet(String name, List<String> versionIndIds) {
422        CluSetInfo cluSetInfo = new CluSetInfo();
423        cluSetInfo.setTypeKey(CluServiceConstants.CLUSET_TYPE_CREDIT_COURSE);
424        cluSetInfo.setStateKey("Active");
425        cluSetInfo.setName(name);
426        cluSetInfo.setEffectiveDate(new Date());
427        cluSetInfo.setIsReferenceable(Boolean.TRUE);
428        cluSetInfo.setIsReusable(Boolean.FALSE);
429        cluSetInfo.setCluIds(versionIndIds);
430        try {
431            cluSetInfo = this.cluService.createCluSet(cluSetInfo.getTypeKey(), cluSetInfo, contextInfo);
432        } catch (Exception ex) {
433            throw new IllegalArgumentException(ex);
434        }
435        return cluSetInfo;
436    }
437
438    private List<String> getVersionIndIds(CluInfo... clus) {
439        List<String> list = new ArrayList<String>();
440        for (CluInfo clu : clus) {
441            list.add(clu.getVersion().getVersionIndId());
442        }
443        return list;
444    }
445
446    private CluInfo getClu(String id) {
447        try {
448            return this.cluService.getClu(id, contextInfo);
449        } catch (Exception ex) {
450            throw new RuntimeException(ex);
451        }
452    }
453    // cache
454    private transient Map<String, NaturalLanguageUsage> name2NaturalLanguageUsageCache = null;
455
456    private NaturalLanguageUsage getNaturalLanguageUsage(String name, String namespace) {
457        if (name2NaturalLanguageUsageCache == null) {
458            name2NaturalLanguageUsageCache = new LinkedHashMap<String, NaturalLanguageUsage>();
459        }
460        String key = namespace + ":" + name;
461        NaturalLanguageUsage usage = name2NaturalLanguageUsageCache.get(key);
462        if (usage != null) {
463            return usage;
464        }
465        // get the usage
466        usage = this.ruleManagementService.getNaturalLanguageUsageByNameAndNamespace(name, namespace);
467        assertNotNull(usage);
468        assertEquals(name, usage.getName());
469        assertEquals(namespace, usage.getNamespace());
470        name2NaturalLanguageUsageCache.put(key, usage);
471        return usage;
472    }
473
474    private NaturalLanguageUsage getTypeDescriptionUsage() {
475        return this.getNaturalLanguageUsage(KsKrmsConstants.KRMS_NL_TYPE_DESCRIPTION, KsKrmsConstants.NAMESPACE_CODE);
476    }
477
478    private NaturalLanguageUsage getRuleEditUsage() {
479        return this.getNaturalLanguageUsage(KsKrmsConstants.KRMS_NL_RULE_EDIT, KsKrmsConstants.NAMESPACE_CODE);
480    }
481
482    private NaturalLanguageUsage getPreviewUsage() {
483        return this.getNaturalLanguageUsage(KsKrmsConstants.KRMS_NL_PREVIEW, KsKrmsConstants.NAMESPACE_CODE);
484    }
485
486    private String simulateUserChoosingContextTypeId() {
487        KrmsTypeDefinition type = this.krmsTypeRepositoryService.getTypeByName(KsKrmsConstants.NAMESPACE_CODE, KsKrmsConstants.CONTEXT_TYPE_COURSE);
488        assertNotNull(type);
489        assertEquals(KsKrmsConstants.CONTEXT_TYPE_COURSE, type.getName());
490        assertEquals(KsKrmsConstants.NAMESPACE_CODE, type.getNamespace());
491        return type.getId();
492    }
493
494    private KrmsTypeDefinition simulateUserChoosingType(String title, List<KrmsTypeDefinition> types, String languageCode, int defaultIndex) {
495        System.out.println(title);
496        this.displayScreenDescriptions(types, languageCode);
497        System.out.print("==> Choose: ");
498        KrmsTypeDefinition selected = types.get(defaultIndex);
499        System.out.println(selected.getName());
500        return selected;
501    }
502
503    private void displayScreenDescriptions(List<KrmsTypeDefinition> types, String languageCode) {
504        for (KrmsTypeDefinition type : types) {
505            System.out.println(this.getScreenDescription(type.getId(), languageCode));
506        }
507    }
508
509    private String getScreenDescription(String typeId, String languageCode) {
510        // check there is a corresponding template so we can display on the screen what kind of rule this is
511        NaturalLanguageTemplate template =
512                this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
513                typeId,
514                this.getTypeDescriptionUsage().getId());
515        if (template == null) {
516            System.out.println("could not find template for " + typeId + " with language " + languageCode + " and for type description usage");
517        }
518        assertNotNull(template);
519        assertEquals(languageCode, template.getLanguageCode());
520        assertEquals(typeId, template.getTypeId());
521        assertEquals(getTypeDescriptionUsage().getId(), template.getNaturalLanguageUsageId());
522        return template.getTemplate();
523    }
524
525    private String getComponentId(NaturalLanguageTemplate template) {
526        return template.getAttributes().get(KsKrmsConstants.ATTRIBUTE_COMPONENT_ID);
527    }
528
529    private String getComponentBuilderClass(NaturalLanguageTemplate template) {
530        return template.getAttributes().get(KsKrmsConstants.ATTRIBUTE_COMPONENT_BUILDER_CLASS);
531    }
532
533    private NaturalLanguageTemplate getRuleEditUsageNaturalLanguageTemplate(String typeId, String languageCode) {
534        // check there is a corresponding template so we can display on the screen what kind of rule this is
535        NaturalLanguageTemplate template =
536                this.ruleManagementService.findNaturalLanguageTemplateByLanguageCodeTypeIdAndNluId(languageCode,
537                typeId,
538                this.getRuleEditUsage().getId());
539        if (template == null) {
540            System.out.println("could not find template for " + typeId + " with language " + languageCode + " and for rule edit usage");
541        }
542        assertNotNull(template);
543        assertEquals(languageCode, template.getLanguageCode());
544        assertEquals(typeId, template.getTypeId());
545        assertEquals(getRuleEditUsage().getId(), template.getNaturalLanguageUsageId());
546        return template;
547    }
548
549    private void checkTypeNamesAnyOrder(Set<String> expected, List<KrmsTypeDefinition> types) {
550        List<String> unexpected = new ArrayList<String>();
551        for (KrmsTypeDefinition type : types) {
552            if (!expected.remove(type.getName())) {
553                unexpected.add(type.getName());
554            }
555        }
556        if (!expected.isEmpty() || !unexpected.isEmpty()) {
557            fail(expected.size() + " types expected that were not found " + expected
558                    + " and "
559                    + unexpected.size() + " types were found but not expected " + unexpected);
560        }
561    }
562
563    private void checkTypeNamesOrdered(Set<String> expected, List<KrmsTypeDefinition> types) {
564        List<String> expectedOrdered = new ArrayList(expected);
565        this.checkTypeNamesAnyOrder(expected, types);
566        for (int i = 0; i < types.size(); i++) {
567            if (!expectedOrdered.get(i).equals(types.get(i).getName())) {
568                fail("Expected " + i + "th position to have " + expectedOrdered.get(i) + " but found " + types.get(i).getName());
569            }
570        }
571    }
572
573    private CluInfo getCurrentCluInfoByVersionIndId(String id, ContextInfo contextInfo) {
574        VersionDisplayInfo versionDisplayInfo = null;
575        try {
576            versionDisplayInfo = this.cluService.getCurrentVersion(CluServiceConstants.CLU_NAMESPACE_URI, id, contextInfo);
577        } catch (Exception ex) {
578            throw new IllegalArgumentException("Unexpected", ex);
579        }
580        try {
581            return this.cluService.getClu(versionDisplayInfo.getId(), contextInfo);
582        } catch (Exception ex) {
583            throw new IllegalArgumentException("Unexpected", ex);
584        }
585    }
586}