org.unitime.banner.dataexchange.BannerStudentEnrollmentMessage.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.banner.dataexchange.BannerStudentEnrollmentMessage.java

Source

/*
 * Licensed to The Apereo Foundation under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for
 * additional information regarding copyright ownership.
 *
 * The Apereo Foundation licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at:
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
*/
package org.unitime.banner.dataexchange;

import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.Vector;

import org.dom4j.Element;
import org.unitime.banner.model.BannerSection;
import org.unitime.timetable.ApplicationProperties;
import org.unitime.timetable.dataexchange.BaseImport;
import org.unitime.timetable.model.Class_;
import org.unitime.timetable.model.CourseDemand;
import org.unitime.timetable.model.CourseOffering;
import org.unitime.timetable.model.CourseRequest;
import org.unitime.timetable.model.CourseRequestOption;
import org.unitime.timetable.model.Session;
import org.unitime.timetable.model.Student;
import org.unitime.timetable.model.StudentClassEnrollment;
import org.unitime.timetable.model.StudentSectioningQueue;

/**
 * @author says
 *
 */
public class BannerStudentEnrollmentMessage extends BaseImport {

    private static final String propertiesElementName = "properties";
    private static final String rootElementName = "enterprise";
    private static String expectedDataSource;
    private static String expectedSource;
    private String messageDateTime;

    private Hashtable<Long, Set<Long>> iUpdatedStudents = new Hashtable<Long, Set<Long>>();

    @Override
    public void loadXml(Element rootElement) throws Exception {
        try {
            if (!rootElement.getName().equalsIgnoreCase(rootElementName)) {
                throw new Exception("Given XML is not a banner enterprise message.");
            }
            beginTransaction();

            propertiesElement(rootElement.element(propertiesElementName));

            membershipElements(rootElement);

            for (Map.Entry<Long, Set<Long>> entry : iUpdatedStudents.entrySet())
                if (!entry.getValue().isEmpty())
                    StudentSectioningQueue.studentChanged(getHibSession(), null, entry.getKey(), entry.getValue());

            commitTransaction();
        } catch (Exception e) {
            fatal("Exception: " + e.getMessage(), e);
            rollbackTransaction();
            throw e;
        }
    }

    private void propertiesElement(Element element) throws Exception {

        String datasource = element.elementTextTrim("datasource");
        if (getExpectedDataSource() != null && !datasource.equalsIgnoreCase(getExpectedDataSource())) {
            throw new Exception("Datasource for message does not match expected datasource:  " + datasource
                    + ", expected:  " + getExpectedDataSource());
        }

        messageDateTime = element.elementTextTrim("datetime");
        if (messageDateTime == null) {
            throw new Exception("Missing date stamp for this message.");
        }

        debug("Processing banner message from:  " + datasource + " with a date time of " + messageDateTime);
    }

    private String sourceIdElement(Element sourceIdElement) throws Exception {
        if (sourceIdElement == null) {
            return (null);
        }
        String source = sourceIdElement.elementTextTrim("source");
        if (getExpectedSource() != null && !getExpectedSource().equalsIgnoreCase(source)) {
            throw new Exception("Source for membership element does not match expected source:  " + source
                    + ", expected:  " + getExpectedSource());
        }
        return (sourceIdElement.elementTextTrim("id"));
    }

