001/*
002 * Copyright 2013 The Kuali Foundation
003 * 
004 * Licensed under the Educational Community License, Version 1.0 (the
005 * "License"); you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 * 
008 * http://www.opensource.org/licenses/ecl1.php
009 * 
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013 * License for the specific language governing permissions and limitations under
014 * the License.
015 */
016package org.kuali.student.enrollment.class2.courseoffering.service.impl;
017
018import java.util.ArrayList;
019import java.util.Date;
020import java.util.LinkedList;
021import java.util.List;
022
023import javax.annotation.Resource;
024
025import junit.framework.Assert;
026
027import org.junit.After;
028import org.junit.Before;
029import org.junit.Test;
030import org.junit.runner.RunWith;
031import org.kuali.student.common.test.spring.log4j.KSLog4JConfigurer;
032import org.kuali.student.enrollment.class2.acal.util.MockAcalTestDataLoader;
033import org.kuali.student.enrollment.class2.courseoffering.service.facade.ActivityOfferingResult;
034import org.kuali.student.enrollment.class2.courseoffering.service.facade.CourseOfferingServiceFacade;
035import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingClusterInfo;
036import org.kuali.student.enrollment.courseoffering.dto.ActivityOfferingInfo;
037import org.kuali.student.enrollment.courseoffering.dto.CourseOfferingInfo;
038import org.kuali.student.enrollment.courseoffering.dto.FormatOfferingInfo;
039import org.kuali.student.enrollment.courseoffering.dto.OfferingInstructorInfo;
040import org.kuali.student.enrollment.courseoffering.dto.RegistrationGroupInfo;
041import org.kuali.student.enrollment.courseoffering.service.CourseOfferingService;
042import org.kuali.student.r2.common.dto.BulkStatusInfo;
043import org.kuali.student.r2.common.dto.ContextInfo;
044import org.kuali.student.r2.common.dto.TimeOfDayInfo;
045import org.kuali.student.r2.common.exceptions.AlreadyExistsException;
046import org.kuali.student.r2.common.exceptions.CircularRelationshipException;
047import org.kuali.student.r2.common.exceptions.DataValidationErrorException;
048import org.kuali.student.r2.common.exceptions.DependentObjectsExistException;
049import org.kuali.student.r2.common.exceptions.DoesNotExistException;
050import org.kuali.student.r2.common.exceptions.InvalidParameterException;
051import org.kuali.student.r2.common.exceptions.MissingParameterException;
052import org.kuali.student.r2.common.exceptions.OperationFailedException;
053import org.kuali.student.r2.common.exceptions.PermissionDeniedException;
054import org.kuali.student.r2.common.exceptions.ReadOnlyException;
055import org.kuali.student.r2.common.exceptions.UnsupportedActionException;
056import org.kuali.student.r2.common.exceptions.VersionMismatchException;
057import org.kuali.student.r2.common.infc.TimeOfDay;
058import org.kuali.student.r2.common.util.TimeOfDayAmPmEnum;
059import org.kuali.student.r2.common.util.TimeOfDayFormattingEnum;
060import org.kuali.student.r2.common.util.TimeOfDayHelper;
061import org.kuali.student.r2.common.util.constants.CourseOfferingServiceConstants;
062import org.kuali.student.r2.common.util.constants.CourseOfferingSetServiceConstants;
063import org.kuali.student.r2.common.util.constants.LprServiceConstants;
064import org.kuali.student.r2.common.util.constants.LuiServiceConstants;
065import org.kuali.student.r2.core.acal.dto.TermInfo;
066import org.kuali.student.r2.core.acal.service.AcademicCalendarService;
067import org.kuali.student.r2.core.atp.dto.AtpInfo;
068import org.kuali.student.r2.core.atp.service.AtpService;
069import org.kuali.student.r2.core.constants.AtpServiceConstants;
070import org.kuali.student.r2.lum.course.service.CourseService;
071import org.kuali.student.r2.lum.lrc.service.LRCService;
072import org.slf4j.Logger;
073import org.springframework.test.context.ContextConfiguration;
074import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
075
076import static org.junit.Assert.assertEquals;
077import static org.junit.Assert.assertFalse;
078import static org.junit.Assert.assertNotNull;
079import static org.junit.Assert.assertTrue;
080import static org.junit.Assert.fail;
081/**
082 * A test case for the course offering service facade impl.
083 * 
084 * @author Kuali Student Team 
085 *
086 */
087@RunWith(SpringJUnit4ClassRunner.class)
088@ContextConfiguration(locations = {"classpath:co-autogen-rg-test-class2-mock-context.xml"})
089public class TestCourseOfferingServiceFacadeImpl {
090    private static final Logger log = KSLog4JConfigurer
091            .getLogger(TestCourseOfferingServiceFacadeImpl.class);
092
093    @Resource (name="CourseOfferingService")
094    protected CourseOfferingService coService;
095
096    @Resource
097    protected CourseService courseService;
098
099    @Resource
100    protected CourseOfferingServiceTestDataLoader dataLoader;
101
102    @Resource(name = "LrcService")
103    protected LRCService lrcService;
104    
105    @Resource
106    protected AcademicCalendarService acalService;
107
108    @Resource
109    protected AtpService atpService;
110    
111    @Resource
112    private CourseOfferingServiceFacade coServiceFacade;
113
114    private ContextInfo contextInfo;
115    
116    /**
117     * 
118     */
119    public TestCourseOfferingServiceFacadeImpl() {
120    }
121    
122    @Before
123    public void beforeTest() throws Exception {
124        dataLoader.beforeTest();
125        
126        contextInfo = new ContextInfo();
127    
128        contextInfo.setCurrentDate(new Date());
129        
130        contextInfo.setPrincipalId("test");
131        contextInfo.setAuthenticatedPrincipalId("test");
132    }
133    
134    @After
135    public void afterTest() throws Exception {
136        dataLoader.afterTest();
137    }
138
139    /**
140     * User Story 3: I need the system to automatically create reg groups when I create an
141     * AO (via add or copy) to eliminate the need to manually create them
142     */
143    @Test
144    public void testAddActivityOffering()
145            throws PermissionDeniedException, MissingParameterException, InvalidParameterException,
146            OperationFailedException, DoesNotExistException, ReadOnlyException, DataValidationErrorException, VersionMismatchException {
147        String foId = "CO-2:LEC-ONLY";
148        FormatOfferingInfo foInfo = coService.getFormatOffering(foId, contextInfo);
149        List<ActivityOfferingClusterInfo> clusters =
150                coService.getActivityOfferingClustersByFormatOffering(foId, contextInfo);
151        String aocId = clusters.get(0).getId();
152        List<ActivityOfferingInfo> aos = coService.getActivityOfferingsByCluster(aocId, contextInfo);
153        assertEquals(2, aos.size());
154        ActivityOfferingInfo aoInfo = new ActivityOfferingInfo(aos.get(0));
155        aoInfo.setId("CO-2:LEC-ONLY:LEC-C");
156        List<RegistrationGroupInfo> rgInfos = coService.getRegistrationGroupsByFormatOffering(foId, contextInfo);
157        assertEquals(2, rgInfos.size());
158        // App layer call
159        ActivityOfferingResult aoResult =
160                coServiceFacade.createActivityOffering(aoInfo, aocId, contextInfo);
161        List<RegistrationGroupInfo> rgInfosByAo = coService.getRegistrationGroupsByActivityOffering(aoResult.getCreatedActivityOffering().getId(), contextInfo);
162        assertEquals(1, rgInfosByAo.size());
163        rgInfos = coService.getRegistrationGroupsByFormatOffering(foId, contextInfo);
164        assertEquals(3, rgInfos.size()); // Now three RGs
165        aos = coService.getActivityOfferingsByCluster(aocId, contextInfo);
166        assertEquals(3, aos.size());
167    }
168
169    /**
170     * User Story 5
171     */
172    @Test
173    public void testDeleteActivityOffering()
174            throws PermissionDeniedException, MissingParameterException,
175            InvalidParameterException, OperationFailedException, DoesNotExistException, DataValidationErrorException, VersionMismatchException, ReadOnlyException {
176        // This FO has only 2 AOs in it
177        String foId = "CO-2:LEC-ONLY";
178        FormatOfferingInfo foInfo = coService.getFormatOffering(foId, contextInfo);
179        List<ActivityOfferingClusterInfo> clusters = coService.getActivityOfferingClustersByFormatOffering(foId, contextInfo);
180        assertEquals(1, clusters.size());
181        String aocId = clusters.get(0).getId();
182        List<ActivityOfferingInfo> aoInfos = coService.getActivityOfferingsByCluster(aocId, contextInfo);
183        assertEquals(2, aoInfos.size());
184        // Get list of AO ids
185        List<String> aoIdsInCluster = new ArrayList<String>();
186        aoIdsInCluster.add(aoInfos.get(0).getId());
187        aoIdsInCluster.add(aoInfos.get(1).getId());
188        List<RegistrationGroupInfo> rgInfos = coService.getRegistrationGroupsByActivityOfferingCluster(aocId, contextInfo);
189        assertEquals(2, rgInfos.size());
190        for (RegistrationGroupInfo rg: rgInfos) {
191            for (String aoId : rg.getActivityOfferingIds()) {
192                assertTrue(aoIdsInCluster.contains(aoId));
193            }
194        }
195        // Now delete the AO
196        String aoIdFirst = aoInfos.get(0).getId();
197        String aoIdSecond = aoInfos.get(1).getId();
198        // App layer call
199        coServiceFacade.deleteActivityOfferingCascaded(aoIdFirst, aocId, foId, contextInfo);
200        List<ActivityOfferingClusterInfo> retrieved =
201                coService.getActivityOfferingClustersByFormatOffering(foId, contextInfo);
202        // Fetch the AOs again--should only be 1
203        aoInfos = coService.getActivityOfferingsByCluster(aocId, contextInfo);
204        assertEquals(1, aoInfos.size()); // Should only have 1 AO
205        // And one RG
206        rgInfos = coService.getRegistrationGroupsByActivityOfferingCluster(aocId, contextInfo);
207        assertEquals(1, rgInfos.size());
208        assertEquals(1, rgInfos.get(0).getActivityOfferingIds().size());
209        assertEquals(aoIdSecond, rgInfos.get(0).getActivityOfferingIds().get(0)); // Id is one that is deleted
210    }
211
212    /**
213     * This is User Story 7: As a user, I need the system to automatically delete all AOs when I delete an AOC
214     * so I don’t have to delete all the AOs first
215     */
216    @Test
217    public void testDeleteActivityOfferingCluster()
218            throws PermissionDeniedException, MissingParameterException,
219            InvalidParameterException, OperationFailedException, DoesNotExistException, DependentObjectsExistException {
220        String foId = "CO-2:LEC-ONLY";
221        FormatOfferingInfo foInfo = coService.getFormatOffering(foId, contextInfo);
222        List<ActivityOfferingClusterInfo> clusters = coService.getActivityOfferingClustersByFormatOffering(foId, contextInfo);
223        assertEquals(1, clusters.size());
224        String aocId = clusters.get(0).getId();
225        List<ActivityOfferingInfo> activities = coService.getActivityOfferingsByCluster(aocId, contextInfo);
226        assertEquals(2, activities.size());
227        List<ActivityOfferingInfo> activitiesByFo = coService.getActivityOfferingsByFormatOffering(foId, contextInfo);
228        assertEquals(2, activitiesByFo.size());
229        // Check the RGs by AOC
230        List<RegistrationGroupInfo> rgsByAoc = coService.getRegistrationGroupsByActivityOfferingCluster(aocId, contextInfo);
231        assertEquals(2, rgsByAoc.size());
232        List<RegistrationGroupInfo> rgsByFo = coService.getRegistrationGroupsByFormatOffering(foId, contextInfo);
233        assertEquals(2, rgsByFo.size());
234        // App layer call
235        // Now zap the AOC
236        coServiceFacade.deleteActivityOfferingCluster(aocId, contextInfo);
237        try {
238            coService.getActivityOfferingCluster(aocId, contextInfo);
239            assert(false); // Shouldn't get here
240        } catch (DoesNotExistException e) {
241            // Should go here
242        }
243        List<ActivityOfferingInfo> activitiesByFo2 = coService.getActivityOfferingsByFormatOffering(foId, contextInfo);
244        assertEquals(0, activitiesByFo2.size());
245        List<ActivityOfferingClusterInfo> clusters2 = coService.getActivityOfferingClustersByFormatOffering(foId, contextInfo);
246        assertEquals(0, clusters2.size());
247    }
248
249    /**
250     * This is User Story 6: As a user, I need the system to automatically create/delete all
251     * associated registration groups when I move an Activity from one AOC to another
252     */
253    @Test
254    public void testMoveActivityOffering() throws PermissionDeniedException, MissingParameterException, InvalidParameterException, OperationFailedException, DoesNotExistException, ReadOnlyException, DataValidationErrorException, VersionMismatchException {
255        String foId = "CO-2:LEC-ONLY";
256        FormatOfferingInfo foInfo = coService.getFormatOffering(foId, contextInfo);
257        List<ActivityOfferingClusterInfo> clusters = coService.getActivityOfferingClustersByFormatOffering(foId, contextInfo);
258        assertEquals(1, clusters.size());
259        String aocId = clusters.get(0).getId();
260        List<ActivityOfferingInfo> activities = coService.getActivityOfferingsByCluster(aocId, contextInfo);
261        assertEquals(2, activities.size());
262        List<ActivityOfferingInfo> activitiesByFo = coService.getActivityOfferingsByFormatOffering(foId, contextInfo);
263        assertEquals(2, activitiesByFo.size());
264        // Check the RGs by AOC
265        List<RegistrationGroupInfo> rgsByAoc = coService.getRegistrationGroupsByActivityOfferingCluster(aocId, contextInfo);
266        assertEquals(2, rgsByAoc.size());
267        List<RegistrationGroupInfo> rgsByFo = coService.getRegistrationGroupsByFormatOffering(foId, contextInfo);
268        assertEquals(2, rgsByFo.size());
269        // Pick an activity to move
270        String aoIdSecond = activities.get(1).getId();
271        // Store original aoId
272        String aoIdFirst = activities.get(0).getId();
273
274        // Now create a new AOC
275        ActivityOfferingClusterInfo aocSecond = new ActivityOfferingClusterInfo();
276        aocSecond.setFormatOfferingId(foId);
277        aocSecond.setPrivateName("Second");
278        aocSecond.setName("Second");
279        aocSecond.setStateKey(CourseOfferingServiceConstants.AOC_ACTIVE_STATE_KEY);
280        aocSecond.setTypeKey(CourseOfferingServiceConstants.AOC_ROOT_TYPE_KEY);
281        String aocSecondTypeKey = aocSecond.getTypeKey();
282        ActivityOfferingClusterInfo aocSecondCreated =
283                coService.createActivityOfferingCluster(foId, aocSecondTypeKey, aocSecond, contextInfo);
284        // And move the AO from original AOC to this newly created AOC
285        List<BulkStatusInfo> bulkStatuses =
286                coServiceFacade.moveActivityOffering(aoIdSecond, aocId, aocSecondCreated.getId(), contextInfo);
287        assertEquals(1, bulkStatuses.size());
288        String newRgId = bulkStatuses.get(0).getId();
289        RegistrationGroupInfo newRg = coService.getRegistrationGroup(newRgId, contextInfo);
290        assertEquals(1, newRg.getActivityOfferingIds().size());
291        assertEquals(aoIdSecond, newRg.getActivityOfferingIds().get(0));
292        // Check RGs in orig AOC
293        rgsByAoc = coService.getRegistrationGroupsByActivityOfferingCluster(aocId, contextInfo);
294        assertEquals(1, rgsByAoc.size());
295        assertEquals(1, rgsByAoc.get(0).getActivityOfferingIds().size());
296        assertEquals(aoIdFirst, rgsByAoc.get(0).getActivityOfferingIds().get(0));
297        // And RGs in the new AOC
298        rgsByAoc = coService.getRegistrationGroupsByActivityOfferingCluster(aocSecondCreated.getId(), contextInfo);
299        assertEquals(1, rgsByAoc.size());
300        assertEquals(1, rgsByAoc.get(0).getActivityOfferingIds().size());
301        assertEquals(aoIdSecond, rgsByAoc.get(0).getActivityOfferingIds().get(0));
302    }
303
304   
305    @Test
306    public void testUserStoryThree () throws AlreadyExistsException, DataValidationErrorException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, VersionMismatchException, DoesNotExistException, CircularRelationshipException, DependentObjectsExistException, UnsupportedActionException, ReadOnlyException {
307        /*
308         * I need the system to automatically create reg groups when I create an AO (via add or copy) to eliminate the need to manually create them
309         */
310        AtpInfo atp = atpService.getAtp(CourseOfferingServiceTestDataLoader.FALL_2012_TERM_ID, contextInfo);
311        
312        TermInfo term = new TermInfo();
313        
314        term.setId(atp.getId());
315        term.setCode(atp.getCode());
316        term.setDescr(atp.getDescr());
317        term.setEndDate(atp.getEndDate());
318        term.setMeta(atp.getMeta());
319        term.setName(atp.getName());
320        term.setStartDate(atp.getStartDate());
321        term.setStateKey(atp.getStateKey());
322        term.setTypeKey(atp.getTypeKey());
323        
324        TestAutogenRegGroupUserStoryThreeCourseOfferingCreationDetails details;
325        
326        String courseOfferingId = dataLoader.createCourseOffering(term, details = new TestAutogenRegGroupUserStoryThreeCourseOfferingCreationDetails(), contextInfo);
327      
328        CourseOfferingInfo co = coService.getCourseOffering(courseOfferingId, contextInfo);
329        
330        List<FormatOfferingInfo> formats = coService.getFormatOfferingsByCourseOffering(courseOfferingId, contextInfo);
331        
332        Assert.assertNotNull(formats);
333        Assert.assertEquals(1, formats.size());
334        
335        FormatOfferingInfo fo = formats.get(0);
336        
337        List<ActivityOfferingClusterInfo> aocs = coService.getActivityOfferingClustersByFormatOffering(fo.getId(), contextInfo);
338        
339        Assert.assertEquals(1, aocs.size());
340        
341        ActivityOfferingClusterInfo aoc = aocs.get(0);
342        
343        List<OfferingInstructorInfo> instructors = new LinkedList<OfferingInstructorInfo>();
344        OfferingInstructorInfo instructor;
345        instructors.add(instructor = new OfferingInstructorInfo());
346        
347        instructor.setPercentageEffort(100.00F);
348        instructor.setPersonName("Instructor");
349        instructor.setStateKey(LprServiceConstants.ACTIVE_STATE_KEY);
350        instructor.setTypeKey(LprServiceConstants.INSTRUCTOR_MAIN_TYPE_KEY);
351        
352        ActivityOfferingInfo aoInfo = CourseOfferingServiceTestDataUtils.createActivityOffering(term.getId(), co, fo.getId(), null, "test", "Lecture Add", "AC", LuiServiceConstants.LECTURE_ACTIVITY_OFFERING_TYPE_KEY, instructors);
353        
354        ActivityOfferingResult results = coServiceFacade.createActivityOffering(aoInfo, aoc.getId(), contextInfo);
355      
356        Assert.assertNotNull(results);
357        
358        Assert.assertTrue(results.getGeneratedRegistrationGroups().size() > 0);
359    }
360    @Test
361    public void testUserStoryEight () throws DoesNotExistException, InvalidParameterException, MissingParameterException, OperationFailedException, PermissionDeniedException, DataValidationErrorException, ReadOnlyException, VersionMismatchException, AlreadyExistsException, CircularRelationshipException, DependentObjectsExistException, UnsupportedActionException {
362        
363        AtpInfo atp = atpService.getAtp(CourseOfferingServiceTestDataLoader.FALL_2012_TERM_ID, contextInfo);
364        
365        TermInfo term = new TermInfo();
366        
367        term.setId(atp.getId());
368        term.setCode(atp.getCode());
369        term.setDescr(atp.getDescr());
370        term.setEndDate(atp.getEndDate());
371        term.setMeta(atp.getMeta());
372        term.setName(atp.getName());
373        term.setStartDate(atp.getStartDate());
374        term.setStateKey(atp.getStateKey());
375        term.setTypeKey(atp.getTypeKey());
376        
377        TestAutogenRegGroupUserStoryThreeCourseOfferingCreationDetails details;
378        
379        String courseOfferingId = dataLoader.createCourseOffering(term, details = new TestAutogenRegGroupUserStoryThreeCourseOfferingCreationDetails(), contextInfo);
380      
381        CourseOfferingInfo co = coService.getCourseOffering(courseOfferingId, contextInfo);
382        
383        List<FormatOfferingInfo> formats = coService.getFormatOfferingsByCourseOffering(courseOfferingId, contextInfo);
384        
385        Assert.assertNotNull(formats);
386        Assert.assertEquals(1, formats.size());
387        
388        FormatOfferingInfo fo = formats.get(0);
389        
390        List<ActivityOfferingClusterInfo> aocs = coService.getActivityOfferingClustersByFormatOffering(fo.getId(), contextInfo);
391        
392        Assert.assertEquals(1, aocs.size());
393        
394        ActivityOfferingClusterInfo aoc = aocs.get(0);
395        
396        List<OfferingInstructorInfo> instructors = new LinkedList<OfferingInstructorInfo>();
397        OfferingInstructorInfo instructor;
398        instructors.add(instructor = new OfferingInstructorInfo());
399        
400        instructor.setPercentageEffort(100.00F);
401        instructor.setPersonName("Instructor");
402        instructor.setStateKey(LprServiceConstants.ACTIVE_STATE_KEY);
403        instructor.setTypeKey(LprServiceConstants.INSTRUCTOR_MAIN_TYPE_KEY);
404        
405        ActivityOfferingInfo aoInfo = CourseOfferingServiceTestDataUtils.createActivityOffering(term.getId(), co, fo.getId(), null, "test", "Lecture Add", "AC", LuiServiceConstants.LECTURE_ACTIVITY_OFFERING_TYPE_KEY, instructors);
406        
407        ActivityOfferingResult results = coServiceFacade.createActivityOffering(aoInfo, aoc.getId(), contextInfo);
408      
409        Assert.assertNotNull(results);
410        
411        Assert.assertTrue(results.getGeneratedRegistrationGroups().size() > 0);
412        
413        
414        Integer aocSeatCount = coServiceFacade.getSeatCountByActivityOfferingCluster(aoc.getId(), contextInfo);
415        
416        Assert.assertNotNull(aocSeatCount);
417        
418        // this is not correct
419//        Assert.assertEquals(25, aocSeatCount.intValue());
420
421        // need to test a case where the cap is applied.
422        
423        // 100 seat lecture, 200 seat lecture, 50 seat lab, 75 seat lab.
424        // 100, 50
425        // 100, 75 100
426        // 200, 50
427        // 200, 75 125 = 225
428        
429        /*
430         * max (ao.maxEnrollment) for each activity type.  200 + 75 = 275
431         * 
432         * sum (rg seats) = 250 
433         * 
434         * It seems like we need some kind of ao aware test
435         * 
436         * 1
437         */
438        
439        // need to test 2 reg groups
440        
441        // need to test 4 reg groups
442        
443        // need to test 16 reg groups.
444        
445        
446        
447    }
448
449    @Test
450    public void copyCourseOfferingToTargetTerm() throws InvalidParameterException, PermissionDeniedException, DataValidationErrorException,
451            AlreadyExistsException, ReadOnlyException, OperationFailedException, MissingParameterException,
452            DoesNotExistException, UnsupportedActionException, DependentObjectsExistException, CircularRelationshipException, VersionMismatchException {
453
454        // Create new Course Offering
455        MockAcalTestDataLoader acalLoader = new MockAcalTestDataLoader(this.acalService);
456        TermInfo term = acalLoader.loadTerm("2012SP", "Spring 2012", "2012-03-01 00:00:00.0", "2012-05-31 00:00:00.0", AtpServiceConstants.ATP_SPRING_TYPE_KEY, AtpServiceConstants.ATP_OFFICIAL_STATE_KEY, "Spring Term 2012");
457        assertEquals("2012SP", term.getCode());
458        TestAutogenRegGroupUserStoryThreeCourseOfferingCreationDetails details;
459        String courseOfferingId = dataLoader.createCourseOffering(term, details = new TestAutogenRegGroupUserStoryThreeCourseOfferingCreationDetails(), contextInfo);
460        CourseOfferingInfo co = coService.getCourseOffering(courseOfferingId, contextInfo);
461        assertEquals("MATH123", co.getCourseOfferingCode());
462
463        // Create targetTerm
464        TermInfo targetTerm = acalLoader.loadTerm("2012FA", "Fall 2012", "2012-09-01 00:00:00.0", "2012-12-31 00:00:00.0", AtpServiceConstants.ATP_FALL_TYPE_KEY, AtpServiceConstants.ATP_OFFICIAL_STATE_KEY, "Fall Term 2012");
465        assertEquals("2012FA", targetTerm.getCode());
466
467        // App layer call
468        List<String> optionKeys = new ArrayList<String>();
469        optionKeys.add(CourseOfferingSetServiceConstants.CONTINUE_WITHOUT_EXAM_OFFERINGS_OPTION_KEY);
470        CourseOfferingInfo coResult = coServiceFacade.copyCourseOfferingToTargetTerm(co, targetTerm, optionKeys, contextInfo);
471        assertEquals(co.getCourseCode(), coResult.getCourseCode());
472        assertEquals(targetTerm.getId(), coResult.getTermId());
473        assertEquals(co.getCourseId(), coResult.getCourseId());
474    }
475
476    @Test
477    public void testTimeOfDayInfoHelper() throws InvalidParameterException {
478        // Standard time --------------------------------------------------------------
479        // Check 8 am
480        TimeOfDay tod = TimeOfDayHelper.createTimeOfDay(8, 0, TimeOfDayAmPmEnum.AM);
481        String todStr = TimeOfDayHelper.formatTimeOfDay(tod);
482        assertEquals("8:00 am", todStr);
483        // Check 11:59 PM
484        tod = TimeOfDayHelper.createTimeOfDay(11, 59, TimeOfDayAmPmEnum.PM);
485        todStr = TimeOfDayHelper.formatTimeOfDay(tod);
486        assertEquals("11:59 pm", todStr);
487        // Military time --------------------------------------------------------------
488        // Check 8 am
489        tod = TimeOfDayHelper.createTimeOfDayInMilitary(8, 0);
490        todStr = TimeOfDayHelper.formatTimeOfDay(tod);
491        assertEquals("8:00 am", todStr);
492        List<TimeOfDayFormattingEnum> options = new ArrayList<TimeOfDayFormattingEnum>();
493        options.add(TimeOfDayFormattingEnum.USE_MILITARY_TIME);
494        todStr = TimeOfDayHelper.formatTimeOfDay(tod, options);
495        assertEquals("8:00", todStr);
496        // Check 11:59 PM
497        tod = TimeOfDayHelper.createTimeOfDayInMilitary(23, 59);
498        todStr = TimeOfDayHelper.formatTimeOfDay(tod);
499        assertEquals("11:59 pm", todStr);
500        todStr = TimeOfDayHelper.formatTimeOfDay(tod, options);
501        assertEquals("23:59", todStr);
502        // Check for invalid times -----------------------------------------------------
503        // 1 millisecond too large
504        assertTrue(_testExceptionOnCreateTimeOfDay(tod.getMilliSeconds() + 1));
505        // Check 1 millisecond too small
506        assertTrue(_testExceptionOnCreateTimeOfDay(-1L));
507        // Check creating hours too large
508        assertTrue(_testExceptionOnCreateTimeOfDay(13, 0, TimeOfDayAmPmEnum.AM));
509        // Check creating hours too small
510        assertTrue(_testExceptionOnCreateTimeOfDay(0, 0, TimeOfDayAmPmEnum.AM));
511        // Check creating minutes too large
512        assertTrue(_testExceptionOnCreateTimeOfDay(1, 60, TimeOfDayAmPmEnum.AM));
513        // Check creating minutes too small
514        assertTrue(_testExceptionOnCreateTimeOfDay(1, -1, TimeOfDayAmPmEnum.AM));
515    }
516
517    private boolean _testExceptionOnCreateTimeOfDay(long millis) {
518        TimeOfDayInfo info = new TimeOfDayInfo();
519        info.setMilliSeconds(-1L);
520        boolean exceptionThrown = false;
521        try {
522            String todStr = TimeOfDayHelper.formatTimeOfDay(info);
523        } catch (InvalidParameterException e) {
524            exceptionThrown = true;
525        }
526        return exceptionThrown;
527    }
528    private boolean _testExceptionOnCreateTimeOfDay(int normalHour, int minute, TimeOfDayAmPmEnum amOrPm) {
529        boolean exceptionThrown = false;
530        try {
531            TimeOfDay tod = TimeOfDayHelper.createTimeOfDay(13, 0, TimeOfDayAmPmEnum.AM);
532        } catch (InvalidParameterException e) {
533            exceptionThrown = true;
534        }
535        return exceptionThrown;
536    }
537}