org.unitime.timetable.solver.instructor.InstructorSchedulingDatabaseSaver.java Source code

Java tutorial

Introduction

Here is the source code for org.unitime.timetable.solver.instructor.InstructorSchedulingDatabaseSaver.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.timetable.solver.instructor;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.cpsolver.ifs.solver.Solver;
import org.cpsolver.ifs.util.ProblemSaver;
import org.cpsolver.ifs.util.Progress;
import org.cpsolver.instructor.model.InstructorSchedulingModel;
import org.cpsolver.instructor.model.TeachingAssignment;
import org.cpsolver.instructor.model.TeachingRequest;
import org.hibernate.CacheMode;
import org.hibernate.Transaction;
import org.unitime.timetable.ApplicationProperties;
import org.unitime.timetable.defaults.ApplicationProperty;
import org.unitime.timetable.interfaces.ExternalCourseOfferingEditAction;
import org.unitime.timetable.interfaces.ExternalInstrOfferingConfigAssignInstructorsAction;
import org.unitime.timetable.model.ClassInstructor;
import org.unitime.timetable.model.Class_;
import org.unitime.timetable.model.DepartmentalInstructor;
import org.unitime.timetable.model.InstrOfferingConfig;
import org.unitime.timetable.model.InstructionalOffering;
import org.unitime.timetable.model.OfferingCoordinator;
import org.unitime.timetable.model.Session;
import org.unitime.timetable.model.StudentSectioningQueue;
import org.unitime.timetable.model.TeachingClassRequest;
import org.unitime.timetable.model.dao.SessionDAO;
import org.unitime.timetable.model.dao._RootDAO;
import org.unitime.timetable.solver.jgroups.SolverServerImplementation;
import org.unitime.timetable.util.NameFormat;

/**
 * @author Tomas Muller
 */