    private void membershipElements(Element rootElement) throws Exception {
        for (Element membershipElement : (List<Element>) rootElement.elements("membership")) {
            String crnTerm = sourceIdElement(membershipElement.element("sourceid"));
            if (crnTerm == null || crnTerm.length() == 0) {
                throw new Exception("Membership element is missing the crn and term data.");
            }
            int dotIndex = crnTerm.indexOf('.');
            if (dotIndex <= 0) {
                throw new Exception("Membership element has badly formed crn and term data:  " + crnTerm);
            }
            String crnStr = crnTerm.substring(0, dotIndex);
            String termCode = crnTerm.substring(dotIndex + 1, crnTerm.length());
            Integer crn = null;
            try {
                crn = Integer.parseInt(crnStr);
            } catch (Exception e) {
                throw new Exception("Membership element has a non-numeric crn:  " + crnStr);
            }
            CourseOffering courseOffering = BannerSection.findCourseOfferingForCrnAndTermCode(crn, termCode);
            if (courseOffering == null) {
                error("Enrollments for CRN:  " + crn.toString()
                        + " not loaded.  No UniTime course offering found to match CRN:  " + crn.toString()
                        + " in banner term:  " + termCode);
                continue;
            }
            List classes = BannerSection.findAllClassesForCrnAndTermCode(crn, termCode);
            Session acadSession = courseOffering.getSubjectArea().getSession();
            Set<Long> updatedStudents = iUpdatedStudents.get(acadSession.getUniqueId());
            if (updatedStudents == null) {
                updatedStudents = new HashSet<Long>();
                iUpdatedStudents.put(acadSession.getUniqueId(), updatedStudents);
            }
            memberElements(membershipElement, acadSession, courseOffering, classes, updatedStudents);
            flushIfNeeded(true);
        }
    }

    private void memberElements(Element membershipElement, Session acadSession, CourseOffering courseOffering,
            List classes, Set<Long> updatedStudents) throws Exception {
        for (Element memberElement : (List<Element>) membershipElement.elements("member")) {
            String id = sourceIdElement(memberElement.element("sourceid"));
            if (id == null || id.length() == 0) {
                throw new Exception("Missing student id from member element.");
            }
            String idType = memberElement.elementTextTrim("idtype");
            if (idType == null || !idType.equals("1")) {
                throw new Exception("Received invalid id type:  " + id + " expected:  1.");
            }
            Student student = Student.findByExternalId(acadSession.getUniqueId(), id);
            Long studentId = null;
            if (student == null) {
                student = new Student();
                student = new Student();
                student.setSession(acadSession);
                student.setFirstName("Name");
                student.setLastName("Unknown");
                student.setExternalUniqueId(id);
                student.setFreeTimeCategory(new Integer(0));
                student.setSchedulePreference(new Integer(0));
                student.setClassEnrollments(new HashSet<StudentClassEnrollment>());
                student.setCourseDemands(new HashSet<CourseDemand>());
                studentId = (Long) getHibSession().save(student);
            } else {
                studentId = student.getUniqueId();
            }
            Element roleElement = memberElement.element("role");
            if (roleElement == null) {
                throw new Exception("Missing role element.");
            }
            String recStatus = getOptionalStringAttribute(roleElement, "recstatus");
            if (recStatus != null && recStatus.equals("3")) {
                if (deleteEnrollment(student, courseOffering, classes)) {
                    updatedStudents.add(studentId);
                }
            } else {
                if (addUpdateEnrollment(student, courseOffering, classes)) {
                    updatedStudents.add(studentId);
                }
            }
        }
    }

    private Vector<StudentClassEnrollment> findStudentClassEnrollments(Student student, List classes) {
        Vector<StudentClassEnrollment> enrollments = new Vector<StudentClassEnrollment>();
        if (student.getClassEnrollments() != null && !student.getClassEnrollments().isEmpty()) {
            for (Iterator cit = classes.iterator(); cit.hasNext();) {
                Class_ c = (Class_) cit.next();
                StudentClassEnrollment sce = findStudentClassEnrollment(student, c);
                if (sce != null) {
                    enrollments.add(sce);
                }
            }
        }
        return (enrollments);
    }

    private StudentClassEnrollment findStudentClassEnrollment(Student student, Class_ clazz) {
        StudentClassEnrollment studentClassEnrollment = null;
        if (student.getClassEnrollments() != null) {
            for (Iterator ceIt = student.getClassEnrollments().iterator(); ceIt.hasNext();) {
                StudentClassEnrollment sce = (StudentClassEnrollment) ceIt.next();
                if (sce.getClazz().getUniqueId().equals(clazz.getUniqueId())) {
                    studentClassEnrollment = sce;
                    break;
                }
            }
        }
        return (studentClassEnrollment);
    }

