Java tutorial
/* * UniTime 3.2 - 3.5 (University Timetabling Application) * Copyright (C) 2008 - 2013, UniTime LLC, and individual contributors * as indicated by the @authors tag. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. * */ package org.unitime.timetable.action; import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.Vector; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.action.ActionMessages; import org.apache.struts.util.LabelValueBean; import org.cpsolver.ifs.util.CSVFile; import org.hibernate.Transaction; import org.hibernate.criterion.Order; import org.hibernate.criterion.Restrictions; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.unitime.commons.Debug; import org.unitime.commons.web.WebTable; import org.unitime.timetable.ApplicationProperties; import org.unitime.timetable.form.TimePatternEditForm; import org.unitime.timetable.model.Class_; import org.unitime.timetable.model.Department; import org.unitime.timetable.model.SchedulingSubpart; import org.unitime.timetable.model.TimePattern; import org.unitime.timetable.model.TimePatternDays; import org.unitime.timetable.model.TimePatternTime; import org.unitime.timetable.model.TimePref; import org.unitime.timetable.model.dao.DepartmentDAO; import org.unitime.timetable.model.dao.TimePatternDAO; import org.unitime.timetable.security.SessionContext; import org.unitime.timetable.security.rights.Right; import org.unitime.timetable.util.Constants; import org.unitime.timetable.util.ExportUtils; /** * @author Tomas Muller */ @Service("/timePatternEdit") public class TimePatternEditAction extends Action { @Autowired SessionContext sessionContext; public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { try { TimePatternEditForm myForm = (TimePatternEditForm) form; // Check Access sessionContext.checkPermission(Right.TimePatterns); // Read operation to be performed String op = (myForm.getOp() != null ? myForm.getOp() : request.getParameter("op")); if (request.getParameterValues("depts") != null) { String[] depts = request.getParameterValues("depts"); for (int i = 0; i < depts.length; i++) myForm.getDepartmentIds().add(new Long(depts[i])); } if (op == null) { myForm.load(null, null); myForm.setOp("List"); } Long sessionId = sessionContext.getUser().getCurrentAcademicSessionId(); List list = (new DepartmentDAO()).getSession().createCriteria(Department.class) .add(Restrictions.eq("session.uniqueId", sessionId)).addOrder(Order.asc("deptCode")).list(); Vector availableDepts = new Vector(); for (Iterator iter = list.iterator(); iter.hasNext();) { Department d = (Department) iter.next(); availableDepts .add(new LabelValueBean(d.getDeptCode() + "-" + d.getName(), d.getUniqueId().toString())); } request.setAttribute(Department.DEPT_ATTR_NAME, availableDepts); // Reset Form if ("Back".equals(op)) { if (myForm.getUniqueId() != null) request.setAttribute("hash", myForm.getUniqueId()); myForm.load(null, null); myForm.setOp("List"); } if ("Add Department".equals(op)) { ActionMessages errors = new ActionErrors(); if (myForm.getDepartmentId() == null || myForm.getDepartmentId().longValue() < 0) errors.add("department", new ActionMessage("errors.generic", "No department selected.")); else { boolean contains = myForm.getDepartmentIds().contains(myForm.getDepartmentId()); if (contains) errors.add("department", new ActionMessage("errors.generic", "Department already present in the list of departments.")); } if (errors.size() > 0) { saveErrors(request, errors); } else { myForm.getDepartmentIds().add(myForm.getDepartmentId()); } myForm.setOp(myForm.getUniqueId().longValue() < 0 ? "Save" : "Update"); } if ("Remove Department".equals(op)) { ActionMessages errors = new ActionErrors(); if (myForm.getDepartmentId() == null || myForm.getDepartmentId().longValue() < 0) errors.add("department", new ActionMessage("errors.generic", "No department selected.")); else { boolean contains = myForm.getDepartmentIds().contains(myForm.getDepartmentId()); if (!contains) errors.add("department", new ActionMessage("errors.generic", "Department not present in the list of departments.")); } if (errors.size() > 0) { saveErrors(request, errors); } else { myForm.getDepartmentIds().remove(myForm.getDepartmentId()); } myForm.setOp(myForm.getUniqueId().longValue() < 0 ? "Save" : "Update"); } // Add / Update if ("Update".equals(op) || "Save".equals(op)) { // Validate input ActionMessages errors = myForm.validate(mapping, request); if (errors.size() > 0) { saveErrors(request, errors); } else { Transaction tx = null; try { org.hibernate.Session hibSession = (new TimePatternDAO()).getSession(); if (hibSession.getTransaction() == null || !hibSession.getTransaction().isActive()) tx = hibSession.beginTransaction(); myForm.saveOrUpdate(sessionContext, hibSession); if (tx != null) tx.commit(); } catch (Exception e) { if (tx != null) tx.rollback(); throw e; } if (myForm.getUniqueId() != null) request.setAttribute("hash", myForm.getUniqueId()); myForm.setOp("List"); } } // Edit if ("Edit".equals(op)) { String id = request.getParameter("id"); ActionMessages errors = new ActionMessages(); if (id == null || id.trim().length() == 0) { errors.add("key", new ActionMessage("errors.invalid", "Unique Id : " + id)); saveErrors(request, errors); return mapping.findForward("list"); } else { TimePattern pattern = (new TimePatternDAO()).get(new Long(id)); if (pattern == null) { errors.add("name", new ActionMessage("errors.invalid", "Unique Id : " + id)); saveErrors(request, errors); return mapping.findForward("list"); } else { myForm.load(pattern, sessionId); } } } // Delete if ("Delete".equals(op)) { Transaction tx = null; try { org.hibernate.Session hibSession = (new TimePatternDAO()).getSession(); if (hibSession.getTransaction() == null || !hibSession.getTransaction().isActive()) tx = hibSession.beginTransaction(); myForm.delete(sessionContext, hibSession); tx.commit(); } catch (Exception e) { if (tx != null) tx.rollback(); throw e; } myForm.load(null, null); myForm.setOp("List"); } if ("Exact Times CSV".equals(op)) { Transaction tx = null; try { org.hibernate.Session hibSession = (new TimePatternDAO()).getSession(); if (hibSession.getTransaction() == null || !hibSession.getTransaction().isActive()) tx = hibSession.beginTransaction(); TimePattern tp = TimePattern.findExactTime(sessionId); if (tp == null) { myForm.load(null, null); myForm.setOp("List"); getTimePatterns(request, sessionId); ActionMessages errors = new ActionMessages(); errors.add("key", new ActionMessage("errors.generic", "There is no Exact Time time pattern defined.")); saveErrors(request, errors); return mapping.findForward("list"); } List timePrefs = hibSession.createQuery( "select distinct p from TimePref as p inner join p.timePattern as tp where tp.uniqueId=:uniqueid") .setLong("uniqueid", tp.getUniqueId().longValue()).list(); CSVFile csv = new CSVFile(); csv.setHeader(new CSVFile.CSVField[] { new CSVFile.CSVField("Class"), new CSVFile.CSVField("Pattern"), new CSVFile.CSVField("Time") }); for (Iterator i = timePrefs.iterator(); i.hasNext();) { TimePref tpref = (TimePref) i.next(); if (!(tpref.getOwner() instanceof Class_)) continue; Class_ clazz = (Class_) tpref.getOwner(); if (!clazz.getSessionId().equals(sessionId)) continue; int dayCode = tpref.getTimePatternModel().getExactDays(); String name = ""; int nrDays = 0; for (int j = 0; j < Constants.DAY_CODES.length; j++) { if ((Constants.DAY_CODES[j] & dayCode) != 0) { name += Constants.DAY_NAMES_SHORT[j]; nrDays++; } } name += " "; int startSlot = tpref.getTimePatternModel().getExactStartSlot(); name += Constants .toTime(Constants.FIRST_SLOT_TIME_MIN + (Constants.SLOT_LENGTH_MIN * startSlot)); int minPerMtg = (nrDays == 0 ? 0 : clazz.getSchedulingSubpart().getMinutesPerWk().intValue() / nrDays); if (nrDays == 0) Debug.warning("Class " + clazz.getClassLabel() + " has zero number of days."); csv.addLine(new CSVFile.CSVField[] { new CSVFile.CSVField(clazz.getClassLabel()), new CSVFile.CSVField(nrDays + " x " + minPerMtg), new CSVFile.CSVField(name) }); } tx.commit(); ExportUtils.exportCSV(csv, response, "exact"); return null; } catch (Exception e) { if (tx != null) tx.rollback(); throw e; } } if ("Generate SQL".equals(op)) { PrintWriter out = ExportUtils.getPlainTextWriter(response, "tp.sql"); try { TreeSet patterns = new TreeSet(TimePattern.findAll(sessionId, null)); boolean mysql = false; int line = 0; if (mysql) out.println( "INSERT INTO `timetable`.`time_pattern`(`uniqueid`, `name`, `mins_pmt`, `slots_pmt`, `nr_mtgs`, `visible`, `type`, `break_time`, `session_id`)"); else out.println("prompt Loading TIME_PATTERN..."); for (Iterator i = patterns.iterator(); i.hasNext();) { TimePattern tp = (TimePattern) i.next(); if (tp.getType() == TimePattern.sTypeExtended) continue; if (!tp.isVisible()) continue; if (mysql) { if (line == 0) out.print("VALUES"); else out.println(","); out.print(" (" + tp.getUniqueId() + ", '" + tp.getName() + "', " + tp.getMinPerMtg() + ", " + tp.getSlotsPerMtg() + ", " + tp.getNrMeetings() + ", " + (tp.isVisible() ? "1" : "0") + ", " + tp.getType() + ", " + tp.getBreakTime() + ", " + sessionId + ")"); } else { out.println( "insert into TIME_PATTERN (UNIQUEID, NAME, MINS_PMT, SLOTS_PMT, NR_MTGS, VISIBLE, TYPE, BREAK_TIME, SESSION_ID)"); out.println("values (" + tp.getUniqueId() + ", '" + tp.getName() + "', " + tp.getMinPerMtg() + ", " + tp.getSlotsPerMtg() + ", " + tp.getNrMeetings() + ", " + (tp.isVisible() ? "1" : "0") + ", " + tp.getType() + ", " + tp.getBreakTime() + ", " + sessionId + ");"); } line++; } if (mysql) { out.println(";"); } else { out.println("commit;"); out.println("prompt " + line + " records loaded"); } out.println(); line = 0; if (mysql) { out.println( "INSERT INTO `timetable`.`time_pattern_days`(`uniqueid`, `day_code`, `time_pattern_id`)"); } else { out.println("prompt Loading TIME_PATTERN_DAYS..."); } for (Iterator i = patterns.iterator(); i.hasNext();) { TimePattern tp = (TimePattern) i.next(); if (tp.getType() == TimePattern.sTypeExtended) continue; if (!tp.isVisible()) continue; for (Iterator j = tp.getDays().iterator(); j.hasNext();) { TimePatternDays d = (TimePatternDays) j.next(); if (mysql) { if (line == 0) out.print("VALUES"); else out.println(","); out.print(" (" + d.getUniqueId() + ", " + d.getDayCode() + ", " + tp.getUniqueId() + ")"); } else { out.println("insert into TIME_PATTERN_DAYS (UNIQUEID, DAY_CODE, TIME_PATTERN_ID)"); out.println("values (" + d.getUniqueId() + ", " + d.getDayCode() + ", " + tp.getUniqueId() + ");"); } line++; } } if (mysql) { out.println(";"); } else { out.println("commit;"); out.println("prompt " + line + " records loaded"); } out.println(); line = 0; if (mysql) { out.println( "INSERT INTO `timetable`.`time_pattern_time`(`uniqueid`, `start_slot`, `time_pattern_id`)"); } else { out.println("prompt Loading TIME_PATTERN_TIME..."); } for (Iterator i = patterns.iterator(); i.hasNext();) { TimePattern tp = (TimePattern) i.next(); if (tp.getType() == TimePattern.sTypeExtended) continue; if (!tp.isVisible()) continue; for (Iterator j = tp.getTimes().iterator(); j.hasNext();) { TimePatternTime t = (TimePatternTime) j.next(); if (mysql) { if (line == 0) out.print("VALUES"); else out.println(","); out.print(" (" + t.getUniqueId() + ", " + t.getStartSlot() + ", " + tp.getUniqueId() + ")"); } else { out.println( "insert into TIME_PATTERN_TIME (UNIQUEID, START_SLOT, TIME_PATTERN_ID)"); out.println("values (" + t.getUniqueId() + ", " + t.getStartSlot() + ", " + tp.getUniqueId() + ");"); } line++; } } if (mysql) { out.println(";"); } else { out.println("commit;"); out.println("prompt " + line + " records loaded"); } out.flush(); out.close(); out = null; return null; } catch (Exception e) { throw e; } finally { if (out != null) out.close(); } } if ("Assign Departments".equals(op)) { Transaction tx = null; PrintWriter out = null; HashSet refresh = new HashSet(); try { org.hibernate.Session hibSession = (new TimePatternDAO()).getSession(); if (hibSession.getTransaction() == null || !hibSession.getTransaction().isActive()) tx = hibSession.beginTransaction(); File file = ApplicationProperties.getTempFile("assigndept", "txt"); out = new PrintWriter(new FileWriter(file)); TreeSet patterns = new TreeSet(TimePattern.findAll(sessionId, null)); for (Iterator i = patterns.iterator(); i.hasNext();) { TimePattern tp = (TimePattern) i.next(); if (tp.getType().intValue() != TimePattern.sTypeExtended) continue; out.println("Checking " + tp.getName() + " ..."); List timePrefs = hibSession.createQuery( "select distinct p from TimePref as p inner join p.timePattern as tp where tp.uniqueId=:uniqueid") .setInteger("uniqueid", tp.getUniqueId().intValue()).list(); HashSet depts = new HashSet(); for (Iterator j = timePrefs.iterator(); j.hasNext();) { TimePref timePref = (TimePref) j.next(); if (timePref.getOwner() instanceof Class_) { Class_ c = (Class_) timePref.getOwner(); if (!c.getSession().getUniqueId().equals(sessionId)) continue; depts.add(c.getManagingDept()); } else if (timePref.getOwner() instanceof SchedulingSubpart) { SchedulingSubpart s = (SchedulingSubpart) timePref.getOwner(); if (!s.getSession().getUniqueId().equals(sessionId)) continue; depts.add(s.getManagingDept()); } } out.println(" -- departments: " + depts); boolean added = false; for (Iterator j = depts.iterator(); j.hasNext();) { Department d = (Department) j.next(); if (d.isExternalManager().booleanValue()) { /* if (tp.getDepartments().contains(d)) { tp.getDepartments().remove(d); d.getTimePatterns().remove(tp); hibSession.saveOrUpdate(d); out.println(" -- department "+d+" removed from "+tp.getName()); added=true; } */ continue; } if (!tp.getDepartments().contains(d)) { tp.getDepartments().add(d); d.getTimePatterns().add(tp); hibSession.saveOrUpdate(d); out.println(" -- department " + d + " added to " + tp.getName()); added = true; } } if (added) { hibSession.saveOrUpdate(tp); refresh.add(tp); } } out.flush(); out.close(); out = null; request.setAttribute(Constants.REQUEST_OPEN_URL, "temp/" + file.getName()); tx.commit(); for (Iterator i = refresh.iterator(); i.hasNext();) { hibSession.refresh(i.next()); } } catch (Exception e) { if (tx != null) tx.rollback(); throw e; } finally { if (out != null) out.close(); } myForm.load(null, null); myForm.setOp("List"); } if ("Export CSV".equals(op)) { Transaction tx = null; try { org.hibernate.Session hibSession = (new TimePatternDAO()).getSession(); if (hibSession.getTransaction() == null || !hibSession.getTransaction().isActive()) tx = hibSession.beginTransaction(); CSVFile csv = new CSVFile(); csv.setHeader( new CSVFile.CSVField[] { new CSVFile.CSVField("Name"), new CSVFile.CSVField("Type"), new CSVFile.CSVField("Visible"), new CSVFile.CSVField("Used"), new CSVFile.CSVField("NbrMtgs"), new CSVFile.CSVField("MinPerMtg"), new CSVFile.CSVField("SlotsPerMtg"), new CSVFile.CSVField("BreakTime"), new CSVFile.CSVField("Days"), new CSVFile.CSVField("Times"), new CSVFile.CSVField("Departments"), new CSVFile.CSVField("Classes") }); TreeSet patterns = new TreeSet(TimePattern.findAll(sessionId, null)); for (Iterator i = patterns.iterator(); i.hasNext();) { TimePattern tp = (TimePattern) i.next(); String deptStr = ""; TreeSet depts = new TreeSet(tp.getDepartments()); for (Iterator j = depts.iterator(); j.hasNext();) { Department d = (Department) j.next(); if (!d.getSessionId().equals(sessionId)) continue; if (deptStr.length() > 0) { deptStr += ", "; } deptStr += d.getShortLabel().trim(); } String classStr = ""; if (tp.getType().intValue() != TimePattern.sTypeStandard) { List timePrefs = hibSession.createQuery( "select distinct p.owner from TimePref as p inner join p.timePattern as tp where tp.uniqueId=:uniqueid") .setInteger("uniqueid", tp.getUniqueId().intValue()).list(); TreeSet allOwners = new TreeSet(); for (Iterator j = timePrefs.iterator(); j.hasNext();) { Object owner = j.next(); if (owner instanceof Class_) { Class_ c = (Class_) owner; if (!c.getSession().getUniqueId().equals(sessionId)) continue; allOwners.add(c.getClassLabel()); } else if (owner instanceof SchedulingSubpart) { SchedulingSubpart s = (SchedulingSubpart) owner; if (!s.getSession().getUniqueId().equals(sessionId)) continue; allOwners.add(s.getSchedulingSubpartLabel()); } } if (allOwners.isEmpty()) { classStr += "not used"; } else { int idx = 0; classStr += allOwners.size() + " / "; for (Iterator j = allOwners.iterator(); j.hasNext(); idx++) { if (idx == 20) { classStr += "..."; break; } classStr += (String) j.next(); if (j.hasNext()) classStr += ", "; } } } csv.addLine(new CSVFile.CSVField[] { new CSVFile.CSVField(tp.getName()), new CSVFile.CSVField(TimePattern.sTypes[tp.getType().intValue()]), new CSVFile.CSVField(tp.isVisible().booleanValue() ? "Y" : "N"), new CSVFile.CSVField(tp.isEditable() ? "N" : "Y"), new CSVFile.CSVField(tp.getNrMeetings()), new CSVFile.CSVField(tp.getMinPerMtg()), new CSVFile.CSVField(tp.getSlotsPerMtg()), new CSVFile.CSVField(tp.getBreakTime()), new CSVFile.CSVField(TimePatternEditForm.dayCodes2str(tp.getDays(), ", ")), new CSVFile.CSVField(TimePatternEditForm.startSlots2str(tp.getTimes(), ", ")), new CSVFile.CSVField(deptStr), new CSVFile.CSVField(classStr) }); } tx.commit(); ExportUtils.exportCSV(csv, response, "timePatterns"); return null; } catch (Exception e) { if (tx != null) tx.rollback(); throw e; } } if ("Add Time Pattern".equals(op)) { myForm.load(null, null); myForm.setOp("Save"); } if ("List".equals(myForm.getOp())) { // Read all existing settings and store in request getTimePatterns(request, sessionId); return mapping.findForward("list"); } String example = myForm.getExample(); if (example != null) { request.setAttribute("TimePatterns.example", example); } return mapping.findForward(myForm.getUniqueId().longValue() < 0 ? "add" : "edit"); } catch (Exception e) { Debug.error(e); throw e; } } private void getTimePatterns(HttpServletRequest request, Long sessionId) throws Exception { WebTable.setOrder(sessionContext, "timePatterns.ord", request.getParameter("ord"), 1); // Create web table instance WebTable webTable = new WebTable(10, null, "timePatternEdit.do?ord=%%", new String[] { "Name", "Type", "Used", "NrMtgs", "MinPerMtg", "SlotsPerMtg", "Break Time", "Days", "Times", "Departments" }, new String[] { "left", "left", "left", "left", "left", "left", "left", "left", "left", "left" }, null); List<TimePattern> patterns = TimePattern.findAll(sessionId, null); if (patterns.isEmpty()) { webTable.addLine(null, new String[] { "No time pattern defined for this academic initiative and term." }, null, null); } Set used = TimePattern.findAllUsed(sessionId); for (TimePattern pattern : patterns) { String onClick = "onClick=\"document.location='timePatternEdit.do?op=Edit&id=" + pattern.getUniqueId() + "';\""; String deptStr = ""; String deptCmp = ""; for (Iterator i = pattern.getDepartments(sessionId).iterator(); i.hasNext();) { Department d = (Department) i.next(); deptStr += d.getManagingDeptAbbv().trim(); deptCmp += d.getDeptCode(); if (i.hasNext()) { deptStr += ", "; deptCmp += ","; } } boolean isUsed = used.contains(pattern); webTable.addLine(onClick, new String[] { (pattern.isVisible() ? "" : "<font color='grey'>") + "<a name='" + pattern.getUniqueId() + "'>" + pattern.getName().replaceAll(" ", " ") + "</a>" + (pattern.isVisible() ? "" : "</font>"), (pattern.isVisible() ? "" : "<font color='gray'>") + TimePattern.sTypes[pattern.getType().intValue()].replaceAll(" ", " ") + (pattern.isVisible() ? "" : "</font>"), (isUsed ? "<IMG border='0' title='This time pattern is being used.' alt='Default' align='absmiddle' src='images/accept.png'>" : ""), (pattern.isVisible() ? "" : "<font color='gray'>") + pattern.getNrMeetings().toString() + (pattern.isVisible() ? "" : "</font>"), (pattern.isVisible() ? "" : "<font color='gray'>") + pattern.getMinPerMtg().toString() + (pattern.isVisible() ? "" : "</font>"), (pattern.isVisible() ? "" : "<font color='gray'>") + pattern.getSlotsPerMtg().toString() + (pattern.isVisible() ? "" : "</font>"), (pattern.isVisible() ? "" : "<font color='gray'>") + pattern.getBreakTime().toString() + (pattern.isVisible() ? "" : "</font>"), (pattern.isVisible() ? "" : "<font color='gray'>") + TimePatternEditForm.dayCodes2str(pattern.getDays(), ", ") + (pattern.isVisible() ? "" : "</font>"), (pattern.isVisible() ? "" : "<font color='gray'>") + TimePatternEditForm.startSlots2str(pattern.getTimes(), ", ") + (pattern.isVisible() ? "" : "</font>"), (pattern.isVisible() ? "" : "<font color='gray'>") + deptStr + (pattern.isVisible() ? "" : "</font>") }, new Comparable[] { pattern.getName(), pattern.getType(), (isUsed ? "0" : "1"), pattern.getNrMeetings(), pattern.getMinPerMtg(), pattern.getSlotsPerMtg(), pattern.getBreakTime(), TimePatternEditForm.dayCodes2str(pattern.getDays(), ", "), TimePatternEditForm.startSlots2str(pattern.getTimes(), ", "), deptCmp }); } request.setAttribute("TimePatterns.table", webTable.printTable(WebTable.getOrder(sessionContext, "timePatterns.ord"))); } }