001    /*
002     * To change this template, choose Tools | Templates
003     * and open the template in the editor.
004     */
005    package org.kuali.rice.krms.impl.repository.mock;
006    
007    import java.util.ArrayList;
008    import java.util.Date;
009    import java.util.LinkedHashMap;
010    import java.util.LinkedHashSet;
011    import java.util.List;
012    import java.util.Map;
013    import java.util.Set;
014    import org.junit.After;
015    import org.junit.AfterClass;
016    import org.junit.Before;
017    import org.junit.BeforeClass;
018    import org.junit.Test;
019    import static org.junit.Assert.*;
020    import org.kuali.rice.krms.api.repository.RuleManagementService;
021    import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
022    import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
023    import org.kuali.rice.krms.api.repository.context.ContextDefinition;
024    import org.kuali.rice.krms.api.repository.language.NaturalLanguageTemplate;
025    import org.kuali.rice.krms.api.repository.language.NaturalLanguageUsage;
026    import org.kuali.rice.krms.api.repository.proposition.PropositionDefinition;
027    import org.kuali.rice.krms.api.repository.proposition.PropositionParameter;
028    import org.kuali.rice.krms.api.repository.proposition.PropositionParameterType;
029    import org.kuali.rice.krms.api.repository.proposition.PropositionType;
030    import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
031    import org.kuali.rice.krms.api.repository.term.TermDefinition;
032    import org.kuali.rice.krms.api.repository.term.TermParameterDefinition;
033    import org.kuali.rice.krms.api.repository.term.TermRepositoryService;
034    import org.kuali.rice.krms.api.repository.term.TermResolverDefinition;
035    import org.kuali.rice.krms.api.repository.term.TermSpecificationDefinition;
036    import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
037    import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
038    import org.kuali.rice.krms.impl.repository.language.SimpleNaturalLanguageTemplater;
039    import org.kuali.student.krms.naturallanguage.util.KsKrmsConstants;
040    import org.kuali.student.r2.common.dto.ContextInfo;
041    import org.kuali.student.r2.core.versionmanagement.dto.VersionDisplayInfo;
042    import org.kuali.student.r2.lum.clu.dto.CluInfo;
043    import org.kuali.student.r2.lum.clu.dto.CluSetInfo;
044    import org.kuali.student.r2.lum.clu.service.CluService;
045    import org.kuali.student.r2.lum.lu.service.impl.CluDataLoader;
046    import org.kuali.student.r2.lum.lu.service.impl.CluServiceMockImpl;
047    import org.kuali.student.r2.lum.util.constants.CluServiceConstants;
048    
049    /**
050     *
051     * @author nwright
052     */
053    public 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    }