public class InstructorSchedulingDatabaseSaver
        extends ProblemSaver<TeachingRequest.Variable, TeachingAssignment, InstructorSchedulingModel> {
    private String iInstructorFormat;
    private Long iSessionId = null;
    private Set<Long> iSolverGroupId = new HashSet<Long>();
    private Set<InstrOfferingConfig> iUpdatedConfigs = new HashSet<InstrOfferingConfig>();
    private Set<InstructionalOffering> iUpdatedOfferings = new HashSet<InstructionalOffering>();
    private Progress iProgress = null;
    private boolean iTentative = true;
    private boolean iShowClassSuffix = false, iShowConfigName = false;

    public InstructorSchedulingDatabaseSaver(Solver solver) {
        super(solver);
        iProgress = Progress.getInstance(getModel());
        iSessionId = getModel().getProperties().getPropertyLong("General.SessionId", (Long) null);
        for (Long id : getModel().getProperties().getPropertyLongArry("General.SolverGroupId", null))
            iSolverGroupId.add(id);
        iTentative = !getModel().getProperties().getPropertyBoolean("Save.Commit", false);
        iInstructorFormat = getModel().getProperties().getProperty("General.InstructorFormat",
                NameFormat.LAST_FIRST.reference());
        iShowClassSuffix = ApplicationProperty.SolverShowClassSufix.isTrue();
        iShowConfigName = ApplicationProperty.SolverShowConfiguratioName.isTrue();
    }

    @Override
    public void save() throws Exception {
        ApplicationProperties.setSessionId(iSessionId);
        iProgress.setStatus("Saving solution ...");
        org.hibernate.Session hibSession = new _RootDAO().getSession();
        hibSession.setCacheMode(CacheMode.IGNORE);
        Transaction tx = null;
        try {
            tx = hibSession.beginTransaction();
            saveSolution(hibSession);
            tx.commit();

            if (!iUpdatedConfigs.isEmpty()) {
                String className = ApplicationProperty.ExternalActionInstrOfferingConfigAssignInstructors.value();
                if (className != null && className.trim().length() > 0) {
                    ExternalInstrOfferingConfigAssignInstructorsAction assignAction = (ExternalInstrOfferingConfigAssignInstructorsAction) (Class
                            .forName(className).newInstance());
                    iProgress.setPhase("Performing external actions ...", iUpdatedConfigs.size());
                    for (InstrOfferingConfig ioc : iUpdatedConfigs) {
                        iProgress.incProgress();
                        assignAction.performExternalInstrOfferingConfigAssignInstructorsAction(ioc, hibSession);
                    }
                }
            }
            if (!iUpdatedOfferings.isEmpty()) {
                String className = ApplicationProperty.ExternalActionCourseOfferingEdit.value();
                if (className != null && className.trim().length() > 0) {
                    ExternalCourseOfferingEditAction editAction = (ExternalCourseOfferingEditAction) (Class
                            .forName(className).newInstance());
                    iProgress.setPhase("Performing external actions ...", iUpdatedOfferings.size());
                    for (InstructionalOffering io : iUpdatedOfferings) {
                        iProgress.incProgress();
                        editAction.performExternalCourseOfferingEditAction(io, hibSession);
                    }
                }
            }

            iProgress.setPhase("Refreshing solution ...", 1);
            try {
                if (SolverServerImplementation.getInstance() != null)
                    SolverServerImplementation.getInstance().refreshInstructorSolution(iSolverGroupId);
                iProgress.incProgress();
            } catch (Exception e) {
                iProgress.warn("Unable to refresh solution, reason:" + e.getMessage(), e);
            }

            if (!iUpdatedOfferings.isEmpty() || !iUpdatedConfigs.isEmpty()) {
                Session session = SessionDAO.getInstance().get(iSessionId, hibSession);
                if (!session.getStatusType().isTestSession() && (session.getStatusType().canOnlineSectionStudents()
                        || session.getStatusType().canSectionAssistStudents())) {
                    Set<Long> offeringIds = new HashSet<Long>();
                    for (InstructionalOffering io : iUpdatedOfferings)
                        offeringIds.add(io.getUniqueId());
                    for (InstrOfferingConfig config : iUpdatedConfigs)
                        offeringIds.add(config.getInstructionalOffering().getUniqueId());
                    StudentSectioningQueue.offeringChanged(hibSession, null, iSessionId, offeringIds);
                    hibSession.flush();
                }
            }
        } catch (Exception e) {
            if (tx != null)
                tx.rollback();
            iProgress.fatal("Unable to save a solution, reason: " + e.getMessage(), e);
        } finally {
            // here we need to close the session since this code may run in a separate thread
            if (hibSession != null && hibSession.isOpen())
                hibSession.close();
        }
    }

    protected String toHtml(Class_ clazz) {
        return "<A href='classDetail.do?cid=" + clazz.getUniqueId() + "'>"
                + clazz.getClassLabel(iShowClassSuffix, iShowConfigName) + "</A>";
    }

    protected String toHtml(DepartmentalInstructor instructor) {
        return "<a href='instructorDetail.do?instructorId=" + instructor.getUniqueId() + "&deptId="
                + instructor.getDepartment().getUniqueId() + "'>" + instructor.getName(iInstructorFormat) + "</a>";
    }

    protected String toHtml(TeachingAssignment assignment) {
        return "<a href='instructorDetail.do?instructorId=" + assignment.getInstructor().getInstructorId() + "'>"
                + assignment.getInstructor().getName() + "</a>";
    }

    protected String toHtml(TeachingRequest request) {
        return "<a href='classDetail.do?cid=" + request.getSections().get(0).getSectionId() + "'>"
                + request.getCourse().getCourseName() + " " + request.getSections() + "</a>";
    }

    protected void saveSolution(org.hibernate.Session hibSession) {
        iProgress.setPhase("Loading instructors ...", 1);
        Map<Long, DepartmentalInstructor> instructors = new HashMap<Long, DepartmentalInstructor>();
        Set<DepartmentalInstructor> changedInstructors = new HashSet<DepartmentalInstructor>();
        Set<InstructionalOffering> changedOfferings = new HashSet<InstructionalOffering>();
        for (DepartmentalInstructor instructor : (List<DepartmentalInstructor>) hibSession
                .createQuery(
                        "select i from DepartmentalInstructor i, SolverGroup g inner join g.departments d where "
                                + "g.uniqueId in :solverGroupId and i.department = d")
                .setParameterList("solverGroupId", iSolverGroupId).list()) {
            instructors.put(instructor.getUniqueId(), instructor);
            for (Iterator<ClassInstructor> i = instructor.getClasses().iterator(); i.hasNext();) {
                ClassInstructor ci = i.next();
                if (ci.getTeachingRequest() != null) {
                    iUpdatedConfigs.add(ci.getClassInstructing().getSchedulingSubpart().getInstrOfferingConfig());
                    changedInstructors.add(ci.getInstructor());
                    ci.getClassInstructing().getClassInstructors().remove(ci);
                    i.remove();
                    hibSession.delete(ci);
                }
            }
        }
        iProgress.incProgress();
        for (OfferingCoordinator coordinator : (List<OfferingCoordinator>) hibSession.createQuery(
                "select c from OfferingCoordinator c inner join c.instructor i, SolverGroup g inner join g.departments d where "
                        + "g.uniqueId in :solverGroupId and i.department = d")
                .setParameterList("solverGroupId", iSolverGroupId).list()) {
            if (coordinator.getTeachingRequest() != null) {
                iUpdatedOfferings.add(coordinator.getOffering());
                changedOfferings.add(coordinator.getOffering());
                coordinator.getOffering().getOfferingCoordinators().remove(coordinator);
                hibSession.delete(coordinator);
            }
        }

        iProgress.setPhase("Loading requests ...", 1);
        Map<Long, org.unitime.timetable.model.TeachingRequest> requests = new HashMap<Long, org.unitime.timetable.model.TeachingRequest>();
        for (org.unitime.timetable.model.TeachingRequest request : (List<org.unitime.timetable.model.TeachingRequest>) hibSession
                .createQuery(
                        "select r from TeachingRequest r inner join r.offering.courseOfferings co where co.isControl = true and co.subjectArea.department.solverGroup.uniqueId in :solverGroupId")
                .setParameterList("solverGroupId", iSolverGroupId).list()) {
            request.getAssignedInstructors().clear();
            requests.put(request.getUniqueId(), request);
        }
        iProgress.incProgress();

        iProgress.setPhase("Saving instructor assignments ...", getModel().variables().size());
        for (TeachingRequest.Variable request : getModel().variables()) {
            iProgress.incProgress();
            TeachingAssignment assignment = getAssignment().getValue(request);
            if (assignment == null)
                continue;
            DepartmentalInstructor instructor = instructors.get(assignment.getInstructor().getInstructorId());
            if (instructor == null)
                continue;
            org.unitime.timetable.model.TeachingRequest r = requests.get(request.getRequest().getRequestId());
            if (r == null)
                continue;
            r.getAssignedInstructors().add(instructor);
            if (!iTentative) {
                if (r.isAssignCoordinator()) {
                    OfferingCoordinator oc = new OfferingCoordinator();
                    oc.setInstructor(instructor);
                    oc.setOffering(r.getOffering());
                    oc.setResponsibility(r.getResponsibility());
                    oc.setPercentShare(r.getPercentShare());
                    oc.setTeachingRequest(r);
                    r.getOffering().getOfferingCoordinators().add(oc);
                    changedOfferings.add(r.getOffering());
                    hibSession.save(oc);
                    iUpdatedOfferings.add(r.getOffering());
                }
                for (TeachingClassRequest cr : r.getClassRequests()) {
                    if (cr.isAssignInstructor()) {
                        ClassInstructor ci = new ClassInstructor();
                        ci.setClassInstructing(cr.getTeachingClass());
                        ci.setInstructor(instructor);
                        ci.setLead(cr.isLead());
                        ci.setPercentShare(cr.getPercentShare());
                        ci.setResponsibility(r.getResponsibility());
                        ci.setTeachingRequest(r);
                        cr.getTeachingClass().getClassInstructors().add(ci);
                        instructor.getClasses().add(ci);
                        changedInstructors.add(ci.getInstructor());
                        hibSession.saveOrUpdate(ci);
                        iUpdatedConfigs.add(cr.getTeachingClass().getSchedulingSubpart().getInstrOfferingConfig());
                    }
                }
            }
        }

        for (org.unitime.timetable.model.TeachingRequest request : requests.values())
            hibSession.saveOrUpdate(request);
        for (DepartmentalInstructor instructor : changedInstructors)
            hibSession.saveOrUpdate(instructor);
        for (InstructionalOffering offering : changedOfferings)
            hibSession.saveOrUpdate(offering);
    }

}