    private boolean addUpdateEnrollment(Student student, CourseOffering courseOffering, List classes) {
        boolean changed = false;
        for (Iterator it = classes.iterator(); it.hasNext();) {
            Class_ c = (Class_) it.next();
            StudentClassEnrollment sce = findStudentClassEnrollment(student, c);
            if (sce == null) {
                changed = true;
                sce = new StudentClassEnrollment();
                sce.setStudent(student);
                sce.setClazz(c);
                sce.setCourseOffering(courseOffering);
                sce.setTimestamp(new java.util.Date());
                student.addToclassEnrollments(sce);
            }
        }

        // make sure all class enrollments have a course request filled in
        boolean fixCourseDemands = false;
        Set<CourseDemand> remaining = new HashSet<CourseDemand>(student.getCourseDemands());
        enrollments: for (StudentClassEnrollment sce : student.getClassEnrollments()) {
            if (sce.getCourseRequest() != null) {
                // already set -> no change is needed
                remaining.remove(sce.getCourseRequest().getCourseDemand());
            } else {
                for (CourseDemand d : student.getCourseDemands()) {
                    for (CourseRequest r : d.getCourseRequests()) {
                        if (r.getCourseOffering().equals(courseOffering)) {
                            // not set, but there is one that can be used already
                            sce.setCourseRequest(r);
                            changed = true;
                            continue enrollments;
                        }
                    }
                }

                // create a new request
                CourseDemand cd = new CourseDemand();
                cd.setTimestamp(new java.util.Date());
                cd.setCourseRequests(new HashSet<CourseRequest>());
                cd.setStudent(student);
                student.addTocourseDemands(cd);
                cd.setAlternative(false);
                cd.setPriority(student.getCourseDemands().size() + 1);
                cd.setWaitlist(false);
                CourseRequest cr = new CourseRequest();
                cd.getCourseRequests().add(cr);
                cr.setCourseDemand(cd);
                cr.setCourseRequestOptions(new HashSet<CourseRequestOption>());
                cr.setAllowOverlap(false);
                cr.setCredit(0);
                cr.setOrder(0);
                cr.setCourseOffering(sce.getCourseOffering());
                sce.setCourseRequest(cr);
                changed = true;
                fixCourseDemands = true;
            }
        }

        if (fixCourseDemands) {
            // removed unused course demands
            for (CourseDemand cd : remaining) {
                if (cd.getFreeTime() != null)
                    getHibSession().delete(cd.getFreeTime());
                for (CourseRequest cr : cd.getCourseRequests())
                    getHibSession().delete(cr);
                student.getCourseDemands().remove(cd);
                getHibSession().delete(cd);
            }
            // fix priorities
            int priority = 0;
            for (CourseDemand cd : new TreeSet<CourseDemand>(student.getCourseDemands())) {
                cd.setPriority(priority++);
                getHibSession().saveOrUpdate(cd);
            }
        }

        if (changed) {
            getHibSession().saveOrUpdate(student);
        }
        return changed;
    }

    private boolean deleteEnrollment(Student student, CourseOffering courseOffering, List classes) {
        boolean changed = false;
        Vector<StudentClassEnrollment> enrollments = findStudentClassEnrollments(student, classes);
        for (StudentClassEnrollment sce : enrollments) {
            changed = true;
            student.getClassEnrollments().remove(sce);
            getHibSession().delete(sce);
        }
        if (changed) {
            getHibSession().update(student);
        }
        return changed;
    }

    /**
     * @return the expectedDataSource
     */
    public static String getExpectedDataSource() {
        if (expectedDataSource == null) {
            expectedDataSource = ApplicationProperties.getProperty("banner.messaging.expected.datasource",
                    "Purdue University");
        }
        return expectedDataSource;
    }

    /**
     * @return the expectedSource
     */
    public static String getExpectedSource() {
        if (expectedSource == null) {
            expectedSource = ApplicationProperties.getProperty("banner.messaging.expected.source",
                    "Purdue University");
        }
        return expectedSource;
    }

}