001: /**********************************************************************************
002: * $URL: https://source.sakaiproject.org/svn/course-management/tags/sakai_2-4-1/cm-impl/hibernate-impl/impl/src/java/org/sakaiproject/coursemanagement/impl/SampleDataLoader.java $
003: * $Id: SampleDataLoader.java 28313 2007-04-04 18:14:09Z ajpoland@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2007 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.sakaiproject.coursemanagement.impl;
021:
022: import java.sql.Time;
023: import java.text.ParseException;
024: import java.text.SimpleDateFormat;
025: import java.util.ArrayList;
026: import java.util.Date;
027: import java.util.GregorianCalendar;
028: import java.util.HashSet;
029: import java.util.Iterator;
030: import java.util.List;
031: import java.util.Locale;
032: import java.util.Map;
033: import java.util.Set;
034:
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037: import org.sakaiproject.authz.cover.AuthzGroupService;
038: import org.sakaiproject.coursemanagement.api.AcademicSession;
039: import org.sakaiproject.coursemanagement.api.CanonicalCourse;
040: import org.sakaiproject.coursemanagement.api.CourseManagementAdministration;
041: import org.sakaiproject.coursemanagement.api.CourseManagementService;
042: import org.sakaiproject.coursemanagement.api.CourseOffering;
043: import org.sakaiproject.coursemanagement.api.EnrollmentSet;
044: import org.sakaiproject.coursemanagement.api.Meeting;
045: import org.sakaiproject.coursemanagement.api.Section;
046: import org.sakaiproject.coursemanagement.api.SectionCategory;
047: import org.sakaiproject.event.cover.EventTrackingService;
048: import org.sakaiproject.event.cover.UsageSessionService;
049: import org.sakaiproject.tool.api.Session;
050: import org.sakaiproject.tool.cover.SessionManager;
051: import org.springframework.beans.BeansException;
052: import org.springframework.beans.factory.BeanFactory;
053: import org.springframework.beans.factory.BeanFactoryAware;
054: import org.springframework.transaction.PlatformTransactionManager;
055: import org.springframework.transaction.TransactionDefinition;
056: import org.springframework.transaction.TransactionStatus;
057: import org.springframework.transaction.support.DefaultTransactionDefinition;
058:
059: public class SampleDataLoader implements BeanFactoryAware {
060: private static final Log log = LogFactory
061: .getLog(SampleDataLoader.class);
062:
063: protected static final String[] ACADEMIC_SESSION_EIDS = new String[4];
064: protected static final Date[] ACADEMIC_SESSION_START_DATES = new Date[4];
065: protected static final Date[] ACADEMIC_SESSION_END_DATES = new Date[4];
066:
067: protected static final String CS = "SMPL";
068:
069: protected static final String CC1 = "SMPL101";
070: protected static final String CC2 = "SMPL202";
071:
072: protected static final String CO1_PREFIX = CC1 + " ";
073: protected static final String CO2_PREFIX = CC2 + " ";
074:
075: protected static final String ENROLLMENT_SET_SUFFIX = "es";
076:
077: protected static final int ENROLLMENT_SETS_PER_ACADEMIC_SESSION = 2;
078: protected static final int ENROLLMENTS_PER_SET = 180;
079:
080: protected static final SimpleDateFormat sdf;
081: static {
082: ACADEMIC_SESSION_EIDS[0] = "Winter 2007";
083: ACADEMIC_SESSION_EIDS[1] = "Spring 2007";
084: ACADEMIC_SESSION_EIDS[2] = "Summer 2007";
085: ACADEMIC_SESSION_EIDS[3] = "Fall 2007";
086:
087: GregorianCalendar startCal = new GregorianCalendar();
088: GregorianCalendar endCal = new GregorianCalendar();
089:
090: startCal.set(2007, 0, 1);
091: endCal.set(2007, 3, 1);
092: ACADEMIC_SESSION_START_DATES[0] = startCal.getTime();
093: ACADEMIC_SESSION_END_DATES[0] = endCal.getTime();
094:
095: startCal.set(2007, 3, 1);
096: endCal.set(2007, 5, 1);
097: ACADEMIC_SESSION_START_DATES[1] = startCal.getTime();
098: ACADEMIC_SESSION_END_DATES[1] = endCal.getTime();
099:
100: startCal.set(2007, 5, 1);
101: endCal.set(2007, 8, 1);
102: ACADEMIC_SESSION_START_DATES[2] = startCal.getTime();
103: ACADEMIC_SESSION_END_DATES[2] = endCal.getTime();
104:
105: startCal.set(2007, 8, 1);
106: endCal.set(2008, 0, 1);
107: ACADEMIC_SESSION_START_DATES[3] = startCal.getTime();
108: ACADEMIC_SESSION_END_DATES[3] = endCal.getTime();
109:
110: sdf = new SimpleDateFormat("HH:mma");
111: }
112:
113: protected int studentMemberCount;
114:
115: // Begin Dependency Injection //
116: protected CourseManagementAdministration cmAdmin;
117:
118: public void setCmAdmin(CourseManagementAdministration cmAdmin) {
119: this .cmAdmin = cmAdmin;
120: }
121:
122: protected CourseManagementService cmService;
123:
124: public void setCmService(CourseManagementService cmService) {
125: this .cmService = cmService;
126: }
127:
128: protected BeanFactory beanFactory;
129:
130: public void setBeanFactory(BeanFactory beanFactory)
131: throws BeansException {
132: this .beanFactory = beanFactory;
133: }
134:
135: /** A flag for disabling the sample data load */
136: protected boolean loadSampleData;
137:
138: public void setLoadSampleData(boolean loadSampleData) {
139: this .loadSampleData = loadSampleData;
140: }
141:
142: // End Dependency Injection //
143:
144: public void init() {
145: log.info("Initializing " + getClass().getName());
146: if (cmAdmin == null) {
147: return;
148: }
149: if (loadSampleData) {
150: loginToSakai();
151: PlatformTransactionManager tm = (PlatformTransactionManager) beanFactory
152: .getBean("org.sakaiproject.springframework.orm.hibernate.GlobalTransactionManager");
153: DefaultTransactionDefinition def = new DefaultTransactionDefinition();
154: def
155: .setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
156: TransactionStatus status = tm.getTransaction(def);
157: try {
158: load();
159: } catch (Exception e) {
160: log.error("Unable to load CM data: " + e);
161: tm.rollback(status);
162: } finally {
163: if (!status.isCompleted()) {
164: tm.commit(status);
165: }
166: }
167: logoutFromSakai();
168: } else {
169: if (log.isInfoEnabled())
170: log.info("Skipped CM data load");
171: }
172: }
173:
174: public void destroy() {
175: log.info("Destroying " + getClass().getName());
176: }
177:
178: private void loginToSakai() {
179: Session sakaiSession = SessionManager.getCurrentSession();
180: sakaiSession.setUserId("admin");
181: sakaiSession.setUserEid("admin");
182:
183: // establish the user's session
184: UsageSessionService
185: .startSession("admin", "127.0.0.1", "CMSync");
186:
187: // update the user's externally provided realm definitions
188: AuthzGroupService.refreshUser("admin");
189:
190: // post the login event
191: EventTrackingService.post(EventTrackingService.newEvent(
192: UsageSessionService.EVENT_LOGIN, null, true));
193: }
194:
195: private void logoutFromSakai() {
196: Session sakaiSession = SessionManager.getCurrentSession();
197: sakaiSession.invalidate();
198:
199: // post the logout event
200: EventTrackingService.post(EventTrackingService.newEvent(
201: UsageSessionService.EVENT_LOGOUT, null, true));
202: }
203:
204: public void load() throws Exception {
205: // Don't do anything if we've got data already. The existence of an
206: // AcademicSession for the first legacy term will be our indicator for existing
207: // data.
208: List<AcademicSession> existingAcademicSessions = cmService
209: .getAcademicSessions();
210: if (existingAcademicSessions != null
211: && !existingAcademicSessions.isEmpty()) {
212: if (log.isInfoEnabled())
213: log.info("CM data exists, skipping data load.");
214: return;
215: }
216:
217: // Academic Sessions
218: List<AcademicSession> academicSessions = new ArrayList<AcademicSession>();
219: for (int i = 0; i < ACADEMIC_SESSION_EIDS.length; i++) {
220: String academicSessionEid = ACADEMIC_SESSION_EIDS[i];
221: academicSessions.add(cmAdmin.createAcademicSession(
222: academicSessionEid, academicSessionEid,
223: academicSessionEid,
224: ACADEMIC_SESSION_START_DATES[i],
225: ACADEMIC_SESSION_END_DATES[i]));
226: }
227:
228: // Course Sets
229: cmAdmin.createCourseSet(CS, "Sample Department",
230: "We study wet things in the Sample Dept", "DEPT", null);
231: cmAdmin.addOrUpdateCourseSetMembership("da1", "DeptAdmin", CS,
232: "active");
233:
234: // Cross-listed Canonical Courses
235: Set<CanonicalCourse> cc = new HashSet<CanonicalCourse>();
236: cc.add(cmAdmin.createCanonicalCourse(CC1, "Sample 101",
237: "A survey of samples"));
238: cc.add(cmAdmin.createCanonicalCourse(CC2, "Sample 202",
239: "An in depth study of samples"));
240: cmAdmin.setEquivalentCanonicalCourses(cc);
241:
242: // Keep an ordered list of COs for use in building enrollment sets & adding enrollments
243: List<CourseOffering> courseOfferingsList = new ArrayList<CourseOffering>();
244:
245: for (Iterator<AcademicSession> iter = academicSessions
246: .iterator(); iter.hasNext();) {
247: AcademicSession as = iter.next();
248: CourseOffering co1 = cmAdmin.createCourseOffering(
249: CO1_PREFIX + as.getEid(), CC1,
250: "Sample course offering #1, " + as.getEid(),
251: "open", as.getEid(), CC1, as.getStartDate(), as
252: .getEndDate());
253: CourseOffering co2 = cmAdmin.createCourseOffering(
254: CO2_PREFIX + as.getEid(), CC2,
255: "Sample course offering #2, " + as.getEid(),
256: "open", as.getEid(), CC2, as.getStartDate(), as
257: .getEndDate());
258:
259: courseOfferingsList.add(co1);
260: courseOfferingsList.add(co2);
261:
262: Set<CourseOffering> courseOfferingSet = new HashSet<CourseOffering>();
263: courseOfferingSet.add(co1);
264: courseOfferingSet.add(co2);
265:
266: // Cross list these course offerings
267: cmAdmin.setEquivalentCourseOfferings(courseOfferingSet);
268:
269: cmAdmin.addCourseOfferingToCourseSet(CS, co1.getEid());
270: cmAdmin.addCourseOfferingToCourseSet(CS, co2.getEid());
271:
272: // And add some other instructors at the offering level (this should help with testing cross listings)
273: cmAdmin.addOrUpdateCourseOfferingMembership("instructor1",
274: "I", co1.getEid(), null);
275: cmAdmin.addOrUpdateCourseOfferingMembership("instructor2",
276: "I", co2.getEid(), null);
277: }
278:
279: Map<String, String> enrollmentStatuses = cmService
280: .getEnrollmentStatusDescriptions(Locale.US);
281: Map<String, String> gradingSchemes = cmService
282: .getGradingSchemeDescriptions(Locale.US);
283:
284: List<String> enrollmentEntries = new ArrayList<String>(
285: enrollmentStatuses.keySet());
286: List<String> gradingEntries = new ArrayList<String>(
287: gradingSchemes.keySet());
288: int enrollmentIndex = 0;
289: int gradingIndex = 0;
290:
291: // Enrollment sets and sections
292: Set<String> instructors = new HashSet<String>();
293: instructors.add("admin");
294: instructors.add("instructor");
295:
296: int enrollmentOffset = 1;
297: for (Iterator<CourseOffering> iter = courseOfferingsList
298: .iterator(); iter.hasNext();) {
299: if (enrollmentOffset > (ENROLLMENT_SETS_PER_ACADEMIC_SESSION * ENROLLMENTS_PER_SET)) {
300: enrollmentOffset = 1;
301: }
302:
303: CourseOffering co = iter.next();
304: EnrollmentSet es = cmAdmin.createEnrollmentSet(co.getEid()
305: + ENROLLMENT_SET_SUFFIX, co.getTitle()
306: + " Enrollment Set", co.getDescription()
307: + " Enrollment Set", "lecture", "3", co.getEid(),
308: instructors);
309:
310: // Enrollments
311: for (int enrollmentCounter = enrollmentOffset; enrollmentCounter < (enrollmentOffset + ENROLLMENTS_PER_SET); enrollmentCounter++) {
312: if (++gradingIndex == gradingEntries.size()) {
313: gradingIndex = 0;
314: }
315: String gradingScheme = gradingEntries.get(gradingIndex);
316:
317: if (++enrollmentIndex == enrollmentEntries.size()) {
318: enrollmentIndex = 0;
319: }
320: String enrollmentStatus = enrollmentEntries
321: .get(enrollmentIndex);
322:
323: cmAdmin.addOrUpdateEnrollment("student"
324: + enrollmentCounter, es.getEid(),
325: enrollmentStatus, "3", gradingScheme);
326: }
327: enrollmentOffset += ENROLLMENTS_PER_SET;
328: }
329:
330: // Don't load the sections in a loop, since we need to define specific data for each
331: // Section Categories (these are returned in alpha order, so we can control the order here)
332: SectionCategory lectureCategory = cmAdmin.addSectionCategory(
333: "01.lct", "Lecture");
334: SectionCategory discussionCategory = cmAdmin
335: .addSectionCategory("03.dsc", "Discussion");
336: cmAdmin.addSectionCategory("02.lab", "Lab");
337: cmAdmin.addSectionCategory("04.rec", "Recitation");
338: cmAdmin.addSectionCategory("05.sto", "Studio");
339:
340: for (Iterator<AcademicSession> iter = cmService
341: .getAcademicSessions().iterator(); iter.hasNext();) {
342: AcademicSession as = iter.next();
343:
344: // Clear the student count for this academic session
345: resetStudentMemberCount();
346:
347: // Lecture Sections
348: String co1Eid = CO1_PREFIX + as.getEid();
349: String lec1Eid = co1Eid;
350: Section lec1 = cmAdmin.createSection(lec1Eid, lec1Eid,
351: lec1Eid + " Lecture", lectureCategory
352: .getCategoryCode(), null, co1Eid, co1Eid
353: + ENROLLMENT_SET_SUFFIX);
354: Set<Meeting> lec1Meetings = new HashSet<Meeting>();
355: Meeting mtg1 = cmAdmin.newSectionMeeting(lec1.getEid(),
356: "A Building 11", getTime("10:30am"),
357: getTime("11:00am"), null);
358: mtg1.setMonday(true);
359: mtg1.setWednesday(true);
360: mtg1.setFriday(true);
361: lec1Meetings.add(mtg1);
362: lec1.setMeetings(lec1Meetings);
363: cmAdmin.updateSection(lec1);
364: if (log.isDebugEnabled())
365: log.debug("Created section " + lec1Eid);
366:
367: String co2Eid = CO2_PREFIX + as.getEid();
368: String lec2Eid = co2Eid;
369: Section lec2 = cmAdmin.createSection(lec2Eid, lec2Eid,
370: lec2Eid + " Lecture", lectureCategory
371: .getCategoryCode(), null, co2Eid, co2Eid
372: + ENROLLMENT_SET_SUFFIX);
373: Set<Meeting> lec2Meetings = new HashSet<Meeting>();
374: Meeting mtg2 = cmAdmin.newSectionMeeting(lec2.getEid(),
375: "A Building 11", getTime("10:30am"),
376: getTime("11:00am"), null);
377: mtg2.setMonday(true);
378: mtg2.setWednesday(true);
379: mtg2.setFriday(true);
380: lec2Meetings.add(mtg2);
381: lec2.setMeetings(lec2Meetings);
382: cmAdmin.updateSection(lec2);
383: if (log.isDebugEnabled())
384: log.debug("Created section " + lec2Eid);
385:
386: // Discussion sections, first Course Offering
387:
388: loadDiscussionSection("Discussion 1 " + CC1, as.getEid(),
389: co1Eid, discussionCategory.getCategoryCode(), null,
390: null, null, new boolean[] { false, false, false,
391: false, false, false, false },
392: studentMemberCount, incrementStudentCount());
393:
394: loadDiscussionSection("Discussion 2 " + CC1, as.getEid(),
395: co1Eid, discussionCategory.getCategoryCode(),
396: "B Building 202", getTime("10:00AM"),
397: getTime("11:30AM"), new boolean[] { false, true,
398: false, true, false, false, false },
399: studentMemberCount, incrementStudentCount());
400:
401: loadDiscussionSection("Discussion 3 " + CC1, as.getEid(),
402: co1Eid, discussionCategory.getCategoryCode(),
403: "B Hall 11", getTime("9:00AM"), getTime("10:30AM"),
404: new boolean[] { false, true, false, true, false,
405: false, false }, studentMemberCount,
406: incrementStudentCount());
407:
408: loadDiscussionSection("Discussion 4 " + CC1, as.getEid(),
409: co1Eid, discussionCategory.getCategoryCode(),
410: "C Building 100", getTime("1:30PM"),
411: getTime("3:00PM"), new boolean[] { false, true,
412: false, true, false, false, false },
413: studentMemberCount, incrementStudentCount());
414:
415: loadDiscussionSection("Discussion 5 " + CC1, as.getEid(),
416: co1Eid, discussionCategory.getCategoryCode(),
417: "Building 10", getTime("9:00AM"),
418: getTime("10:00AM"), new boolean[] { true, false,
419: true, false, true, false, false },
420: studentMemberCount, incrementStudentCount());
421:
422: loadDiscussionSection("Discussion 6 " + CC1, as.getEid(),
423: co1Eid, discussionCategory.getCategoryCode(),
424: "Hall 200", getTime("4:00PM"), getTime("5:00PM"),
425: new boolean[] { true, false, true, false, true,
426: false, false }, studentMemberCount,
427: incrementStudentCount());
428:
429: // Discussion sections, second Course Offering
430:
431: loadDiscussionSection("Discussion 1 " + CC2, as.getEid(),
432: co2Eid, discussionCategory.getCategoryCode(), null,
433: null, null, new boolean[] { false, false, false,
434: false, false, false, false },
435: studentMemberCount, incrementStudentCount());
436:
437: loadDiscussionSection("Discussion 2 " + CC2, as.getEid(),
438: co2Eid, discussionCategory.getCategoryCode(),
439: "2 Building A", getTime("11:30AM"),
440: getTime("1:00PM"), new boolean[] { false, true,
441: false, true, false, false, false },
442: studentMemberCount, incrementStudentCount());
443:
444: loadDiscussionSection("Discussion 3 " + CC2, as.getEid(),
445: co2Eid, discussionCategory.getCategoryCode(),
446: "101 Hall A", getTime("10:00AM"),
447: getTime("11:00AM"), new boolean[] { true, false,
448: true, false, true, false, false },
449: studentMemberCount, incrementStudentCount());
450:
451: loadDiscussionSection("Discussion 4 " + CC2, as.getEid(),
452: co2Eid, discussionCategory.getCategoryCode(),
453: "202 Building", getTime("8:00AM"),
454: getTime("9:00AM"), new boolean[] { true, false,
455: true, false, true, false, false },
456: studentMemberCount, incrementStudentCount());
457:
458: loadDiscussionSection("Discussion 5 " + CC2, as.getEid(),
459: co2Eid, discussionCategory.getCategoryCode(),
460: "11 Hall B", getTime("2:00PM"), getTime("3:30PM"),
461: new boolean[] { false, true, false, true, false,
462: false, false }, studentMemberCount,
463: incrementStudentCount());
464:
465: loadDiscussionSection("Discussion 6 " + CC2, as.getEid(),
466: co2Eid, discussionCategory.getCategoryCode(),
467: "100 Building C", getTime("3:00PM"),
468: getTime("4:00PM"), new boolean[] { true, false,
469: true, false, true, false, false },
470: studentMemberCount, incrementStudentCount());
471: }
472:
473: if (log.isInfoEnabled())
474: log.info("Finished loading sample CM data");
475: }
476:
477: protected Time getTime(String timeString) {
478: Date date = null;
479: try {
480: date = sdf.parse(timeString);
481: } catch (ParseException pe) {
482: log.error("Can not parse time " + timeString);
483: date = new Date();
484: }
485: return new Time(date.getTime());
486: }
487:
488: protected void loadDiscussionSection(String secEidPrefix,
489: String asEid, String coEid, String categoryCode,
490: String location, Time startTime, Time endTime,
491: boolean[] days, int studentStart, int studentEnd) {
492: String secEid = secEidPrefix + " " + asEid;
493: Section sec = cmAdmin.createSection(secEid, secEidPrefix,
494: secEid, categoryCode, null, coEid, null);
495: for (int studentCounter = studentStart; studentCounter < studentEnd; studentCounter++) {
496: cmAdmin.addOrUpdateSectionMembership("student"
497: + studentCounter, "S", secEid, "member");
498: }
499: cmAdmin.addOrUpdateSectionMembership("instructor", "I", secEid,
500: "section_leader");
501: cmAdmin.addOrUpdateSectionMembership("admin", "I", secEid,
502: "section_leader");
503:
504: Set<Meeting> meetings = new HashSet<Meeting>();
505: Meeting mtg = cmAdmin.newSectionMeeting(secEid, location,
506: startTime, endTime, null);
507: mtg.setMonday(days[0]);
508: mtg.setTuesday(days[1]);
509: mtg.setWednesday(days[2]);
510: mtg.setThursday(days[3]);
511: mtg.setFriday(days[4]);
512: mtg.setSaturday(days[5]);
513: mtg.setSunday(days[6]);
514: meetings.add(mtg);
515: sec.setMeetings(meetings);
516: cmAdmin.updateSection(sec);
517:
518: if (log.isDebugEnabled())
519: log.debug("Created section " + secEid);
520: }
521:
522: protected int incrementStudentCount() {
523: studentMemberCount += 30;
524: return studentMemberCount;
525: }
526:
527: protected void resetStudentMemberCount() {
528: studentMemberCount = 1;
529: }
530: }
|