You can subscribe to this list here.
| 2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(275) |
Jul
(81) |
Aug
(19) |
Sep
(26) |
Oct
(190) |
Nov
(118) |
Dec
(16) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2008 |
Jan
(9) |
Feb
(318) |
Mar
(251) |
Apr
(354) |
May
(209) |
Jun
(261) |
Jul
(226) |
Aug
(136) |
Sep
(156) |
Oct
(30) |
Nov
(5) |
Dec
(13) |
| 2009 |
Jan
(26) |
Feb
(35) |
Mar
(63) |
Apr
(21) |
May
(26) |
Jun
(33) |
Jul
(55) |
Aug
(71) |
Sep
(23) |
Oct
(40) |
Nov
(18) |
Dec
(13) |
| 2010 |
Jan
(17) |
Feb
(98) |
Mar
(39) |
Apr
(25) |
May
(107) |
Jun
(257) |
Jul
(270) |
Aug
(206) |
Sep
(237) |
Oct
(187) |
Nov
(302) |
Dec
(187) |
| 2011 |
Jan
(63) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:03
|
Update of /cvsroot/unitime/UniTime/Documentation/Database/Oracle/Utils In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/Documentation/Database/Oracle/Utils Modified Files: Set Managing Depts.sql Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) Index: Set Managing Depts.sql =================================================================== RCS file: /cvsroot/unitime/UniTime/Documentation/Database/Oracle/Utils/Set Managing Depts.sql,v retrieving revision 1.3 retrieving revision 1.4 diff -C2 -d -r1.3 -r1.4 *** Set Managing Depts.sql 17 Jun 2008 21:25:04 -0000 1.3 --- Set Managing Depts.sql 1 Dec 2010 11:10:55 -0000 1.4 *************** *** 1,9 **** /* ! * UniTime 3.1 (University Timetabling Application) ! * Copyright (C) 2008, UniTime LLC * * 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 2 of the License, or * (at your option) any later version. * --- 1,9 ---- /* ! * UniTime 3.2 (University Timetabling Application) ! * Copyright (C) 2008 - 2010, UniTime LLC * * 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. * *************** *** 14,19 **** * * You should have received a copy of the GNU General Public License along ! * with this program; if not, write to the Free Software Foundation, Inc., ! * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ --- 14,19 ---- * * You should have received a copy of the GNU General Public License along ! * with this program. If not, see <http://www.gnu.org/licenses/>. ! * */ |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:03
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/reports In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/reports Modified Files: PdfLegacyReport.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) Index: PdfLegacyReport.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/reports/PdfLegacyReport.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** PdfLegacyReport.java 25 Jun 2008 16:22:17 -0000 1.9 --- PdfLegacyReport.java 1 Dec 2010 11:10:55 -0000 1.10 *************** *** 1,2 **** --- 1,21 ---- + /* + * UniTime 3.2 (University Timetabling Application) + * Copyright (C) 2008 - 2010, 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.reports; *************** *** 10,27 **** import org.unitime.timetable.util.Constants; ! import com.lowagie.text.Document; ! import com.lowagie.text.DocumentException; ! import com.lowagie.text.FontFactory; ! import com.lowagie.text.PageSize; ! import com.lowagie.text.Paragraph; ! import com.lowagie.text.pdf.PdfWriter; public class PdfLegacyReport { protected int iNrChars = 133; protected int iNrLines = 50; - private File iFile = null; private FileOutputStream iOut = null; private Document iDoc = null; - private PdfWriter iWriter = null; private StringBuffer iBuffer = new StringBuffer(); private PrintWriter iPrint = null; --- 29,47 ---- import org.unitime.timetable.util.Constants; ! import com.itextpdf.text.Document; ! import com.itextpdf.text.DocumentException; ! import com.itextpdf.text.FontFactory; ! import com.itextpdf.text.PageSize; ! import com.itextpdf.text.Paragraph; ! import com.itextpdf.text.pdf.PdfWriter; + /** + * @author Tomas Muller + */ public class PdfLegacyReport { protected int iNrChars = 133; protected int iNrLines = 50; private FileOutputStream iOut = null; private Document iDoc = null; private StringBuffer iBuffer = new StringBuffer(); private PrintWriter iPrint = null; *************** *** 36,40 **** private boolean iEmpty = true; - private int iMode = 0; public static final int sModeNormal = 0; --- 56,59 ---- *************** *** 43,47 **** public PdfLegacyReport(int mode, File file, String title, String title2, String subject, String session) throws IOException, DocumentException{ - iFile = file; iTitle = title; iTitle2 = title2; --- 62,65 ---- *************** *** 61,65 **** iDoc = new Document(mode==sModeLedger?PageSize.LEDGER.rotate():PageSize.LETTER.rotate()); ! iWriter = PdfWriter.getInstance(iDoc, iOut); iDoc.addTitle(iTitle); --- 79,83 ---- iDoc = new Document(mode==sModeLedger?PageSize.LEDGER.rotate():PageSize.LETTER.rotate()); ! PdfWriter.getInstance(iDoc, iOut); iDoc.addTitle(iTitle); *************** *** 186,190 **** iPrint.print(iBuffer); } else { ! Paragraph p = new Paragraph(iBuffer.toString(), FontFactory.getFont(FontFactory.COURIER, 9)); p.setLeading(9.5f); //was 13.5f iDoc.add(p); --- 204,209 ---- iPrint.print(iBuffer); } else { ! //FIXME: For some reason when a line starts with space, the line is shifted by one space in the resulting PDF (when using iText 5.0.2) ! Paragraph p = new Paragraph(iBuffer.toString().replace("\n ", "\n "), FontFactory.getFont(FontFactory.COURIER, 9)); p.setLeading(9.5f); //was 13.5f iDoc.add(p); |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:03
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/resources/logos In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/resources/logos Added Files: unitime.png Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: unitime.png --- (This appears to be a binary file; contents omitted.) |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:02
|
Update of /cvsroot/unitime/UniTime/WebContent/layouts In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/WebContent/layouts Modified Files: pageLayout.jsp Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) Index: pageLayout.jsp =================================================================== RCS file: /cvsroot/unitime/UniTime/WebContent/layouts/pageLayout.jsp,v retrieving revision 1.11 retrieving revision 1.12 diff -C2 -d -r1.11 -r1.12 *** pageLayout.jsp 11 Feb 2010 12:32:09 -0000 1.11 --- pageLayout.jsp 1 Dec 2010 11:10:54 -0000 1.12 *************** *** 1,9 **** <%-- ! * UniTime 3.1 (University Timetabling Application) ! * Copyright (C) 2008, UniTime LLC * * 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 2 of the License, or * (at your option) any later version. * --- 1,9 ---- <%-- ! * UniTime 3.2 (University Timetabling Application) ! * Copyright (C) 2008 - 2010, UniTime LLC * * 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. * *************** *** 14,22 **** * * You should have received a copy of the GNU General Public License along ! * with this program; if not, write to the Free Software Foundation, Inc., ! * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. --%> ! <%@ page language="java" pageEncoding="utf-8" contentType="text/html;charset=utf-8"%> ! <%@ page errorPage="/error.jsp" %> <%@ page import="java.text.NumberFormat" %> <%@ page import="net.sf.cpsolver.ifs.util.JProf" %> --- 14,21 ---- * * You should have received a copy of the GNU General Public License along ! * with this program. If not, see <http://www.gnu.org/licenses/>. ! * --%> ! <%@ page language="java" pageEncoding="utf-8" contentType="text/html;charset=utf-8" errorPage="/error.jsp"%> <%@ page import="java.text.NumberFormat" %> <%@ page import="net.sf.cpsolver.ifs.util.JProf" %> *************** *** 32,35 **** --- 31,35 ---- <tiles:importAttribute name="checkAdmin" scope="request"/> <tiles:importAttribute name="checkAccessLevel" scope="request"/> + <tiles:importAttribute name="showMenu" scope="request"/> <logic:equal name="checkLogin" value="true"> *************** *** 52,86 **** <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html> ! <HEAD> ! <META http-equiv="pragma" content="no-cache"> ! <META http-equiv="cache-control" content="no-cache"> ! <META http-equiv="expires" content="0"> ! <STYLE type="text/css">@import url(<%=basePath%>scripts/jscalendar/calendar-blue.css);</STYLE> ! <LINK rel="stylesheet" type="text/css" href="<%=basePath%>styles/timetabling.css"> <tt:hasProperty name="tmtbl.custom.css"> ! <LINK rel="stylesheet" type="text/css" href="<%=basePath%>%tmtbl.custom.css%" /> </tt:hasProperty> <link rel="shortcut icon" href="<%=basePath%>images/timetabling.ico" /> ! <TITLE><tiles:getAsString name="title" /></TITLE> ! <SCRIPT language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/loading.js"></SCRIPT> ! <SCRIPT language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/validator.js"></SCRIPT> ! <SCRIPT language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/jscalendar/calendar.js"></SCRIPT> ! <SCRIPT language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/jscalendar/lang/calendar-en.js"></SCRIPT> ! <SCRIPT language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/jscalendar/calendar-setup.js"></SCRIPT> ! <SCRIPT language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/select.js"></SCRIPT> ! <SCRIPT language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/rtt.js"></SCRIPT> ! <SCRIPT language="javascript"><!-- ! function doLoad() { ! // Trick 1 to prevent use of back button ! if(window.history.forward(1) != null) ! window.history.forward(1); ! ! // Focus on frame ! self.focus(); ! } ! // --></SCRIPT> ! </HEAD> ! <BODY class="bodyStyle" <tiles:getAsString name="onLoadFunction" />> ! <tt:hasProperty name="tmtbl.global.warn"> <table width='100%' border='0' cellpadding='3' cellspacing='0'><tr><td class="reqGlobalWarn" width='5'> </td><td class="reqGlobalWarn" > <tt:property name="tmtbl.global.warn"/> --- 52,95 ---- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html:html> ! <head> ! <meta http-equiv="pragma" content="no-cache"> ! <meta http-equiv="cache-control" content="no-cache"> ! <meta http-equiv="expires" content="0"> ! <meta http-equiv="X-UA-Compatible" content="IE=8,chrome=1"> ! <style type="text/css">@import url(<%=basePath%>scripts/jscalendar/calendar-blue.css);</style> ! <link type="text/css" rel="stylesheet" href="<%=basePath%>unitime/gwt/standard/standard.css"> ! <link type="text/css" rel="stylesheet" href="<%=basePath%>styles/unitime.css"> ! <link rel="stylesheet" type="text/css" href="<%=basePath%>styles/timetabling.css"> <tt:hasProperty name="tmtbl.custom.css"> ! <link rel="stylesheet" type="text/css" href="<%=basePath%>%tmtbl.custom.css%" /> </tt:hasProperty> <link rel="shortcut icon" href="<%=basePath%>images/timetabling.ico" /> ! <title>UniTime 3.2| <tiles:getAsString name="title" /></title> ! <script language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/loading.js"></script> ! <script language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/validator.js"></script> ! <script language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/jscalendar/calendar.js"></script> ! <script language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/jscalendar/lang/calendar-en.js"></script> ! <script language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/jscalendar/calendar-setup.js"></script> ! <script language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/select.js"></script> ! <script language="JavaScript" type="text/javascript" src="<%=basePath%>scripts/rtt.js"></script> ! <script type="text/javascript" language="javascript" src="<%=basePath%>unitime/unitime.nocache.js">--</script> ! </head> ! <body class="unitime-Body" <tiles:getAsString name="onLoadFunction" />> ! <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex="-1" style="position:absolute;width:0;height:0;border:0"></iframe> ! <iframe src="javascript:''" id="__printingFrame" tabIndex="-1" style="position:absolute;width:0;height:0;border:0"></iframe> ! ! <logic:equal name="showMenu" value="true"> ! <tt:notHasProperty name="unitime.menu.style" user="true"> ! <span id='UniTimeGWT:DynamicTopMenu' style="display: none;" ></span> ! </tt:notHasProperty> ! <tt:propertyEquals name="unitime.menu.style" user="true" value="Dynamic On Top"> ! <span id='UniTimeGWT:DynamicTopMenu' style="display: none;" ></span> ! </tt:propertyEquals> ! <tt:propertyEquals name="unitime.menu.style" user="true" value="Static On Top"> ! <span id='UniTimeGWT:TopMenu' style="display: none;" ></span> ! </tt:propertyEquals> ! </logic:equal> ! ! <tt:hasProperty name="tmtbl.global.warn"> <table width='100%' border='0' cellpadding='3' cellspacing='0'><tr><td class="reqGlobalWarn" width='5'> </td><td class="reqGlobalWarn" > <tt:property name="tmtbl.global.warn"/> *************** *** 103,111 **** </table> <% } %> - <% if (request.getAttribute(Constants.REQUEST_WARN)!=null) { %> - <table width='100%' border='0' cellpadding='3' cellspacing='0'><tr><td class="reqWarn" width='5'> </td><td class="reqWarn" > - <%=request.getAttribute(Constants.REQUEST_WARN)%> - </td></tr></table> - <% } %> <% if (session.getAttribute(Constants.REQUEST_WARN)!=null) { %> <table width='100%' border='0' cellpadding='3' cellspacing='0'><tr><td class="reqWarn" width='5'> </td><td class="reqWarn" > --- 112,115 ---- *************** *** 114,122 **** <% session.removeAttribute(Constants.REQUEST_WARN); } %> - <% if (request.getAttribute(Constants.REQUEST_MSSG)!=null) { %> - <table width='100%' border='0' cellpadding='3' cellspacing='0'><tr><td class="reqMsg" width='5'> </td><td class="reqMsg" > - <%=request.getAttribute(Constants.REQUEST_MSSG)%> - </td></tr></table> - <% } %> <% if (session.getAttribute(Constants.REQUEST_MSSG)!=null) { %> <table width='100%' border='0' cellpadding='3' cellspacing='0'><tr><td class="reqMsg" width='5'> </td><td class="reqMsg" > --- 118,121 ---- *************** *** 129,146 **** <tt:solver-warnings/> </logic:equal> ! <DIV id="contentMain"> <tiles:importAttribute/> <tiles:importAttribute name="title" scope="request"/> <tiles:importAttribute name="showNavigation" scope="request"/> ! <tiles:importAttribute name="helpFile" scope="request"/> ! <tiles:insert attribute="header"> ! <tiles:put name="helpFile" value="${helpFile}"/> ! <tiles:put name="showNavigation" value="${showNavigation}"/> ! </tiles:insert> ! <BLOCKQUOTE> ! <tiles:insert attribute="body"> ! <tiles:put name="body2" value="${body2}"/> ! <tiles:put name="action2" value="${action2}"/> ! </tiles:insert> <% --- 128,209 ---- <tt:solver-warnings/> </logic:equal> ! <tiles:importAttribute/> <tiles:importAttribute name="title" scope="request"/> <tiles:importAttribute name="showNavigation" scope="request"/> ! <div id="contentMain"> ! <table align="center"> ! <tr> ! <td valign="top" rowspan="2"> ! <logic:equal name="showMenu" value="true"> ! <tt:propertyEquals name="unitime.menu.style" user="true" value="Stack On Side"> ! <span id='UniTimeGWT:SideStackMenu' style="display: none;" ></span> ! </tt:propertyEquals> ! <tt:propertyEquals name="unitime.menu.style" user="true" value="Tree On Side"> ! <span id='UniTimeGWT:SideTreeMenu' style="display: none;" ></span> ! </tt:propertyEquals> ! </logic:equal> ! </td> ! <td valign="top"> ! <table class="unitime-Page" width="100%"> ! <tr><td> ! <table class="unitime-MainTable" cellpadding="2" cellspacing="0" width="100%"> ! <tr><td rowspan="3"><a href='main.jsp' tabIndex="-1"><img src="images/unitime.png" border="0"/></a></td> ! <td nowrap="nowrap" width="100%" align="right" valign="middle" class="unitime-Title" style="padding-right: 20px;"> ! <span id='UniTimeGWT:Title'><bean:write name="title" scope="request"/></span> ! </td> ! </tr><tr> ! <td width="100%" align="right" valign="middle" nowrap="nowrap"> ! <logic:equal name="showMenu" value="true"> ! <span id='UniTimeGWT:Header'></span> ! </logic:equal> ! </td> ! </tr><tr> ! <td width="100%" align="left" valign="middle"> ! <span id='UniTimeGWT:TitlePanel'> ! <tiles:insert attribute="header"> ! <tiles:put name="showNavigation" value="${showNavigation}"/> ! </tiles:insert> ! </span> ! </td> ! </tr> ! </table> ! </td></tr><tr><td style="min-width: 800px"> ! <span id='UniTimeGWT:Content'> ! <tiles:insert attribute="body"> ! <tiles:put name="body2" value="${body2}"/> ! <tiles:put name="action2" value="${action2}"/> ! </tiles:insert> ! </span> ! </td></tr></table> ! </td></tr><tr><td valign="top"> ! <table class="unitime-Footer"> ! <tr> ! <td width="33%" align="left" class="unitime-FooterText"><span id="UniTimeGWT:Version"></span> ! <logic:notEmpty scope="request" name="TimeStamp"> ! <% ! double endTime = JProf.currentTimeSec(); ! double startTime = ((Double)request.getAttribute("TimeStamp")).doubleValue(); ! double diff = endTime - startTime; ! NumberFormat nf = NumberFormat.getInstance(); ! nf.setMaximumFractionDigits(2); ! %> ! Page generated in <%=nf.format(diff)%> sec. ! </logic:notEmpty> ! </td> ! <!-- WARNING: Changing or removing the copyright notice will violate the license terms. If you need a different licensing, please contact us at su...@un... --> ! <td width="34%" align="center" class="unitime-FooterText"><tt:copy/></td> ! <td width="33%" align="right" class="unitime-FooterText"><tt:registration/></td> ! </tr> ! <tt:hasProperty name="tmtbl.page.disclaimer"> ! <tr> ! <td colspan="3" class="unitime-Disclaimer"> ! <tt:property name="tmtbl.page.disclaimer"/> ! </td> ! </tr> ! </tt:hasProperty> ! </table> ! </td></tr></table> ! </div> <% *************** *** 149,154 **** if (session.getAttribute("userTrace")==null) { sb = "User: " + Web.getUser(session).getLogin() + "\nPage: " + request.getAttribute("title"); ! } ! else { sb = (String) session.getAttribute("userTrace"); sb += "\n" --- 212,216 ---- if (session.getAttribute("userTrace")==null) { sb = "User: " + Web.getUser(session).getLogin() + "\nPage: " + request.getAttribute("title"); ! } else { sb = (String) session.getAttribute("userTrace"); sb += "\n" *************** *** 166,211 **** catch (Exception e) { } - %> - - <logic:notEmpty scope="request" name="TimeStamp"> - <% - //long endTime = new Date().getTime(); - //float diff = ((float)(endTime - beginTime))/1000.0f; - double endTime = JProf.currentTimeSec(); - double startTime = ((Double)request.getAttribute("TimeStamp")).doubleValue(); - double diff = endTime - startTime; - NumberFormat nf = NumberFormat.getInstance(); - nf.setMaximumFractionDigits(2); %> ! <table border='0' class='font8Gray' width='95%'> ! <tr> ! <td width='33%'> </td> ! <td width='33%' align='center' ! onMouseOver="this.style.cursor='hand';this.style.cursor='pointer';" ! onClick="window.open('http://www.unitime.org','unitime','width=1000,height=600,resizable=yes,scrollbars=yes,toolbar=yes,location=yes,directories=no,status=yes,menubar=no,copyhistory=no').focus();" ! > ! © 2008 UniTime LLC ! <%-- ! [<span style='text-decoration: underline; color: #606060;' onclick="window.open('http://wiki.unitime.org/UniTime_Disclaimer','wikiHelp','width=1000,height=600,resizable=yes,scrollbars=yes,toolbar=yes,location=yes,directories=no,status=yes,menubar=no,copyhistory=no').focus(); event.cancelBubble=true;">disclaimer</span>] ! --%> ! </td> ! <td width='33%' align='right'>Page generated in <%=nf.format(diff)%> sec.</td> ! </tr> ! </table> ! </logic:notEmpty> ! </BLOCKQUOTE> ! </DIV> ! ! <DIV id="loadingMain" style="visibility:hidden;display:none"> ! <TABLE width="100%" height="100%" align="center" cellpadding="0" cellspacing="0" border="0"> ! <TR> ! <TD valign="middle" align="center"> <font class="WelcomeRowHeadNoLine">Loading</font><br> <br> ! <IMG align="middle" vspace="5" border="0" src="images/loading.gif"> ! </TD> ! </TR> ! </TABLE> ! </DIV> ! ! </BODY> </html:html> --- 228,242 ---- catch (Exception e) { } %> ! <div id="loadingMain" style="visibility:hidden;display:none"> ! <table width="100%" height="100%" align="center" cellpadding="0" cellspacing="0" border="0"> ! <tr> ! <td valign="middle" align="center"> <font class="WelcomeRowHeadNoLine">Loading</font><br> <br> ! <img align="middle" vspace="5" border="0" src="images/loading.gif"> ! </td> ! </tr> ! </table> ! </div> ! </body> </html:html> |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:02
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt Added Files: UniTimeDev.gwt.xml UniTime.gwt.xml Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: UniTimeDev.gwt.xml --- <?xml version="1.0" encoding="UTF-8"?> <!-- * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, UniTime LLC * * 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/>. * --> <module rename-to='unitime'> <inherits name='org.unitime.timetable.gwt.UniTime' /> <set-property name="user.agent" value="gecko1_8" /> </module> --- NEW FILE: UniTime.gwt.xml --- <?xml version="1.0" encoding="UTF-8"?> <!-- * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, UniTime LLC * * 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/>. * --> <module rename-to='unitime'> <!-- Inherit the core Web Toolkit stuff. --> <inherits name='com.google.gwt.user.User' /> <inherits name='com.google.gwt.user.UserAgent' /> <inherits name="com.google.gwt.resources.Resources" /> <inherits name="com.google.gwt.i18n.I18N"/> <!-- Inherit the default GWT style sheet. You can change --> <!-- the theme of your GWT application by uncommenting --> <!-- any one of the following lines. --> <inherits name='com.google.gwt.user.theme.standard.StandardResources' /> <!-- <inherits name='com.google.gwt.user.theme.chrome.Chrome'/> --> <!-- <inherits name='com.google.gwt.user.theme.dark.Dark'/> --> <!-- Other module inherits --> <!-- Specify the app entry point class. --> <entry-point class='org.unitime.timetable.gwt.client.Client' /> <!-- Specify the paths for translatable code --> <source path='client' /> <source path='shared' /> <source path='resources' /> <source path='services' /> </module> |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:02
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable Modified Files: ApplicationProperties.java InitServlet.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) Index: InitServlet.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/InitServlet.java,v retrieving revision 1.5 retrieving revision 1.6 diff -C2 -d -r1.5 -r1.6 *** InitServlet.java 28 May 2010 15:34:56 -0000 1.5 --- InitServlet.java 1 Dec 2010 11:10:54 -0000 1.6 *************** *** 1,10 **** /* ! * UniTime 3.1 (University Timetabling Application) ! * Copyright (C) 2008, 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 2 of the License, or * (at your option) any later version. * --- 1,10 ---- /* ! * UniTime 3.2 (University Timetabling Application) ! * Copyright (C) 2008 - 2010, 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. * *************** *** 15,20 **** * * You should have received a copy of the GNU General Public License along ! * with this program; if not, write to the Free Software Foundation, Inc., ! * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.unitime.timetable; --- 15,20 ---- * * 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; *************** *** 28,31 **** --- 28,32 ---- import org.unitime.timetable.model.dao._RootDAO; import org.unitime.timetable.solver.remote.SolverRegisterService; + import org.unitime.timetable.util.Constants; import org.unitime.timetable.util.RoomAvailability; import org.unitime.timetable.util.queue.QueueProcessor; *************** *** 35,39 **** * Application Initialization Servlet * @version 1.0 ! * @author Heston Fernandes */ --- 36,40 ---- * Application Initialization Servlet * @version 1.0 ! * @author Heston Fernandes, Tomas Muller */ *************** *** 44,48 **** */ private static final long serialVersionUID = 3258415014804142137L; ! /** * Initializes the application --- 45,51 ---- */ private static final long serialVersionUID = 3258415014804142137L; ! ! private static Exception sInitializationException = null; ! /** * Initializes the application *************** *** 50,79 **** public void init() throws ServletException { ! logMessage("******* Initializing Timetabling Application : START *******"); super.init(); try { ! ! logMessage(" - Initializing Debugger ... "); Debug.init(ApplicationProperties.getProperties()); ! logMessage(" - Initializing Hibernate ... "); _RootDAO.initialize(); ! logMessage(" - Initializing Solver Register ... "); SolverRegisterService.startService(); SolverRegisterService.addShutdownHook(); if (RoomAvailability.getInstance()!=null) { ! logMessage(" - Initializing Room Availability Service ... "); RoomAvailability.getInstance().startService(); } ! logMessage("******* Timetabling Application : Initializing DONE *******"); ! } ! catch (Exception e) { ! logError("Servlet Initialization Failed : " + e.getMessage()); ! e.printStackTrace(); } } --- 53,84 ---- public void init() throws ServletException { ! Debug.info("******* UniTime " + (Constants.VERSION + "." + Constants.BLD_NUMBER).replace("@build.number@", "?") + ! " build on " + Constants.REL_DATE.replace("@build.date@", "?") + " is starting up *******"); super.init(); try { ! ! Debug.info(" - Initializing Logging ... "); Debug.init(ApplicationProperties.getProperties()); ! Debug.info(" - Initializing Hibernate ... "); _RootDAO.initialize(); ! Debug.info(" - Initializing Solver Register ... "); SolverRegisterService.startService(); SolverRegisterService.addShutdownHook(); if (RoomAvailability.getInstance()!=null) { ! Debug.info(" - Initializing Room Availability Service ... "); RoomAvailability.getInstance().startService(); } ! Debug.info("******* UniTime " + (Constants.VERSION + "." + Constants.BLD_NUMBER).replace("@build.number@", "?") + ! " build on " + Constants.REL_DATE.replace("@build.date@", "?") + " initialized successfully *******"); ! ! } catch (Exception e) { ! Debug.error("UniTime Initialization Failed : " + e.getMessage(), e); ! sInitializationException = e; } } *************** *** 85,93 **** try { ! logMessage("******* Shutting down Timetabling Application *******"); super.destroy(); ! logMessage(" - Stopping Solver Register ... "); SolverRegisterService.stopService(); try { --- 90,99 ---- try { ! Debug.info("******* UniTime " + (Constants.VERSION + "." + Constants.BLD_NUMBER).replace("@build.number@", "?") + ! " build on " + Constants.REL_DATE.replace("@build.date@", "?") + " is going down *******"); super.destroy(); ! Debug.info(" - Stopping Solver Register ... "); SolverRegisterService.stopService(); try { *************** *** 100,104 **** if (RoomAvailability.getInstance()!=null) { ! logMessage(" - Stopping Room Availability Service ... "); RoomAvailability.getInstance().stopService(); } --- 106,110 ---- if (RoomAvailability.getInstance()!=null) { ! Debug.info(" - Stopping Room Availability Service ... "); RoomAvailability.getInstance().stopService(); } *************** *** 106,116 **** QueueProcessor.stopProcessor(); ! logMessage("******* Timetabling Application : Shut down DONE *******"); } catch (Exception e) { ! Debug.error(e); if (e instanceof RuntimeException) throw (RuntimeException)e; else ! throw new RuntimeException("Shut down failed", e); } } --- 112,123 ---- QueueProcessor.stopProcessor(); ! Debug.info("******* UniTime " + (Constants.VERSION + "." + Constants.BLD_NUMBER).replace("@build.number@", "?") + ! " shut down successfully *******"); } catch (Exception e) { ! Debug.error("UniTime Shutdown Failed : " + e.getMessage(), e); if (e instanceof RuntimeException) throw (RuntimeException)e; else ! throw new RuntimeException("UniTime Shutdown Failed : " + e.getMessage(), e); } } *************** *** 121,142 **** */ public String getServletInfo() { ! ! return "Timetabling Initialization Servlet"; ! ! } ! ! /* ! * Writes message to log ! */ ! private static void logMessage(String message) { ! Debug.info(message); ! } ! ! /* ! * Write error to log ! */ ! private static void logError(String message) { ! Debug.error(message); ! System.err.println(message); } } --- 128,134 ---- */ public String getServletInfo() { ! return "UniTime " + (Constants.VERSION + "." + Constants.BLD_NUMBER).replace("@build.number@", "?") + " Initialization Servlet"; } + + public static Exception getInitializationException() { return sInitializationException; } } Index: ApplicationProperties.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/ApplicationProperties.java,v retrieving revision 1.9 retrieving revision 1.10 diff -C2 -d -r1.9 -r1.10 *** ApplicationProperties.java 17 Jun 2008 21:24:57 -0000 1.9 --- ApplicationProperties.java 1 Dec 2010 11:10:54 -0000 1.10 *************** *** 1,10 **** /* ! * UniTime 3.1 (University Timetabling Application) ! * Copyright (C) 2008, 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 2 of the License, or * (at your option) any later version. * --- 1,10 ---- /* ! * UniTime 3.2 (University Timetabling Application) ! * Copyright (C) 2008 - 2010, 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. * *************** *** 15,20 **** * * You should have received a copy of the GNU General Public License along ! * with this program; if not, write to the Free Software Foundation, Inc., ! * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.unitime.timetable; --- 15,20 ---- * * 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; *************** *** 23,26 **** --- 23,27 ---- import java.io.FileInputStream; import java.io.IOException; + import java.net.URI; import java.net.URISyntaxException; import java.net.URL; *************** *** 205,218 **** */ public static String getBasePath() { - //Get the URL of the class location (usually in /WEB-INF/classes/...) ! java.net.URL url = ApplicationProperties.class. getProtectionDomain().getCodeSource().getLocation(); if (url==null) return null; ! //Get file and parent ! java.io.File file = new java.io.File(url.getFile()); ! java.io.File parent = file.getParentFile(); // Iterate up the folder structure till WEB-INF is encountered --- 206,224 ---- */ public static String getBasePath() { //Get the URL of the class location (usually in /WEB-INF/classes/...) ! URL url = ApplicationProperties.class. getProtectionDomain().getCodeSource().getLocation(); if (url==null) return null; ! //Get file and parent ! File file = null; ! try { ! // Try to use URI to avoid bug 4466485 on Windows (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4466485) ! file = new File(new URI(url.toString()).getPath()); ! } catch (URISyntaxException e) { ! file = new File(url.getFile()); ! } ! File parent = file.getParentFile(); // Iterate up the folder structure till WEB-INF is encountered |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:02
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/client/admin In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/client/admin Added Files: SimpleEditPage.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: SimpleEditPage.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.admin; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import org.unitime.timetable.gwt.client.page.UniTimePageLabel; import org.unitime.timetable.gwt.client.widgets.SimpleForm; import org.unitime.timetable.gwt.client.widgets.UniTimeHeaderPanel; import org.unitime.timetable.gwt.client.widgets.UniTimeTable; import org.unitime.timetable.gwt.client.widgets.UniTimeTableHeader; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.DataChangedEvent; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.DataChangedListener; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasFocus; import org.unitime.timetable.gwt.resources.GwtResources; import org.unitime.timetable.gwt.services.MenuService; import org.unitime.timetable.gwt.services.MenuServiceAsync; import org.unitime.timetable.gwt.services.SimpleEditService; import org.unitime.timetable.gwt.services.SimpleEditServiceAsync; import org.unitime.timetable.gwt.shared.SimpleEditException; import org.unitime.timetable.gwt.shared.SimpleEditInterface; import org.unitime.timetable.gwt.shared.SimpleEditInterface.Field; import org.unitime.timetable.gwt.shared.SimpleEditInterface.FieldType; import org.unitime.timetable.gwt.shared.SimpleEditInterface.ListItem; import org.unitime.timetable.gwt.shared.SimpleEditInterface.Record; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Cursor; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; /** * @author Tomas Muller */ public class SimpleEditPage extends Composite { public static final GwtResources RESOURCES = GWT.create(GwtResources.class); private final SimpleEditServiceAsync iService = GWT.create(SimpleEditService.class); private final MenuServiceAsync iMenuService = GWT.create(MenuService.class); private SimpleForm iPanel; private UniTimeHeaderPanel iHeader, iBottom; private SimpleEditInterface.Type iType; private UniTimeTable<Record> iTable; private SimpleEditInterface iData; private boolean iEditable = false; public SimpleEditPage() throws SimpleEditException { String typeString = Window.Location.getParameter("type"); if (typeString == null) throw new SimpleEditException("Edit type is not provided."); iType = SimpleEditInterface.Type.valueOf(typeString); if (iType == null) throw new SimpleEditException("Edit type not recognized."); UniTimePageLabel.getInstance().setPageName(iType.getTitle()); ClickHandler save = new ClickHandler() { @Override public void onClick(ClickEvent event) { iData.getRecords().clear(); iData.getRecords().addAll(iTable.getData()); iHeader.setMessage("Saving data..."); iService.save(iData, new AsyncCallback<SimpleEditInterface>() { @Override public void onFailure(Throwable caught) { iHeader.setErrorMessage("Save failed (" + caught.getMessage() + ")."); } @Override public void onSuccess(SimpleEditInterface result) { iData = result; iEditable = false; refreshTable(); saveOrder(); } }); } }; ClickHandler edit = new ClickHandler() { @Override public void onClick(ClickEvent event) { iEditable = true; iHeader.setEnabled("edit", false); refreshTable(); } }; ClickHandler back = new ClickHandler() { @Override public void onClick(ClickEvent event) { iEditable = false; load(); } }; iPanel = new SimpleForm(); iHeader = new UniTimeHeaderPanel(); iHeader.addButton("edit", "<u>E</u>dit", 'e', 75, edit); iHeader.addButton("save", "<u>S</u>ave", 's', 75, save); iHeader.addButton("back", "<u>B</u>ack", 'b', 75, back); iPanel.addHeaderRow(iHeader); iTable = new UniTimeTable<Record>(); iPanel.addRow(iTable); iBottom = iHeader.clonePanel(); iPanel.addNotPrintableBottomRow(iBottom); initWidget(iPanel); final Timer timer = new Timer() { @Override public void run() { saveOrder(); } }; iTable.addDataChangedListener(new DataChangedListener<Record>() { @Override public void onDataInserted(DataChangedEvent<Record> event) { } @Override public void onDataMoved(List<DataChangedEvent<Record>> event) { timer.schedule(5000); } @Override public void onDataRemoved(DataChangedEvent<Record> event) { } @Override public void onDataSorted(List<DataChangedEvent<Record>> event) { } }); load(); } public void load() { iBottom.setVisible(false); iHeader.setEnabled("save", false); iHeader.setEnabled("edit", false); iHeader.setEnabled("back", false); iHeader.setMessage("Loading data..."); iTable.clearTable(); iService.load(iType, new AsyncCallback<SimpleEditInterface>() { @Override public void onSuccess(SimpleEditInterface result) { iData = result; final Comparator<Record> cmp = iData.getComparator(); Set<String> ordRequest = new HashSet<String>(); ordRequest.add("SimpleEdit.Order[" + iType.toString() + "]"); iMenuService.getUserData(ordRequest, new AsyncCallback<HashMap<String,String>>() { @Override public void onSuccess(HashMap<String, String> result) { final String order = "|" + result.get("SimpleEdit.Order[" + iType.toString() + "]") + "|"; Collections.sort(iData.getRecords(), new Comparator<Record>() { public int compare(Record r1, Record r2) { int i1 = (r1.getUniqueId() == null ? -1 : order.indexOf("|" + r1.getUniqueId() + "|")); if (i1 >= 0) { int i2 = (r2.getUniqueId() == null ? -1 : order.indexOf("|" + r2.getUniqueId() + "|")); if (i2 >= 0) { return (i1 < i2 ? -1 : i1 > i2 ? 1 : cmp.compare(r1, r2)); } } return cmp.compare(r1, r2); } }); refreshTable(); } @Override public void onFailure(Throwable caught) { Collections.sort(iData.getRecords(), cmp); refreshTable(); } }); } @Override public void onFailure(Throwable caught) { iHeader.setErrorMessage("Unable to load data (" + caught.getMessage() + ")"); } }); } private void refreshTable() { iTable.clearTable(); List<Widget> header = new ArrayList<Widget>(); int col = 0; for (final Field field: iData.getFields()) { UniTimeTableHeader cell = new UniTimeTableHeader(field.getName(), col + 1 == iData.getFields().length && iData.isEditable() && iEditable ? 3 : 1); header.add(cell); final int index = col; cell.addOperation(new UniTimeTableHeader.Operation() { @Override public void execute() { iTable.sort(new Comparator<Record>() { public int compare(Record a, Record b) { String f = a.getField(index); String g = b.getField(index); if (f == null) { if (g != null) return 1; } else { if (g == null) return -1; int cmp = f.compareTo(g); if (cmp != 0) return cmp; } return (a.getUniqueId() == null ? b.getUniqueId() == null ? 0 : 1 : b.getUniqueId() == null ? -1 : a.getUniqueId().compareTo(b.getUniqueId())); } }); saveOrder(); } @Override public boolean isApplicable() { return true; } @Override public boolean hasSeparator() { return false; } @Override public String getName() { return "Sort by " + field.getName(); } }); col++; } iTable.addRow(null, header); boolean empty = false; int row = 1; for (Record r: iData.getRecords()) { fillRow(r, row++); empty = r.isEmpty(); } if (!empty && iEditable && iData.isEditable()) fillRow(iData.addRecord(null), row); iBottom.setVisible(true); if (iData.isEditable()) { iHeader.setEnabled("back", iEditable); iHeader.setEnabled("save", iEditable); iHeader.setEnabled("edit", !iEditable); } iHeader.clearMessage(); } private void fillRow(Record record, int row) { List<Widget> line = new ArrayList<Widget>(); int col = 0; for (Field field: iData.getFields()) { MyCell cell = new MyCell(iData.isEditable() && iEditable, field, record, col++); line.add(cell); } if (iData.isEditable() && iEditable) { Image add = new Image(RESOURCES.add()); add.getElement().getStyle().setCursor(Cursor.POINTER); add.setTitle("Insert a new row above this row."); add.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int row = iTable.getCellForEvent(event).getRowIndex(); fillRow(iData.addRecord(null), iTable.insertRow(row)); } }); line.add(add); Image delete = new Image(RESOURCES.delete()); delete.setTitle("Delete this row."); delete.getElement().getStyle().setCursor(Cursor.POINTER); delete.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { int row = iTable.getCellForEvent(event).getRowIndex(); iData.getRecords().remove(iTable.getData(row)); iTable.removeRow(row); } }); line.add(delete); } iTable.setRow(row, record, line); } public class MyCell extends Composite implements HasFocus { private Field iField; private Record iRecord; private int iIndex; public MyCell(boolean editable, Field field, final Record record, final int index) { iField = field; iRecord = record; iIndex = index; if (editable) { if (field.getType() == FieldType.text) { final TextBox text = new TextBox(); text.setStyleName("unitime-TextBox"); text.setMaxLength(field.getLength()); text.setText(record.getField(index)); text.setWidth(field.getWidth() + "px"); text.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { record.setField(index, text.getText()); } }); initWidget(text); } else if (field.getType() == FieldType.list) { final ListBox list = new ListBox(false); list.setStyleName("unitime-TextBox"); if (record.getField(index) == null) { list.addItem("", ""); } for (ListItem item: field.getValues()) list.addItem(item.getText(), item.getValue()); for (int i = 0; i < list.getItemCount(); i++) if (list.getValue(i).equals(record.getField(index))) list.setSelectedIndex(i); list.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { record.setField(index, (list.getSelectedIndex() < 0 || list.getValue(list.getSelectedIndex()).isEmpty() ? null : list.getValue(list.getSelectedIndex()))); } }); initWidget(list); } else if (field.getType() == FieldType.multi) { final ListBox list = new ListBox(true); list.setStyleName("unitime-TextBox"); list.setVisibleItemCount(3); for (ListItem item: field.getValues()) list.addItem(item.getText(), item.getValue()); String[] vals = record.getValues(index); if (vals != null) { for (String val: vals) { for (int i = 0; i < list.getItemCount(); i++) if (list.getValue(i).equals(val)) list.setItemSelected(i, true); } } list.addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { record.setField(index, null); for (int i = 0; i < list.getItemCount(); i++ ) { if (list.isItemSelected(i)) record.addToField(index, list.getValue(i)); } } }); initWidget(list); } else if (field.getType() == FieldType.toggle) { final CheckBox check = new CheckBox(); check.setValue(record.getField(index) == null ? null : "true".equalsIgnoreCase(record.getField(index))); check.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { record.setField(index, check.getValue() == null ? null : check.getValue() ? "true" : "false"); } }); initWidget(check); } } else { Label label = new Label(getValue()); initWidget(label); } } public String getValue() { String value = iRecord.getField(iIndex); if (value == null) return ""; if (iField.getType() == FieldType.list) { for (ListItem item: iField.getValues()) { if (item.getValue().equals(value)) return item.getText(); } } else if (iField.getType() == FieldType.multi) { String text = ""; for (String val: iRecord.getValues(iIndex)) { for (ListItem item: iField.getValues()) { if (item.getValue().equals(val)) { if (!text.isEmpty()) text += ", "; text += item.getText(); } } } return text; } return value; } public Record getRecord() { return iRecord; } public boolean focus() { if (getWidget() instanceof Focusable) { ((Focusable)getWidget()).setFocus(true); if (getWidget() instanceof TextBox) ((TextBox)getWidget()).selectAll(); return true; } return false; } } public void saveOrder() { iHeader.setMessage("Saving order..."); String ord = ""; for (int i = 0; i < iTable.getRowCount(); i++) { Record r = iTable.getData(i); if (r == null || r.getUniqueId() == null) continue; if (!ord.isEmpty()) ord += "|"; ord += r.getUniqueId(); } List<String[]> data = new ArrayList<String[]>(); data.add(new String[] {"SimpleEdit.Order[" + iType.toString() + "]", ord}); iMenuService.setUserData(data, new AsyncCallback<Boolean>() { @Override public void onFailure(Throwable caught) { // iHeader.setErrorMessage("Failed to save table order (" + caught.getMessage() + ")"); iHeader.clearMessage(); } @Override public void onSuccess(Boolean result) { iHeader.clearMessage(); } }); } } |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:02
|
Update of /cvsroot/unitime/UniTime/3rd_party In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/3rd_party Added Files: google-sites-liberation-1.0.3.jar gwt-dev.jar ojdbc6.jar gwt-user.jar Removed Files: ojdbc14.jar log4j-1.2.8.jar Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- log4j-1.2.8.jar DELETED --- --- NEW FILE: gwt-user.jar --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ojdbc6.jar --- (This appears to be a binary file; contents omitted.) --- NEW FILE: gwt-dev.jar --- (This appears to be a binary file; contents omitted.) --- NEW FILE: google-sites-liberation-1.0.3.jar --- (This appears to be a binary file; contents omitted.) --- ojdbc14.jar DELETED --- |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/client/widgets In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/client/widgets Added Files: UniTimeTextBox.java LoadingWidget.java UniTimeTabPabel.java UniTimeTableHeader.java HorizontalPanelWithHint.java WebTable.java UniTimeHeaderPanel.java Validator.java UniTimeWidget.java SimpleForm.java UniTimeDialogBox.java UniTimeTable.java UniTimeFrameDialog.java ValidationErrors.java ImageLink.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: WebTable.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.widgets; import java.util.ArrayList; import org.unitime.timetable.gwt.resources.StudentSectioningMessages; import org.unitime.timetable.gwt.resources.StudentSectioningResources; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.resources.client.ImageResource; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant; import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant; /** * @author Tomas Muller */ public class WebTable extends Composite { public static final StudentSectioningResources RESOURCES = GWT.create(StudentSectioningResources.class); public static final StudentSectioningMessages MESSAGES = GWT.create(StudentSectioningMessages.class); private Row[] iHeader; private String iEmptyMessage = MESSAGES.tableEmpty(); private Row[] iRows; private ArrayList<RowClickHandler> iRowClickHandlers = new ArrayList<RowClickHandler>(); private ArrayList<RowDoubleClickHandler> iRowDoubleClickHandlers = new ArrayList<RowDoubleClickHandler>(); private RowSelectingFlexTable iTable; private int iSelectedRow = -1; private boolean iSelectSameIdRows = false; public WebTable() { iTable = new RowSelectingFlexTable(); iTable.setCellPadding(2); iTable.setCellSpacing(0); initWidget(iTable); } public Widget getPrintWidget(int... skipColumns) { ArrayList<Integer> skip = new ArrayList<Integer>(); for (int c: skipColumns) skip.add(c); return getPrintWidget(skip); } public Widget getPrintWidget(ArrayList<Integer> skipColumns) { WebTable x = new WebTable(); if (iHeader != null) { Row[] header = new Row[iHeader.length]; for (int i = 0; i < iHeader.length; i++) { int col = 0; ArrayList<Cell> cells = new ArrayList<Cell>(); for (int j = 0; j < iHeader[i].getNrCells(); j++) { Cell cell = iHeader[i].getCell(j); int newColSpan = 0; for (int c = 0; c < cell.getColSpan(); c++) { if (!skipColumns.contains(col + c)) newColSpan++; } col += cell.getColSpan(); if (newColSpan == 0) continue; Cell c = new Cell(cell.getValue(), newColSpan, cell.getWidth()); c.setStyleName(cell.getStyleName()); cells.add(c); } header[i] = new Row(cells); } x.setHeader(header); } if (iRows != null && iRows.length > 0) { Row[] data = new Row[iRows.length]; for (int i = 0; i < iRows.length; i++) { int col = 0; ArrayList<Cell> cells = new ArrayList<Cell>(); for (int j = 0; j < iRows[i].getNrCells(); j++) { Cell cell = iRows[i].getCell(j); int newColSpan = 0; for (int c = 0; c < cell.getColSpan(); c++) { if (!skipColumns.contains(col + c)) newColSpan++; } col += cell.getColSpan(); if (newColSpan == 0) continue; Cell c = new Cell(cell.getValue(), newColSpan, cell.getWidth()); c.setStyleName(cell.getStyleName()); cells.add(c); } data[i] = new Row(cells); } x.setData(data); } else { x.setEmptyMessage(iEmptyMessage); } return x; } public void setHeader(Row... header) { iHeader = header; for (int i=0; i<header.length; i++) { for (int j=0; j<header[i].getNrCells(); j++) { Cell cell = header[i].getCell(j); if (cell.getWidget() == null) iTable.setHTML(i, j, (cell.getValue() == null || cell.getValue().isEmpty() ? " " : cell.getValue())); else iTable.setWidget(i, j, cell.getWidget()); iTable.getFlexCellFormatter().setStyleName(i, j, (cell.getStyleName() == null ? "unitime-TableHeader" : cell.getStyleName())); iTable.getFlexCellFormatter().setWidth(i, j, (cell.getWidth() == null ? (100 / header.length) + "%" : cell.getWidth())); iTable.getFlexCellFormatter().setColSpan(i, j, cell.getColSpan()); iTable.getFlexCellFormatter().setVerticalAlignment(i, j, cell.getVerticalAlignment()); iTable.getFlexCellFormatter().setHorizontalAlignment(i, j, cell.getHorizontalAlignment()); } } } public void setColumnVisible(int col, boolean visible) { for (int row = 0; row < iTable.getRowCount(); row++) { iTable.getFlexCellFormatter().setVisible(row, col, visible); } } public int getColumnsCount() { if (iHeader==null || iHeader.length==0) return 1; int ret = 0; for (int i=0; i<iHeader[0].getNrCells(); i++) ret += iHeader[0].getCell(i).getColSpan(); return ret; } public int getHeaderRowsCount() { if (iHeader==null) return 0; return iHeader.length; } public int getRowsCount() { if (iRows==null) return 0; return iRows.length; } public void setEmptyMessage(String emptyMessage) { iEmptyMessage = emptyMessage; if (iRows==null || iRows.length==0) { iTable.setHTML(getHeaderRowsCount(), 0, iEmptyMessage); if (iEmptyMessage!=null) { iTable.getFlexCellFormatter().setColSpan(getHeaderRowsCount(), 0, getColumnsCount()); iTable.getFlexCellFormatter().setStyleName(getHeaderRowsCount(), 0, "unitime-TableEmpty"); } else { iTable.getFlexCellFormatter().setColSpan(getHeaderRowsCount(), 0, 1); iTable.getFlexCellFormatter().setStyleName(getHeaderRowsCount(), 0, null); } } } public void clearData(boolean showEmptyMessage) { for (int row = iTable.getRowCount() - 1; row >= getHeaderRowsCount(); row--) { iTable.removeRow(row); } iRows = null; if (showEmptyMessage) setEmptyMessage(iEmptyMessage); } public void clearData(int keepRows) { for (int row = iTable.getRowCount() - 1; row >= getHeaderRowsCount() + keepRows; row--) { iTable.removeRow(row); } } public void setData(Row... rows) { setSelectedRow(-1); if (rows==null || rows.length==0) { clearData(true); return; } clearData(rows.length); iRows = rows; for (int i=0; i<iRows.length; i++) { if (iRows[i] == null) continue; iRows[i].setRowIdx(i); iRows[i].setTable(this); iTable.getRowFormatter().setStyleName(i+getHeaderRowsCount(), null); for (int j=0; j<iRows[i].getNrCells(); j++) { Cell cell = iRows[i].getCell(j); cell.setColIdx(j); cell.setRow(iRows[i]); if (cell.getWidget() == null) iTable.setHTML(i+getHeaderRowsCount(), j, (cell.getValue() == null || cell.getValue().isEmpty() ? " " : cell.getValue())); else iTable.setWidget(i+getHeaderRowsCount(), j, cell.getWidget()); iTable.getFlexCellFormatter().setColSpan(i+getHeaderRowsCount(), j, cell.getColSpan()); iTable.getFlexCellFormatter().setStyleName(i+getHeaderRowsCount(), j, cell.getStyleName()); iTable.getFlexCellFormatter().setWidth(i+getHeaderRowsCount(), j, cell.getWidth()); iTable.getFlexCellFormatter().setVerticalAlignment(i+getHeaderRowsCount(), j, cell.getVerticalAlignment()); iTable.getFlexCellFormatter().setHorizontalAlignment(i+getHeaderRowsCount(), j, cell.getHorizontalAlignment()); } for (int j=iTable.getCellCount(i+getHeaderRowsCount()) - 1; j >= iRows[i].getNrCells(); j--) { iTable.clearCell(i+getHeaderRowsCount(), j); } } } public void setData(String[]... lines) { Row[] rows = new Row[lines.length]; for (int i=0; i<lines.length; i++) { rows[i] = new Row(lines[i]); } setData(rows); } public void addRowClickHandler(RowClickHandler rowClickHandler) { iRowClickHandlers.add(rowClickHandler); } public void addRowDoubleClickHandler(RowDoubleClickHandler rowDoubleClickHandler) { iRowDoubleClickHandlers.add(rowDoubleClickHandler); } public void fireRowClickEvent(Event event, int row) { RowClickEvent e = new RowClickEvent(event, iRows[row], row); for (RowClickHandler h: iRowClickHandlers) h.onRowClick(e); } public void fireDoubleRowClickEvent(Event event, int row) { RowDoubleClickEvent e = new RowDoubleClickEvent(event, iRows[row], row); for (RowDoubleClickHandler h: iRowDoubleClickHandlers) h.onRowDoubleClick(e); } public void setSelectedRow(int row) { if (iSelectedRow>=0) { if (isSelectSameIdRows() && iRows != null && iSelectedRow < iRows.length) { String id = iRows[iSelectedRow].getId(); for (Row r: iRows) { if (id.equals(r.getId())) iTable.getRowFormatter().setStyleName(getHeaderRowsCount() + r.getRowIdx(), null); } } else { iTable.getRowFormatter().setStyleName(iSelectedRow + getHeaderRowsCount(), null); } } if (row<0 || iRows==null || iRows.length==0) { iSelectedRow = -1; } else { iSelectedRow = row % iRows.length; if (isSelectSameIdRows()) { String id = iRows[iSelectedRow].getId(); for (Row r: iRows) { if (id.equals(r.getId())) iTable.getRowFormatter().setStyleName(getHeaderRowsCount() + r.getRowIdx(), "unitime-TableRowSelected"); } } else { iTable.getRowFormatter().setStyleName(iSelectedRow + getHeaderRowsCount(), "unitime-TableRowSelected"); } } } public int getSelectedRow() { return iSelectedRow; } public Row[] getRows() { return iRows; } public void setSelectSameIdRows(boolean selectSameIdRows) { iSelectSameIdRows = selectSameIdRows; } public boolean isSelectSameIdRows() { return iSelectSameIdRows; } public String getSelectedRowId() { if (iSelectedRow < 0 || iSelectedRow >= iRows.length) return null; return iRows[iSelectedRow].getId(); } public static class Row { private String iId; private Cell[] iCells; private int iRowIdx = -1; private WebTable iTable; public Row(Cell... cells) { iCells = cells; } public Row(ArrayList<Cell> cells) { iCells = new Cell[cells.size()]; for (int i = 0; i < iCells.length; i++) iCells[i] = cells.get(i); } public Row(String... cells) { iCells = new Cell[cells.length]; for (int i=0; i<cells.length;i++) iCells[i] = new Cell(cells[i]); } public int getNrCells() { return iCells.length; } public Cell getCell(int idx) { return iCells[idx]; } public Cell[] getCells() { return iCells; } public String getId() { return iId; } public void setId(String id) { iId = id; } public int getRowIdx() { return iRowIdx; } public void setRowIdx(int rowIdx) { iRowIdx = rowIdx; } public void setTable(WebTable table) { iTable = table; } public WebTable getTable() { return iTable; } public void setCell(int col, Cell cell) { iCells[col] = cell; if (iTable != null) { FlexTable t = iTable.iTable; cell.setColIdx(col); cell.setRow(this); if (cell.getWidget() == null) t.setHTML(getRowIdx() + iTable.getHeaderRowsCount(), col, (cell.getValue() == null || cell.getValue().isEmpty() ? " " : cell.getValue())); else t.setWidget(getRowIdx() + iTable.getHeaderRowsCount(), col, cell.getWidget()); t.getFlexCellFormatter().setColSpan(getRowIdx() + iTable.getHeaderRowsCount(), col, cell.getColSpan()); t.getFlexCellFormatter().setStyleName(getRowIdx() + iTable.getHeaderRowsCount(), col, cell.getStyleName()); t.getFlexCellFormatter().setWidth(getRowIdx() + iTable.getHeaderRowsCount(), col, cell.getWidth()); t.getFlexCellFormatter().setVerticalAlignment(getRowIdx() + iTable.getHeaderRowsCount(), col, cell.getVerticalAlignment()); t.getFlexCellFormatter().setHorizontalAlignment(getRowIdx() + iTable.getHeaderRowsCount(), col, cell.getHorizontalAlignment()); } } } public static class Cell { String iValue; int iColSpan = 1; String iStyleName = null; String iWidth = null; Row iRow = null; int iColIdx = -1; VerticalAlignmentConstant iVerticalAlignment = HasVerticalAlignment.ALIGN_TOP; HorizontalAlignmentConstant iHorizontalAlignment = HasHorizontalAlignment.ALIGN_LEFT; public Cell(String value) { iValue = value; } public Cell(String value, int colSpan, String width) { iValue = value; iColSpan = colSpan; iWidth = width; } public String getValue() { return iValue; } public int getColSpan() { return iColSpan; } public void setColSpan(int colSpan) { iColSpan = colSpan; } public String getStyleName() { return iStyleName; } public void setStyleName(String styleName) { iStyleName = styleName; if (iRow != null) iRow.iTable.iTable.getCellFormatter().setStyleName(iRow.iTable.getHeaderRowsCount() + iRow.iRowIdx, iColIdx, iStyleName); } public String getWidth() { return iWidth; } public void setWitdh(String width) { iWidth = width; } public void setColIdx(int colIdx) { iColIdx = colIdx; } public int getColIdx() { return iColIdx; } public void setRow(Row row) { iRow = row; } public Row getRow() { return iRow; } public Widget getWidget() { return null; } public VerticalAlignmentConstant getVerticalAlignment() { return iVerticalAlignment; } public void setVerticalAlignment(VerticalAlignmentConstant vertical) { iVerticalAlignment = vertical; } public HorizontalAlignmentConstant getHorizontalAlignment() { return iHorizontalAlignment; } public void setHorizontalAlignment(HorizontalAlignmentConstant vertical) { iHorizontalAlignment = vertical; } } public static class CheckboxCell extends Cell { private CheckBox iCheck = new CheckBox(); public CheckboxCell(boolean check) { super(null); iCheck.setValue(check); iCheck.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { event.stopPropagation(); } }); } public boolean isChecked() { return iCheck.getValue(); } public String getValue() { return iCheck.getValue().toString(); } public Widget getWidget() { return iCheck; } } public static class IconCell extends Cell { private Image iIcon = null; private HTML iLabel = null; private HorizontalPanel iPanel = null; public IconCell(ImageResource resource, String title, String text) { super(null); iIcon = new Image(resource); iIcon.setTitle(title); iLabel = new HTML(text, false); iPanel = new HorizontalPanel(); iPanel.add(iIcon); iPanel.add(iLabel); iIcon.getElement().getStyle().setPaddingRight(3, Unit.PX); iPanel.setCellVerticalAlignment(iIcon, HasVerticalAlignment.ALIGN_MIDDLE); } public String getValue() { return iLabel.getText(); } public Widget getWidget() { return iPanel; } public void setStyleName(String styleName) { super.setStyleName(styleName); iLabel.setStyleName(styleName); iLabel.getElement().getStyle().setBorderWidth(0, Unit.PX); } } public static class WidgetCell extends Cell { private Widget iWidget = null; public WidgetCell(Widget widget, String text, int colspan, String width) { super(text, colspan, width); iWidget = widget; } public WidgetCell(Widget widget, String text) { super(text); iWidget = widget; } public Widget getWidget() { return iWidget; } } public static class MultiCell extends Cell { protected Panel iPanel = new FlowPanel(); protected String iText = ""; protected ArrayList<UIObject> iContent = new ArrayList<UIObject>(); public MultiCell(ArrayList<String> names, String separator) { super(null); if (names != null) { separator = separator.replace(" ", " "); for (int i = 0; i < names.size(); i++) add(names.get(i) + (i + 1 < names.size() ? separator : "")); } } protected void add(String text) { iText += text; HTML h = new HTML(text, false); iPanel.add(h); iContent.add(h); } public String getValue() { return iText; } public Widget getWidget() { return iPanel; } public void setStyleName(String styleName) { super.setStyleName(styleName); for (UIObject c: iContent) { c.setStyleName(styleName); c.getElement().getStyle().setBorderWidth(0, Unit.PX); } } } public static class InstructorCell extends MultiCell { public InstructorCell(ArrayList<String> names, ArrayList<String> emails, String separator) { super(null, separator); if (names != null && !names.isEmpty()) { separator = separator.replace(" ", " "); for (int i = 0; i < names.size(); i++) { String text = names.get(i) + (i + 1 < names.size() ? separator : ""); String email = (emails != null && i < emails.size() ? emails.get(i) : null); if (email != null && !email.isEmpty()) { iText += text; HorizontalPanel p = new HorizontalPanel(); Anchor a = new Anchor(); a.setHref("mailto:" + email); a.setHTML(DOM.toString(new Image(RESOURCES.email()).getElement())); a.setTitle("Send " + names.get(i) + " an email."); a.setStyleName("unitime-SimpleLink"); a.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { event.stopPropagation(); } }); p.add(a); p.setCellVerticalAlignment(a, HasVerticalAlignment.ALIGN_MIDDLE); HTML h = new HTML(text, false); h.getElement().getStyle().setMarginLeft(2, Unit.PX); p.add(h); iPanel.add(p); iContent.add(h); } else add(text); } } else { add(" "); } } } public class RowSelectingFlexTable extends FlexTable { public RowSelectingFlexTable() { super(); sinkEvents(Event.ONMOUSEOVER); sinkEvents(Event.ONMOUSEOUT); sinkEvents(Event.ONCLICK); sinkEvents(Event.ONDBLCLICK); } public void onBrowserEvent(Event event) { if (iRows==null || iRows.length==0) return; Element td = getEventTargetCell(event); if (td==null) return; Element tr = DOM.getParent(td); Element body = DOM.getParent(tr); int row = DOM.getChildIndex(body, tr); switch (DOM.eventGetType(event)) { case Event.ONMOUSEOVER: if (row >= getHeaderRowsCount() && row < getHeaderRowsCount() + iRows.length) { if (isSelectSameIdRows()) { String id = iRows[row - getHeaderRowsCount()].getId(); String sid = getSelectedRowId(); for (Row r: iRows) { if (id.equals(r.getId())) getRowFormatter().setStyleName(getHeaderRowsCount() + r.getRowIdx(), (id.equals(sid)? "unitime-TableRowSelectedHover" : "unitime-TableRowHover")); } } else { getRowFormatter().setStyleName(row, (row - getHeaderRowsCount() == iSelectedRow? "unitime-TableRowSelectedHover" : "unitime-TableRowHover")); } } break; case Event.ONMOUSEOUT: if (row >= getHeaderRowsCount() && row < getHeaderRowsCount() + iRows.length && row - getHeaderRowsCount() != iSelectedRow) { if (isSelectSameIdRows()) { String id = iRows[row - getHeaderRowsCount()].getId(); String sid = getSelectedRowId(); for (Row r: iRows) { if (id.equals(r.getId())) getRowFormatter().setStyleName(getHeaderRowsCount() + r.getRowIdx(), (id.equals(sid)? "unitime-TableRowSelectedHover" : null)); } } else { getRowFormatter().setStyleName(row, (row - getHeaderRowsCount() == iSelectedRow? "unitime-TableRowSelectedHover" : null)); } } break; case Event.ONCLICK: if (row >= getHeaderRowsCount() && row < getHeaderRowsCount() + iRows.length) { RowClickEvent e = new RowClickEvent(event, iRows[row - getHeaderRowsCount()], row - getHeaderRowsCount()); for (RowClickHandler h: iRowClickHandlers) h.onRowClick(e); } break; case Event.ONDBLCLICK: if (row >= getHeaderRowsCount() && row < getHeaderRowsCount() + iRows.length) { RowDoubleClickEvent e = new RowDoubleClickEvent(event, iRows[row - getHeaderRowsCount()], row - getHeaderRowsCount()); for (RowDoubleClickHandler h: iRowDoubleClickHandlers) h.onRowDoubleClick(e); } break; } } } public FlexTable getTable() { return iTable; } public static class RowClickEvent { private Event iEvent; private Row iRow; private int iRowIdx; private RowClickEvent(Event event, Row row, int rowIdx) { iEvent = event; iRow = row; iRowIdx = rowIdx; } public Event getEvent() { return iEvent; } public Row getRow() { return iRow; } public int getRowIdx() { return iRowIdx; } } public static interface RowClickHandler { public void onRowClick(RowClickEvent event); } public static class RowDoubleClickEvent { private Event iEvent; private Row iRow; private int iRowIdx; private RowDoubleClickEvent(Event event, Row row, int rowIdx) { iEvent = event; iRow = row; iRowIdx = rowIdx; } public Event getEvent() { return iEvent; } public Row getRow() { return iRow; } public int getRowIdx() { return iRowIdx; } } public static interface RowDoubleClickHandler { public void onRowDoubleClick(RowDoubleClickEvent event); } } --- NEW FILE: UniTimeTabPabel.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.widgets; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.ui.TabPanel; import com.google.gwt.user.client.ui.Widget; /** * {@link TabPanel} wrapper to avoid deprecation warnings. * To be used only for pages not based on LayoutPanel (and preferably avoided in the future development). */ @SuppressWarnings("deprecation") public class UniTimeTabPabel extends TabPanel { public UniTimeTabPabel() { super(); } public void add(Widget w, String tabText, boolean asHTML) { super.add(w, tabText, asHTML); } public void insert(Widget widget, String tabText, boolean asHTML, int beforeIndex) { super.insert(widget, tabText, asHTML, beforeIndex); } public void setDeckSize(String width, String height) { getDeckPanel().setSize(width, height); } public void setDeckStyleName(String style) { getDeckPanel().setStyleName(style); } public void selectTab(int index) { super.selectTab(index); } public HandlerRegistration addSelectionHandler(SelectionHandler<Integer> handler) { return super.addSelectionHandler(handler); } public int getTabCount() { return getTabBar().getTabCount(); } public int getSelectedTab() { return getTabBar().getSelectedTab(); } } --- NEW FILE: ValidationErrors.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.widgets; import java.util.ArrayList; import org.unitime.timetable.gwt.resources.StudentSectioningMessages; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.VerticalPanel; /** * @author Tomas Muller */ public class ValidationErrors extends Composite { public static final StudentSectioningMessages MESSAGES = GWT.create(StudentSectioningMessages.class); private DialogBox iDialog; private Label iProgress, iError; private VerticalPanel iErrorsPanel; private boolean iAutoHide; private ArrayList<Validator> iValidators = new ArrayList<Validator>(); private boolean iShowIndividualErrors; private String iErrorMessage; public ValidationErrors(boolean showIndividualErrors, String title, String errorMessage, boolean autoHide) { iDialog = new DialogBox(); iDialog.setText(title); iDialog.setAnimationEnabled(false); iDialog.setAutoHideEnabled(false); iDialog.setGlassEnabled(true); iDialog.setModal(true); iAutoHide = autoHide; iProgress = new Label(MESSAGES.pleaseWait()); iProgress.setStyleName("unitime-ProgressMessage"); iDialog.add(iProgress); iErrorsPanel = new VerticalPanel(); iErrorsPanel.setSpacing(5); iErrorsPanel.setStyleName("unitime-ValidationErrors"); iError = new Label(); iErrorMessage = errorMessage; iShowIndividualErrors = showIndividualErrors; if (!iShowIndividualErrors) { iError.setStyleName("unitime-ErrorMessage"); iErrorsPanel.add(iError); } initWidget(iErrorsPanel); } public void addValidator(Validator validator) { iValidators.add(validator); } public synchronized void validate(final AsyncCallback<Boolean> onResult) { if (iShowIndividualErrors) for (int i=iErrorsPanel.getWidgetCount()-1; i>=0; i--) iErrorsPanel.remove(i); iError.setText(null); iDialog.center(); final Counter c = new Counter(iValidators.size()); for (Validator validator: iValidators) { validator.validate(new AsyncCallback<String>() { public void onFailure(Throwable caught) { onSuccess(caught.getMessage()); } public void onSuccess(String result) { if (result!=null && !result.isEmpty()) { if (iShowIndividualErrors) { Label error = new Label(result); error.setStyleName("unitime-ErrorMessage"); iErrorsPanel.add(error); } } if (c.decrement(result!=null && !result.isEmpty())) { if (iAutoHide) { new Timer() { @Override public void run() { iDialog.hide(); } }.schedule(500); } if (c.isError()) iError.setText(iErrorMessage); onResult.onSuccess(!c.isError()); } } }); } } public void hide() { iDialog.hide(); } private static class Counter { private int iCounter; private boolean iError = false; private Counter(int counter) { iCounter = counter; } private boolean decrement(boolean error) { if (error) iError = true; return --iCounter == 0; } private boolean isError() { return iError; } } } --- NEW FILE: UniTimeTextBox.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.widgets; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasFocus; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.ValueBoxBase; /** * @author Tomas Muller */ public class UniTimeTextBox extends TextBox implements HasFocus { public UniTimeTextBox() { super(); setStyleName("unitime-TextBox"); } public UniTimeTextBox(int maxWidth, int width, ValueBoxBase.TextAlignment align) { this(); setWidth(width + "px"); setMaxLength(maxWidth); if (align != null) setAlignment(align); } public UniTimeTextBox(int maxWidth, int width) { this(maxWidth, width, null); } public UniTimeTextBox(int maxWidth, ValueBoxBase.TextAlignment align) { this(maxWidth, 10 * maxWidth, align); } public UniTimeTextBox(int maxWidth) { this(maxWidth, 10 * maxWidth, null); } public UniTimeTextBox(boolean editable) { this(); setReadOnly(!editable); } public UniTimeTextBox(int maxWidth, ValueBoxBase.TextAlignment align, boolean editable) { this(maxWidth, align); setReadOnly(!editable); } @Deprecated public void setEnabled(boolean enabled) { super.setEnabled(enabled); } @Deprecated public boolean isEnabled() { return super.isEnabled(); } public void setReadOnly(boolean readOnly) { super.setReadOnly(readOnly); if (readOnly) { getElement().getStyle().setBorderColor("transparent"); getElement().getStyle().setBackgroundColor("transparent"); } else { getElement().getStyle().clearBorderColor(); getElement().getStyle().clearBackgroundColor(); } } @Override public boolean focus() { if (isReadOnly()) return false; setFocus(true); selectAll(); return true; } } --- NEW FILE: UniTimeTable.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.widgets; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlexTable; import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.TextBoxBase; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant; /** * @author Tomas Muller */ public class UniTimeTable<T> extends FlexTable { private List<MouseOverListener<T>> iMouseOverListeners = new ArrayList<MouseOverListener<T>>(); private List<MouseOutListener<T>> iMouseOutListeners = new ArrayList<MouseOutListener<T>>(); private List<MouseClickListener<T>> iMouseClickListeners = new ArrayList<MouseClickListener<T>>(); private List<DataChangedListener<T>> iDataChangedListeners = new ArrayList<DataChangedListener<T>>(); private PopupPanel iHintPanel = null; private HintProvider<T> iHintProvider = null; private int iLastHoverRow = -1; private boolean iAllowSelection = false; public UniTimeTable() { setCellPadding(2); setCellSpacing(0); sinkEvents(Event.ONMOUSEOVER); sinkEvents(Event.ONMOUSEOUT); sinkEvents(Event.ONCLICK); sinkEvents(Event.ONKEYDOWN); setStylePrimaryName("unitime-MainTable"); iHintPanel = new PopupPanel(); iHintPanel.setStyleName("unitime-PopupHint"); } public void setAllowSelection(boolean allow) { iAllowSelection = allow; } public boolean isAllowSelection() { return iAllowSelection; } public void clearTable(int headerRows) { for (int row = getRowCount() - 1; row >= headerRows; row--) removeRow(row); } public void clearTable() { clearTable(0); } public void addRow(T data, Widget... widgets) { List<Widget> list = new ArrayList<Widget>(); for (Widget widget: widgets) list.add(widget); addRow(data, list); } public int addRow(T data, List<? extends Widget> widgets) { int row = getRowCount(); setRow(row, data, widgets); return row; } public void setRow(int row, T data, List<? extends Widget> widgets) { SmartTableRow<T> oldRow = getSmartRow(row); if (oldRow != null && oldRow.getData() != null) { DataChangedEvent<T> event = new DataChangedEvent<T>(oldRow.getData(), row); for (DataChangedListener<T> listener: iDataChangedListeners) listener.onDataRemoved(event); } SmartTableRow smartRow = new SmartTableRow(data); int col = 0; for (Widget widget: widgets) { SmartTableCell cell = new SmartTableCell(smartRow, widget); if (widget instanceof HasColSpan) getFlexCellFormatter().setColSpan(row, col, ((HasColSpan)widget).getColSpan()); if (widget instanceof HasStyleName && ((HasStyleName)widget).getStyleName() != null) getFlexCellFormatter().setStyleName(row, col, ((HasStyleName)widget).getStyleName()); if (widget instanceof HasAdditionalStyleNames) { List<String> styleNames = ((HasAdditionalStyleNames)widget).getAdditionalStyleNames(); if (styleNames != null) for (String styleName: styleNames) getFlexCellFormatter().addStyleName(row, col, styleName); } if (widget instanceof HasCellAlignment) getFlexCellFormatter().setHorizontalAlignment(row, col, ((HasCellAlignment)widget).getCellAlignment()); setWidget(row, col++, cell); } if (data != null) { DataChangedEvent<T> event = new DataChangedEvent<T>(data, row); for (DataChangedListener<T> listener: iDataChangedListeners) listener.onDataInserted(event); } } public boolean isColumnVisible(int col) { return getCellFormatter().isVisible(0, col); } public void setColumnVisible(int col, boolean visible) { for (int r = 0; r < getRowCount(); r++) getCellFormatter().setVisible(r, col, visible); } public static class SmartTableRow<T> { private List<SmartTableCell> iCells = new ArrayList<SmartTableCell>(); private T iData = null; public SmartTableRow(T data) { iData = data; } public T getData() { return iData; } public boolean hasData() { return iData != null; } public List<SmartTableCell> getCells() { return iCells; } public Comparator<SmartTableRow<T>> getComparator(final Comparator<T> cmp) { return new Comparator<SmartTableRow<T>>() { public int compare(SmartTableRow<T> a, SmartTableRow<T> b) { return cmp.compare(a.getData(), b.getData()); } }; } } public static class SmartTableCell extends Composite { SmartTableRow iRow; public SmartTableCell(SmartTableRow row, Widget widget) { iRow = row; row.getCells().add(this); initWidget(widget); } public SmartTableRow getRow() { return iRow; } public boolean focus() { if (getWidget() instanceof HasFocus) { return ((HasFocus)getWidget()).focus(); } else if (getWidget() instanceof Focusable) { ((Focusable)getWidget()).setFocus(true); if (getWidget() instanceof TextBoxBase) ((TextBoxBase)getWidget()).selectAll(); return true; } return false; } public Widget getInnerWidget() { return getWidget(); } } public Widget getWidget(int row, int col) { Widget w = super.getWidget(row, col); if (w == null) return w; if (w instanceof SmartTableCell) return ((SmartTableCell)w).getInnerWidget(); return w; } private boolean focus(int row, int col) { if (!getRowFormatter().isVisible(row) || col >= getCellCount(row)) return false; Widget w = super.getWidget(row, col); if (w == null || !w.isVisible()) return false; if (w instanceof SmartTableCell) { return ((SmartTableCell)w).focus(); } else if (w instanceof HasFocus) { return ((HasFocus)w).focus(); } else if (w instanceof Focusable) { ((Focusable)w).setFocus(true); if (w instanceof TextBoxBase) ((TextBoxBase)w).selectAll(); return true; } return false; } public T getData(int row) { SmartTableRow<T> r = getSmartRow(row); return (r == null ? null : r.getData()); } public List<T> getData() { List<T> ret = new ArrayList<T>(); for (int row = 0; row < getRowCount(); row++) { T data = getData(row); if (data != null) ret.add(data); } return ret; } public SmartTableRow<T> getSmartRow(int row) { if (row < 0 || row >= getRowCount()) return null; for (int col = 0; col < getCellCount(row); col++) { Widget w = super.getWidget(row, col); if (w != null && w instanceof SmartTableCell) return ((SmartTableCell)w).getRow(); } return null; } private void swapRows(int r0, int r1) { if (r0 == r1) return; if (r0 > r1) { swapRows(r1, r0); } else { // r0 < r1 Element body = getBodyElement(); Element a = DOM.getChild(body, r0); Element b = DOM.getChild(body, r1); DOM.removeChild(body, a); DOM.removeChild(body, b); DOM.insertChild(body, b, r0); DOM.insertChild(body, a, r1); } } public void sort(final Comparator<T> rowComparator) { Element body = getBodyElement(); ArrayList<Object[]> rows = new ArrayList<Object[]>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> r = getSmartRow(row); if (r != null && r.hasData()) { rows.add(new Object[] {r, getRowFormatter().getElement(row)}); } } Collections.sort(rows,new Comparator<Object[]>() { public int compare(Object[] a, Object[] b) { return rowComparator.compare(((SmartTableRow<T>)a[0]).getData(), ((SmartTableRow<T>)b[0]).getData()); } }); int idx = 0; List<DataChangedEvent<T>> changeEvents = new ArrayList<DataChangedEvent<T>>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> a = getSmartRow(row); if (a != null && a.hasData()) { Object[] o = rows.get(idx++); int otherRow = DOM.getChildIndex(body, (Element)o[1]); swapRows(row, otherRow); changeEvents.add(new DataChangedEvent<T>(((SmartTableRow<T>)o[0]).getData(), row)); } } for (DataChangedListener<T> listener: iDataChangedListeners) listener.onDataSorted(changeEvents); } public void sortByRow(final Comparator<Integer> rowComparator) { Element body = getBodyElement(); ArrayList<Object[]> rows = new ArrayList<Object[]>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> r = getSmartRow(row); if (r != null && r.hasData()) { rows.add(new Object[] {r, getRowFormatter().getElement(row), row}); } } Collections.sort(rows,new Comparator<Object[]>() { public int compare(Object[] a, Object[] b) { return rowComparator.compare((Integer)a[2], (Integer)b[2]); } }); int idx = 0; List<DataChangedEvent<T>> changeEvents = new ArrayList<DataChangedEvent<T>>(); for (int row = 0; row < getRowCount(); row++) { SmartTableRow<T> a = getSmartRow(row); if (a != null && a.hasData()) { Object[] o = rows.get(idx++); int otherRow = DOM.getChildIndex(body, (Element)o[1]); swapRows(row, otherRow); changeEvents.add(new DataChangedEvent<T>(((SmartTableRow<T>)o[0]).getData(), row)); } } for (DataChangedListener<T> listener: iDataChangedListeners) listener.onDataSorted(changeEvents); } public boolean canSwapRows(T a, T b) { return true; } public void onBrowserEvent(final Event event) { Element td = getEventTargetCell(event); if (td==null) return; final Element tr = DOM.getParent(td); int col = DOM.getChildIndex(tr, td); Element body = DOM.getParent(tr); int row = DOM.getChildIndex(body, tr); Widget widget = getWidget(row, col); SmartTableRow<T> r = getSmartRow(row); boolean hasData = (r != null && r.getData() != null); TableEvent<T> tableEvent = new TableEvent<T>(event, row, col, tr, td, hasData ? r.getData() : null); Widget hint = null; if (widget instanceof HasHint) { String html = ((HasHint)widget).getHint(); if (html != null && !html.isEmpty()) hint = new HTML(html, false); } if (hint == null && iHintProvider != null) hint = iHintProvider.getHint(tableEvent); String style = getRowFormatter().getStyleName(row); switch (DOM.eventGetType(event)) { case Event.ONMOUSEOVER: if (hasData) { if (isAllowSelection()) { if ("unitime-TableRowSelected".equals(style)) getRowFormatter().setStyleName(row, "unitime-TableRowSelectedHover"); else getRowFormatter().setStyleName(row, "unitime-TableRowHover"); } else { getRowFormatter().addStyleName(row, "unitime-TableRowHover"); } iLastHoverRow = row; } if (!iHintPanel.isShowing() && hint != null) { iHintPanel.setWidget(hint); iHintPanel.setPopupPositionAndShow(new PopupPanel.PositionCallback() { @Override public void setPosition(int offsetWidth, int offsetHeight) { boolean top = (tr.getAbsoluteBottom() - Window.getScrollTop() + 15 + offsetHeight > Window.getClientHeight()); iHintPanel.setPopupPosition( Math.max(Math.min(event.getClientX(), tr.getAbsoluteRight() - offsetWidth - 15), tr.getAbsoluteLeft() + 15), top ? tr.getAbsoluteTop() - offsetHeight - 15 : tr.getAbsoluteBottom() + 15); } }); } for (MouseOverListener<T> listener: iMouseOverListeners) listener.onMouseOver(tableEvent); break; case Event.ONMOUSEOUT: if (hasData) { if (isAllowSelection()) { if ("unitime-TableRowHover".equals(style)) getRowFormatter().setStyleName(row, null); else if ("unitime-TableRowSelectedHover".equals(style)) getRowFormatter().setStyleName(row, "unitime-TableRowSelected"); } else { getRowFormatter().removeStyleName(row, "unitime-TableRowHover"); } iLastHoverRow = -1; } if (iHintPanel.isShowing()) iHintPanel.hide(); for (MouseOutListener<T> listener: iMouseOutListeners) listener.onMouseOut(tableEvent); break; case Event.ONMOUSEMOVE: if (iHintPanel.isShowing()) { boolean top = (tr.getAbsoluteBottom() - Window.getScrollTop() + 15 + iHintPanel.getOffsetHeight() > Window.getClientHeight()); iHintPanel.setPopupPosition( Math.max(Math.min(event.getClientX(), tr.getAbsoluteRight() - iHintPanel.getOffsetWidth() - 15), tr.getAbsoluteLeft() + 15), top ? tr.getAbsoluteTop() - iHintPanel.getOffsetHeight() - 15 : tr.getAbsoluteBottom() + 15); } break; case Event.ONCLICK: if (isAllowSelection()) { Element element = DOM.eventGetTarget(event); while (DOM.getElementProperty(element, "tagName").equalsIgnoreCase("div")) element = DOM.getParent(element); if (DOM.getElementProperty(element, "tagName").equalsIgnoreCase("td")) { boolean hover = ("unitime-TableRowHover".equals(style) || "unitime-TableRowSelectedHover".equals(style)); boolean selected = !("unitime-TableRowSelected".equals(style) || "unitime-TableRowSelectedHover".equals(style)); getRowFormatter().setStyleName(row, "unitime-TableRow" + (selected ? "Selected" : "") + (hover ? "Hover" : "")); } } for (MouseClickListener<T> listener: iMouseClickListeners) listener.onMouseClick(tableEvent); break; case Event.ONKEYDOWN: if (event.getKeyCode() == KeyCodes.KEY_RIGHT && (event.getAltKey() || event.getMetaKey())) { do { col++; if (col >= getCellCount(row)) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } if (event.getKeyCode() == KeyCodes.KEY_LEFT && (event.getAltKey() || event.getMetaKey())) { do { col--; if (col < 0) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } if (event.getKeyCode() == KeyCodes.KEY_UP && (event.getAltKey() || event.getMetaKey())) { do { row--; if (row < 0) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } if (event.getKeyCode() == KeyCodes.KEY_DOWN && (event.getAltKey() || event.getMetaKey())) { do { row++; if (row >= getRowCount()) break; } while (!focus(row, col)); event.stopPropagation(); event.preventDefault(); } if (hasData && event.getKeyCode() == KeyCodes.KEY_UP && event.getCtrlKey()) { SmartTableRow<T> up = getSmartRow(row - 1); if (up != null && up.getData() != null && canSwapRows(r.getData(), up.getData())) { getRowFormatter().removeStyleName(row, "unitime-TableRowHover"); getRowFormatter().removeStyleName(row - 1, "unitime-TableRowHover"); swapRows(row - 1, row); focus(row - 1, col); if (!iDataChangedListeners.isEmpty()) { List<DataChangedEvent<T>> e = new ArrayList<DataChangedEvent<T>>(); e.add(new DataChangedEvent<T>(up.getData(), row)); e.add(new DataChangedEvent<T>(r.getData(), row - 1)); for (DataChangedListener<T> listener: iDataChangedListeners) { listener.onDataMoved(e); } } } event.stopPropagation(); event.preventDefault(); } if (hasData && event.getKeyCode() == KeyCodes.KEY_DOWN && event.getCtrlKey()) { SmartTableRow<T> dn = getSmartRow(row + 1); if (dn != null && dn.getData() != null && canSwapRows(r.getData(), dn.getData())) { getRowFormatter().removeStyleName(row, "unitime-TableRowHover"); getRowFormatter().removeStyleName(row + 1, "unitime-TableRowHover"); swapRows(row + 1, row); focus(row + 1, col); if (!iDataChangedListeners.isEmpty()) { List<DataChangedEvent<T>> e = new ArrayList<DataChangedEvent<T>>(); e.add(new DataChangedEvent<T>(dn.getData(), row)); e.add(new DataChangedEvent<T>(r.getData(), row + 1)); for (DataChangedListener<T> listener: iDataChangedListeners) { listener.onDataMoved(e); } } } event.stopPropagation(); event.preventDefault(); } break; } } public void clearHover() { if (iLastHoverRow >= 0 && iLastHoverRow < getRowCount()) { if (isAllowSelection()) { String style = getRowFormatter().getStyleName(iLastHoverRow); boolean selected = ("unitime-TableRowSelected".equals(style) || "unitime-TableRowSelectedHover".equals(style)); getRowFormatter().setStyleName(iLastHoverRow, "unitime-TableRow" + (selected ? "Selected" : "")); } else { getRowFormatter().removeStyleName(iLastHoverRow, "unitime-TableRowHover"); } } iLastHoverRow = 1; } public boolean isSelected(int row) { if (isAllowSelection()) { String style = getRowFormatter().getStyleName(row); return "unitime-TableRowSelected".equals(style) || "unitime-TableRowSelectedHover".equals(style); } else { return false; } } public void setSelected(int row, boolean selected) { if (isAllowSelection()) { String style = getRowFormatter().getStyleName(row); boolean hover = ("unitime-TableRowHover".equals(style) || "unitime-TableRowSelectedHover".equals(style)); getRowFormatter().setStyleName(row, "unitime-TableRow" + (selected ? "Selected" : "") + (hover ? "Hover" : "")); } } public int getSelectedCount() { int selected = 0; for (int row = 0; row < getRowCount(); row ++) if (isSelected(row)) selected ++; return selected; } public int getSelectedRow() { for (int row = 0; row < getRowCount(); row ++) if (isSelected(row)) return row; return -1; } public static class TableEvent<T> { private Event iSourceEvent; private int iRow; private int iCol; private Element iTD; private Element iTR; private T iData; public TableEvent(Event sourceEvent, int row, int col, Element tr, Element td, T data) { iRow = row; iCol = col; iTR = tr; iTD = td; iData = data; iSourceEvent = sourceEvent; } public int getRow() { return iRow; } public int getCol() { return iCol; } public T getData() { return iData; } public Element getRowElement() { return iTR; } public Element getCellElement() { return iTD; } public Event getSourceEvent() { return iSourceEvent; } } public static interface MouseOverListener<T> { public void onMouseOver(TableEvent<T> event); } public void addMouseOverListener(MouseOverListener<T> mouseOverListener) { iMouseOverListeners.add(mouseOverListener); } public static interface MouseOutListener<T> { public void onMouseOut(TableEvent<T> event); } public void addMouseOutListener(MouseOutListener<T> mouseOutListener) { iMouseOutListeners.add(mouseOutListener); } public static interface MouseClickListener<T> { public void onMouseClick(TableEvent<T> event); } public void addMouseClickListener(MouseClickListener<T> mouseClickListener) { iMouseClickListeners.add(mouseClickListener); } public static class DataChangedEvent<T> { private T iData; private int iRow; public DataChangedEvent(T data, int row) { iData = data; iRow = row; } public T getData() { return iData; } public int getRow() { return iRow; } } public interface DataChangedListener<T> { public void onDataInserted(DataChangedEvent<T> event); public void onDataRemoved(DataChangedEvent<T> event); public void onDataMoved(List<DataChangedEvent<T>> events); public void onDataSorted(List<DataChangedEvent<T>> events); } public void addDataChangedListener(DataChangedListener<T> listener) { iDataChangedListeners.add(listener); } public static interface HasFocus { public boolean focus(); } public static interface HasHint { public String getHint(); } public static interface HasColSpan { public int getColSpan(); } public static interface HasCellAlignment { public HorizontalAlignmentConstant getCellAlignment(); } public static interface HasStyleName { public String getStyleName(); } public static interface HasAdditionalStyleNames { public List<String> getAdditionalStyleNames(); } public static interface HasDataUpdate { public void update(); } public static interface HintProvider<T> { Widget getHint(TableEvent<T> event); } public void setHintProvider(HintProvider<T> hintProvider) { iHintProvider = hintProvider; } } --- NEW FILE: UniTimeDialogBox.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.widgets; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.logical.shared.HasOpenHandlers; import com.google.gwt.event.logical.shared.OpenEvent; import com.google.gwt.event.logical.shared.OpenHandler; import com.google.gwt.event.shared.HandlerRegistration; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Event.NativePreviewEvent; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Widget; /** * @author Tomas Muller */ public class UniTimeDialogBox extends DialogBox implements HasOpenHandlers<UniTimeDialogBox> { private FlowPanel iContainer, iControls; private Anchor iClose; private boolean iEscapeToHide = false; private Command iSubmitHandler = null; public UniTimeDialogBox(boolean autoHide, boolean modal) { super(autoHide, modal); setAnimationEnabled(true); setGlassEnabled(true); iContainer = new FlowPanel(); iContainer.addStyleName("dialogContainer"); iClose = new Anchor(); iClose.setTitle("Click here or outside of the dialog to close."); iClose.setStyleName("close"); iClose.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { onCloseClick(event); } }); iClose.setVisible(autoHide); iControls = new FlowPanel(); iControls.setStyleName("dialogControls"); iControls.add(iClose); } public void setAutoHideEnabled(boolean autoHide) { super.setAutoHideEnabled(autoHide); iClose.setVisible(autoHide); } public void setEscapeToHide(boolean escapeToHide) { iEscapeToHide = escapeToHide; } public boolean isEscapeToHide() { return iEscapeToHide; } public void setEnterToSubmit(Command submitCommand) { iSubmitHandler = submitCommand; } public boolean isEnterToSubmit() { return iSubmitHandler != null; } public void setWidget(Widget widget) { if (iContainer.getWidgetCount() == 0) { iContainer.add(iControls); super.setWidget(iContainer); } else { while (iContainer.getWidgetCount() > 1) { iContainer.remove(1); } } iContainer.add(widget); } protected void onCloseClick(ClickEvent event) { hide(); } public HandlerRegistration addOpenHandler(OpenHandler<UniTimeDialogBox> handler) { return addHandler(handler, OpenEvent.getType()); } @Override public void show() { boolean fireOpen = !isShowing(); super.show(); if (fireOpen) { OpenEvent.fire(this, this); } } @Override protected void onPreviewNativeEvent(NativePreviewEvent event) { super.onPreviewNativeEvent(event); if (isEscapeToHide() && DOM.eventGetKeyCode((Event)event.getNativeEvent()) == KeyCodes.KEY_ESCAPE) hide(); if (isEnterToSubmit() && DOM.eventGetKeyCode((Event)event.getNativeEvent()) == KeyCodes.KEY_ENTER) iSubmitHandler.execute(); } } --- NEW FILE: UniTimeTableHeader.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.widgets; import java.util.ArrayList; import java.util.List; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasAdditionalStyleNames; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasCellAlignment; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasColSpan; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasStyleName; import com.google.gwt.dom.client.Style.Cursor; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.MenuBar; import com.google.gwt.user.client.ui.MenuItem; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.Widget; /** * @author Tomas Muller */ public class UniTimeTableHeader extends HTML implements HasStyleName, HasCellAlignment, HasColSpan, HasAdditionalStyleNames { private int iColSpan = 1; private HorizontalAlignmentConstant iAlign; private List<Operation> iOperations = new ArrayList<Operation>(); private List<String> iStyleNames = new ArrayList<String>(); public UniTimeTableHeader(String title, int colSpan, HorizontalAlignmentConstant align) { super(title, false); iColSpan = colSpan; iAlign = align; addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { final PopupPanel popup = new PopupPanel(true); List<Operation> operations = getOperations(); if (operations.isEmpty()) return; boolean first = true; MenuBar menu = new MenuBar(true); for (final Operation op: operations) { if (!op.isApplicable()) continue; if (op.hasSeparator() && !first) menu.addSeparator(); first = false; MenuItem item = new MenuItem(op.getName(), true, new Command() { @Override public void execute() { popup.hide(); op.execute(); } }); item.getElement().getStyle().setCursor(Cursor.POINTER); menu.addItem(item); } if (first) return; menu.setVisible(true); popup.add(menu); popup.showRelativeTo((Widget)event.getSource()); } }); } public UniTimeTableHeader(String title) { this(title, 1, HasHorizontalAlignment.ALIGN_LEFT); } public UniTimeTableHeader(String title, int colSpan) { this(title, colSpan, HasHorizontalAlignment.ALIGN_LEFT); } public UniTimeTableHeader(String title, HorizontalAlignmentConstant align) { this(title, 1, align); } public int getColSpan() { return iColSpan; } public HorizontalAlignmentConstant getCellAlignment() { return iAlign; } public String getStyleName() { return "unitime-ClickableTableHeader"; } public void addOperation(Operation operation) { iOperations.add(operation); } ... [truncated message content] |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:11:01
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/client/sectioning In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/client/sectioning Added Files: StudentSectioningPage.java StudentSectioningWidget.java TimeGrid.java CourseRequestsTable.java CourseSelectionBox.java AcademicSessionSelector.java UserAuthentication.java FreeTimePicker.java SuggestionsBox.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: CourseSelectionBox.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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/>. * */ [...1146 lines suppressed...] f.setLength(endTime - startTime); // 6 * (endTime - startTime)); ret.add(f); lastDays = days; } return ret; } public String freeTimesToString(ArrayList<CourseRequestInterface.FreeTime> freeTimes) { String ret = ""; String lastDays = null; for (CourseRequestInterface.FreeTime ft: freeTimes) { if (ret.length() > 0) ret += ", "; String days = ft.getDaysString(CONSTANTS.shortDays()); if (ft.getDays().size() == CONSTANTS.freeTimeDays().length && !ft.getDays().contains(5) && !ft.getDays().contains(6)) days = ""; ret += (days.isEmpty() || days.equals(lastDays) ? "" : days + " ") + ft.getStartString() + " - " + ft.getEndString(); lastDays = days; } return CONSTANTS.freePrefix() + ret; } } --- NEW FILE: StudentSectioningWidget.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.sectioning; import java.util.ArrayList; import java.util.Iterator; import org.unitime.timetable.gwt.client.ToolBox; import org.unitime.timetable.gwt.client.sectioning.TimeGrid.Meeting; import org.unitime.timetable.gwt.client.widgets.ImageLink; import org.unitime.timetable.gwt.client.widgets.UniTimeTabPabel; import org.unitime.timetable.gwt.client.widgets.WebTable; import org.unitime.timetable.gwt.resources.StudentSectioningConstants; import org.unitime.timetable.gwt.resources.StudentSectioningMessages; import org.unitime.timetable.gwt.resources.StudentSectioningResources; import org.unitime.timetable.gwt.services.SectioningService; import org.unitime.timetable.gwt.services.SectioningServiceAsync; import org.unitime.timetable.gwt.shared.ClassAssignmentInterface; import org.unitime.timetable.gwt.shared.CourseRequestInterface; import org.unitime.timetable.gwt.shared.AcademicSessionProvider.AcademicSessionChangeEvent; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.RunAsyncCallback; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FocusPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.VerticalPanel; /** * @author Tomas Muller */ public class StudentSectioningWidget extends Composite { public static final StudentSectioningResources RESOURCES = GWT.create(StudentSectioningResources.class); public static final StudentSectioningMessages MESSAGES = GWT.create(StudentSectioningMessages.class); public static final StudentSectioningConstants CONSTANTS = GWT.create(StudentSectioningConstants.class); private final SectioningServiceAsync iSectioningService = GWT.create(SectioningService.class); private AcademicSessionSelector iSessionSelector; private UserAuthentication iUserAuthentication; private VerticalPanel iPanel; private HorizontalPanel iFooter; private Button iPrev, iNext, iEnroll, iPrint, iExport, iSave; private HTML iErrorMessage; private UniTimeTabPabel iAssignmentPanel; private FocusPanel iAssignmentPanelWithFocus; private ImageLink iCalendar; private CourseRequestsTable iCourseRequests; private WebTable iAssignments; private TimeGrid iAssignmentGrid; private SuggestionsBox iSuggestionsBox; private ArrayList<ClassAssignmentInterface.ClassAssignment> iLastResult; private ClassAssignmentInterface iLastAssignment; private ArrayList<HistoryItem> iHistory = new ArrayList<HistoryItem>(); private int iAssignmentTab = 0; private boolean iInRestore = false; public StudentSectioningWidget(AcademicSessionSelector sessionSelector, UserAuthentication userAuthentication, StudentSectioningPage.Mode mode) { iSessionSelector = sessionSelector; iUserAuthentication = userAuthentication; iPanel = new VerticalPanel(); iCourseRequests = new CourseRequestsTable(iSessionSelector); iPanel.add(iCourseRequests); iFooter = new HorizontalPanel(); iFooter.setStyleName("unitime-MainTableBottomHeader"); iPrev = new Button(MESSAGES.buttonPrev()); iPrev.setWidth("75"); iPrev.setAccessKey('p'); iPrev.setVisible(false); iFooter.add(iPrev); iErrorMessage = new HTML(); iErrorMessage.setWidth("100%"); iErrorMessage.setStyleName("unitime-ErrorMessage"); iFooter.add(iErrorMessage); HorizontalPanel rightFooterPanel = new HorizontalPanel(); iFooter.add(rightFooterPanel); iFooter.setCellHorizontalAlignment(rightFooterPanel, HasHorizontalAlignment.ALIGN_RIGHT); iNext = new Button(MESSAGES.buttonNext()); iNext.setWidth("75"); iNext.setAccessKey('n'); rightFooterPanel.add(iNext); iNext.setVisible(mode.isSectioning()); iSave = new Button(MESSAGES.buttonSave()); iSave.setWidth("75"); iSave.setAccessKey('s'); rightFooterPanel.add(iSave); iSave.setVisible(!mode.isSectioning()); iEnroll = new Button(MESSAGES.buttonEnroll()); iEnroll.setWidth("75"); iEnroll.setAccessKey('e'); iEnroll.setVisible(false); rightFooterPanel.add(iEnroll); iPrint = new Button(MESSAGES.buttonPrint()); iPrint.setWidth("75"); iPrint.setAccessKey('r'); iPrint.setVisible(false); iPrint.getElement().getStyle().setMarginLeft(4, Unit.PX); rightFooterPanel.add(iPrint); iExport = new Button(MESSAGES.buttonExport()); iExport.setWidth("75"); iExport.setAccessKey('x'); iExport.setVisible(false); iExport.getElement().getStyle().setMarginLeft(4, Unit.PX); rightFooterPanel.add(iExport); iPanel.add(iFooter); iLastResult = new ArrayList<ClassAssignmentInterface.ClassAssignment>(); initWidget(iPanel); initAsync(); } private void initAsync() { GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { init(); } public void onFailure(Throwable reason) { Label error = new Label(MESSAGES.failedToLoadTheApp(reason.getMessage())); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("loading").setVisible(false); RootPanel.get("body").add(error); } }); } private void addHistory() { if (iInRestore) return; iHistory.add(new HistoryItem()); History.newItem(String.valueOf(iHistory.size() - 1), false); } private void updateHistory() { if (iInRestore) return; if (!iHistory.isEmpty()) iHistory.remove(iHistory.size() - 1); addHistory(); } private void init() { iCalendar = new ImageLink(); iCalendar.setImage(new Image(RESOURCES.calendar())); iCalendar.setTarget(null); iCalendar.setTitle("Export in iCalendar format."); iAssignments = new WebTable(); iAssignments.setHeader(new WebTable.Row( new WebTable.Cell(MESSAGES.colLock(), 1, "15"), new WebTable.Cell(MESSAGES.colSubject(), 1, "75"), new WebTable.Cell(MESSAGES.colCourse(), 1, "75"), new WebTable.Cell(MESSAGES.colSubpart(), 1, "50"), new WebTable.Cell(MESSAGES.colClass(), 1, "75"), new WebTable.Cell(MESSAGES.colLimit(), 1, "60"), new WebTable.Cell(MESSAGES.colDays(), 1, "50"), new WebTable.Cell(MESSAGES.colStart(), 1, "75"), new WebTable.Cell(MESSAGES.colEnd(), 1, "75"), new WebTable.Cell(MESSAGES.colDate(), 1, "75"), new WebTable.Cell(MESSAGES.colRoom(), 1, "100"), new WebTable.Cell(MESSAGES.colInstructor(), 1, "100"), new WebTable.Cell(MESSAGES.colParent(), 1, "75"), new WebTable.WidgetCell(iCalendar, MESSAGES.colSaved(), 1, "10"), new WebTable.Cell(MESSAGES.colHighDemand(), 1, "10") )); iAssignmentPanel = new UniTimeTabPabel(); iAssignmentPanel.add(iAssignments, MESSAGES.tabClasses(), true); iAssignmentPanel.selectTab(0); iAssignmentGrid = new TimeGrid(); iAssignmentPanel.add(iAssignmentGrid, MESSAGES.tabTimetable(), true); iAssignmentPanel.addSelectionHandler(new SelectionHandler<Integer>() { public void onSelection(SelectionEvent<Integer> event) { iAssignmentTab = event.getSelectedItem(); if (event.getSelectedItem() == 1) iAssignmentGrid.scrollDown(); addHistory(); } }); iAssignmentPanelWithFocus = new FocusPanel(iAssignmentPanel); iAssignmentPanelWithFocus.setStyleName("unitime-FocusPanel"); iPrev.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { prev(); addHistory(); } }); iNext.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { iCourseRequests.changeTip(); iErrorMessage.setHTML(""); iCourseRequests.getValidator().validate(new AsyncCallback<Boolean>() { public void onSuccess(Boolean result) { updateHistory(); if (result) { iSectioningService.saveRequest(iCourseRequests.getRequest(), new AsyncCallback<Boolean>() { public void onSuccess(Boolean result) { if (result) { iErrorMessage.setHTML("<font color='blue'>" + MESSAGES.saveRequestsOK() + "</font>"); iErrorMessage.setVisible(true); } } public void onFailure(Throwable caught) { iErrorMessage.setHTML(MESSAGES.saveRequestsFail(caught.getMessage())); iErrorMessage.setVisible(true); } }); iSectioningService.section(iCourseRequests.getRequest(), iLastResult, new AsyncCallback<ClassAssignmentInterface>() { public void onFailure(Throwable caught) { iErrorMessage.setHTML(caught.getMessage()); iErrorMessage.setVisible(true); iCourseRequests.getValidator().hide(); updateHistory(); } public void onSuccess(ClassAssignmentInterface result) { fillIn(result); addHistory(); } }); } else { iErrorMessage.setHTML(MESSAGES.validationFailed()); iErrorMessage.setVisible(true); iCourseRequests.getValidator().hide(); updateHistory(); } } public void onFailure(Throwable caught) { iErrorMessage.setHTML(MESSAGES.validationFailed()); iErrorMessage.setVisible(true); iCourseRequests.getValidator().hide(); updateHistory(); } }); } }); iAssignmentPanelWithFocus.addKeyUpHandler(new KeyUpHandler() { public void onKeyUp(KeyUpEvent event) { if (event.getNativeKeyCode()==KeyCodes.KEY_DOWN) { iAssignments.setSelectedRow(iAssignments.getSelectedRow()+1); } if (event.getNativeKeyCode()==KeyCodes.KEY_UP) { iAssignments.setSelectedRow(iAssignments.getSelectedRow()==0?iAssignments.getRowsCount()-1:iAssignments.getSelectedRow()-1); } if (event.getNativeKeyCode()==KeyCodes.KEY_ENTER) { updateHistory(); showSuggestionsAsync(iAssignments.getSelectedRow()); } if (event.getNativeEvent().getCtrlKey() && (event.getNativeKeyCode()=='l' || event.getNativeKeyCode()=='L')) { iAssignmentPanel.selectTab(0); event.preventDefault(); } if (event.getNativeEvent().getCtrlKey() && (event.getNativeKeyCode()=='t' || event.getNativeKeyCode()=='T')) { iAssignmentPanel.selectTab(1); event.preventDefault(); } } }); iAssignments.addRowClickHandler(new WebTable.RowClickHandler() { public void onRowClick(WebTable.RowClickEvent event) { updateHistory(); showSuggestionsAsync(event.getRowIdx()); } }); iAssignmentGrid.addMeetingClickHandler(new TimeGrid.MeetingClickHandler() { public void onMeetingClick(TimeGrid.MeetingClickEvent event) { updateHistory(); showSuggestionsAsync(event.getRowIndex()); } }); iAssignmentGrid.addPinClickHandler(new TimeGrid.PinClickHandler() { public void onPinClick(TimeGrid.PinClickEvent event) { ((CheckBox)iAssignments.getRows()[event.getRowIndex()].getCell(0).getWidget()).setValue(event.isPinChecked()); iLastResult.get(event.getRowIndex()).setPinned(event.isPinChecked()); updateHistory(); } }); iEnroll.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { iSectioningService.enroll(iCourseRequests.getRequest(), iLastResult, new AsyncCallback<ArrayList<Long>>() { public void onSuccess(ArrayList<Long> result) { int idx = 0; for (ClassAssignmentInterface.ClassAssignment ca: iLastResult) { if (ca.getClassId() != null) { ca.setSaved(result.contains(ca.getClassId())); WebTable.Row row = iAssignments.getRows()[idx]; WebTable.Cell c = (ca.isSaved() ? new WebTable.IconCell(RESOURCES.saved(), null, null) : new WebTable.Cell("")); c.setStyleName(row.getCell(row.getNrCells() - 1).getStyleName()); row.setCell(row.getNrCells() - 2, c); ArrayList<Meeting> meetings = iAssignmentGrid.getMeetings(idx); if (meetings != null) for (TimeGrid.Meeting m: meetings) m.setSaved(ca.isSaved()); } idx++; } iErrorMessage.setHTML("<font color='blue'>" + MESSAGES.enrollOK() + "</font>"); iErrorMessage.setVisible(true); updateHistory(); } public void onFailure(Throwable caught) { iErrorMessage.setHTML(MESSAGES.enrollFailed(caught.getMessage())); iErrorMessage.setVisible(true); updateHistory(); } }); } }); iPrint.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { boolean allSaved = true; for (ClassAssignmentInterface.ClassAssignment clazz: iLastResult) { if (!clazz.isFreeTime() && clazz.isAssigned() && !clazz.isSaved()) allSaved = false; } ToolBox.print((allSaved ? MESSAGES.studentSchedule() : MESSAGES.studentScheduleNotEnrolled()), (CONSTANTS.printReportShowUserName() ? iUserAuthentication.getUser() : ""), iSessionSelector.getAcademicSessionName(), iAssignmentGrid.getPrintWidget(), iAssignments.getPrintWidget(0, 5, 13, 14), iErrorMessage); } }); iExport.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { ToolBox.open(iCalendar.getUrl()); } }); History.addValueChangeHandler(new ValueChangeHandler<String>() { public void onValueChange(ValueChangeEvent<String> event) { if (!event.getValue().isEmpty()) { int item = iHistory.size() - 1; try { item = Integer.parseInt(event.getValue()); } catch (NumberFormatException e) {} if (item < 0) item = 0; if (item >= iHistory.size()) item = iHistory.size() - 1; if (item >= 0) iHistory.get(item).restore(); } else { iCourseRequests.clear(); if (!iNext.isVisible()) prev(); } } }); addHistory(); iSessionSelector.addAcademicSessionChangeHandler(new AcademicSessionSelector.AcademicSessionChangeHandler() { public void onAcademicSessionChange(AcademicSessionChangeEvent event) { addHistory(); } }); iSave.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { iCourseRequests.changeTip(); iErrorMessage.setHTML(""); iCourseRequests.getValidator().validate(new AsyncCallback<Boolean>() { public void onSuccess(Boolean result) { updateHistory(); if (result) { iSectioningService.saveRequest(iCourseRequests.getRequest(), new AsyncCallback<Boolean>() { public void onSuccess(Boolean result) { if (result) { iErrorMessage.setHTML("<font color='blue'>" + MESSAGES.saveRequestsOK() + "</font>"); iErrorMessage.setVisible(true); } iCourseRequests.getValidator().hide(); } public void onFailure(Throwable caught) { iErrorMessage.setHTML(MESSAGES.saveRequestsFail(caught.getMessage())); iErrorMessage.setVisible(true); iCourseRequests.getValidator().hide(); } }); } else { iErrorMessage.setHTML(MESSAGES.validationFailed()); iErrorMessage.setVisible(true); iCourseRequests.getValidator().hide(); updateHistory(); } } public void onFailure(Throwable caught) { iErrorMessage.setHTML(MESSAGES.validationFailed()); iErrorMessage.setVisible(true); iCourseRequests.getValidator().hide(); updateHistory(); } }); } }); } public void openSuggestionsBox(int rowIndex) { if (iSuggestionsBox == null) { iSuggestionsBox = new SuggestionsBox(); iSuggestionsBox.addCloseHandler(new CloseHandler<PopupPanel>() { public void onClose(CloseEvent<PopupPanel> event) { Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { iAssignmentPanelWithFocus.setFocus(true); } }); } }); iSuggestionsBox.addSuggestionSelectedHandler(new SuggestionsBox.SuggestionSelectedHandler() { public void onSuggestionSelected(SuggestionsBox.SuggestionSelectedEvent event) { ClassAssignmentInterface result = event.getSuggestion(); fillIn(result); addHistory(); } }); } iAssignments.setSelectedRow(rowIndex); iErrorMessage.setVisible(false); iSuggestionsBox.setRow(iCourseRequests.getRequest(), iLastResult, rowIndex); iSuggestionsBox.center(); } private void fillIn(ClassAssignmentInterface result) { iLastResult.clear(); iLastAssignment = result; String calendarUrl = GWT.getHostPageBaseURL() + "calendar?sid=" + iSessionSelector.getAcademicSessionId() + "&cid="; String ftParam = "&ft="; if (!result.getCourseAssignments().isEmpty()) { ArrayList<WebTable.Row> rows = new ArrayList<WebTable.Row>(); iAssignmentGrid.clear(); for (ClassAssignmentInterface.CourseAssignment course: result.getCourseAssignments()) { if (course.isAssigned()) { boolean firstClazz = true; for (ClassAssignmentInterface.ClassAssignment clazz: course.getClassAssignments()) { if (clazz.getClassId() != null) calendarUrl += clazz.getCourseId() + "-" + clazz.getClassId() + ","; else if (clazz.isFreeTime()) ftParam += clazz.getDaysString(CONSTANTS.shortDays()) + "-" + clazz.getStart() + "-" + clazz.getLength() + ","; String style = "unitime-ClassRow" + (firstClazz && !rows.isEmpty() ? "First": ""); final WebTable.Row row = new WebTable.Row( new WebTable.CheckboxCell(clazz.isPinned()), new WebTable.Cell(firstClazz ? course.isFreeTime() ? MESSAGES.freeTimeSubject() : course.getSubject() : ""), new WebTable.Cell(firstClazz ? course.isFreeTime() ? MESSAGES.freeTimeCourse() : course.getCourseNbr() : ""), new WebTable.Cell(clazz.getSubpart()), new WebTable.Cell(clazz.getSection()), new WebTable.Cell(clazz.getLimitString()), new WebTable.Cell(clazz.getDaysString(CONSTANTS.shortDays())), new WebTable.Cell(clazz.getStartString()), new WebTable.Cell(clazz.getEndString()), new WebTable.Cell(clazz.getDatePattern()), (clazz.hasDistanceConflict() ? new WebTable.IconCell(RESOURCES.distantConflict(), MESSAGES.backToBackDistance(clazz.getBackToBackRooms(), clazz.getBackToBackDistance()), clazz.getRooms(", ")) : new WebTable.Cell(clazz.getRooms(", "))), new WebTable.InstructorCell(clazz.getInstructors(), clazz.getInstructorEmails(), ", "), new WebTable.Cell(clazz.getParentSection()), (clazz.isSaved() ? new WebTable.IconCell(RESOURCES.saved(), null, null) : new WebTable.Cell("")), (clazz.isOfHighDemand() ? new WebTable.IconCell(RESOURCES.highDemand(), MESSAGES.highDemand(clazz.getExpected(), clazz.getAvailableLimit()), null) : new WebTable.Cell(""))); final ArrayList<TimeGrid.Meeting> meetings = iAssignmentGrid.addClass(clazz, rows.size()); // row.setId(course.isFreeTime() ? "Free " + clazz.getDaysString() + " " +clazz.getStartString() + " - " + clazz.getEndString() : course.getCourseId() + ":" + clazz.getClassId()); final int index = rows.size(); ((CheckBox)row.getCell(0).getWidget()).addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { Boolean checked = Boolean.valueOf(row.getCell(0).getValue()); if (meetings == null) { iLastResult.get(index).setPinned(checked); } else { for (Meeting m: meetings) { m.setPinned(checked); iLastResult.get(m.getIndex()).setPinned(checked); } } } }); rows.add(row); iLastResult.add(clazz); for (WebTable.Cell cell: row.getCells()) cell.setStyleName(style); firstClazz = false; } } else { String style = "unitime-ClassRowRed" + (!rows.isEmpty() ? "First": ""); WebTable.Row row = null; String unassignedMessage = ""; if (course.getOverlaps()!=null && !course.getOverlaps().isEmpty()) { unassignedMessage = MESSAGES.conflictWith(); for (Iterator<String> i = course.getOverlaps().iterator(); i.hasNext();) { String x = i.next(); if (course.getOverlaps().size() > 1 && !i.hasNext()) unassignedMessage += MESSAGES.conflictWithOr(); unassignedMessage += x; if (i.hasNext()) unassignedMessage += ", "; } if (course.getInstead() != null) unassignedMessage += MESSAGES.conflictAssignedAlternative(course.getInstead()); unassignedMessage += "."; } else if (course.isNotAvailable()) { unassignedMessage = MESSAGES.classNotAvailable(); } for (ClassAssignmentInterface.ClassAssignment clazz: course.getClassAssignments()) { row = new WebTable.Row( new WebTable.Cell(null), new WebTable.Cell(course.isFreeTime() ? MESSAGES.freeTimeSubject() : course.getSubject()), new WebTable.Cell(course.isFreeTime() ? MESSAGES.freeTimeCourse() : course.getCourseNbr()), new WebTable.Cell(clazz.getSubpart()), new WebTable.Cell(clazz.getSection()), new WebTable.Cell(clazz.getLimitString()), new WebTable.Cell(clazz.getDaysString(CONSTANTS.shortDays())), new WebTable.Cell(clazz.getStartString()), new WebTable.Cell(clazz.getEndString()), new WebTable.Cell(clazz.getDatePattern()), new WebTable.Cell(unassignedMessage, 5, null)); row.setId(course.isFreeTime() ? "Free " + clazz.getDaysString(CONSTANTS.shortDays()) + " " +clazz.getStartString() + " - " + clazz.getEndString() : course.getCourseId() + ":" + clazz.getClassId()); iLastResult.add(clazz); break; } if (row == null) { row = new WebTable.Row( new WebTable.Cell(null), new WebTable.Cell(course.getSubject()), new WebTable.Cell(course.getCourseNbr()), new WebTable.Cell(unassignedMessage, 12, null)); row.setId(course.getCourseId().toString()); iLastResult.add(course.addClassAssignment()); } for (WebTable.Cell cell: row.getCells()) cell.setStyleName(style); row.getCell(row.getNrCells() - 1).setStyleName("unitime-ClassRowProblem" + (!rows.isEmpty() ? "First": "")); rows.add(row); } } WebTable.Row[] rowArray = new WebTable.Row[rows.size()]; int idx = 0; for (WebTable.Row row: rows) rowArray[idx++] = row; iAssignmentGrid.shrink(); iAssignmentPanel.setWidth(iAssignmentGrid.getWidth()); iAssignments.setData(rowArray); iCourseRequests.getValidator().hide(); iPanel.remove(iCourseRequests); iPanel.insert(iAssignmentPanelWithFocus, 0); iPrev.setVisible(true); iEnroll.setVisible(true); iPrint.setVisible(true); iExport.setVisible(true); iNext.setVisible(false); iAssignmentGrid.scrollDown(); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { iAssignmentPanelWithFocus.setFocus(true); } }); if (calendarUrl.endsWith(",")) calendarUrl = calendarUrl.substring(0, calendarUrl.length() - 1); calendarUrl += ftParam; if (calendarUrl.endsWith(",")) calendarUrl = calendarUrl.substring(0, calendarUrl.length() - 1); iAssignmentGrid.setCalendarUrl(calendarUrl); iCalendar.setUrl(calendarUrl); } else { iErrorMessage.setHTML(MESSAGES.noSchedule()); iCourseRequests.getValidator().hide(); } } public void prev() { iPanel.remove(iAssignmentPanelWithFocus); iPanel.insert(iCourseRequests, 0); iPrev.setVisible(false); iEnroll.setVisible(false); iPrint.setVisible(false); iExport.setVisible(false); iNext.setVisible(true); iErrorMessage.setVisible(false); } public void clear() { iCourseRequests.clear(); iLastResult.clear(); if (iPrev.isVisible()) { prev(); } } public void lastRequest(Long sessionId) { iSectioningService.lastRequest(sessionId, new AsyncCallback<CourseRequestInterface>() { public void onFailure(Throwable caught) { } public void onSuccess(CourseRequestInterface result) { iCourseRequests.setRequest(result); iSectioningService.lastResult(result.getAcademicSessionId(), new AsyncCallback<ArrayList<ClassAssignmentInterface.ClassAssignment>>() { public void onFailure(Throwable caught) {} public void onSuccess(ArrayList<ClassAssignmentInterface.ClassAssignment> result) { if (iNext.isVisible()) { iLastResult.clear(); iLastResult.addAll(result); } } }); } }); } public void showSuggestionsAsync(final int rowIndex) { if (rowIndex < 0) return; GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { openSuggestionsBox(rowIndex); } public void onFailure(Throwable reason) { Label error = new Label(MESSAGES.failedToLoadTheApp(reason.getMessage())); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("loading").setVisible(false); RootPanel.get("body").add(error); } }); } public class HistoryItem { private CourseRequestInterface iRequest; private ClassAssignmentInterface iAssignment; private boolean iFirstPage; private Long iSessionId; private String iUser; private String iError = null; private int iTab = 0; private HistoryItem() { iRequest = iCourseRequests.getRequest(); iAssignment = iLastAssignment; iFirstPage = iNext.isVisible(); iSessionId = iSessionSelector.getAcademicSessionId(); iUser = iUserAuthentication.getUser(); if (iErrorMessage.isVisible()) iError = iErrorMessage.getHTML(); iTab = iAssignmentTab; } public void restore() { iInRestore = true; iUserAuthentication.setUser(iUser, new AsyncCallback<Boolean>() { public void onSuccess(Boolean result) { if (result) { iSessionSelector.selectSession(iSessionId, new AsyncCallback<Boolean>() { public void onSuccess(Boolean result) { if (result) { iCourseRequests.setRequest(iRequest); if (iTab != iAssignmentTab) iAssignmentPanel.selectTab(iTab); if (iFirstPage) { if (!iNext.isVisible()) prev(); iCourseRequests.changeTip(); } else { if (iAssignment != null) fillIn(iAssignment); } if (iError != null) { iErrorMessage.setHTML(iError); iErrorMessage.setVisible(true); } } iInRestore = false; } public void onFailure(Throwable reason) { iInRestore = false; } }); } else { iInRestore = false; } } public void onFailure(Throwable reason) { iInRestore = false; } }); } } } --- NEW FILE: AcademicSessionSelector.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.sectioning; import java.util.Collection; import java.util.Vector; import org.unitime.timetable.gwt.client.widgets.WebTable; import org.unitime.timetable.gwt.resources.StudentSectioningMessages; import org.unitime.timetable.gwt.services.SectioningService; import org.unitime.timetable.gwt.services.SectioningServiceAsync; import org.unitime.timetable.gwt.shared.AcademicSessionProvider; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Event.NativePreviewEvent; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.Hidden; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.VerticalPanel; /** * @author Tomas Muller */ public class AcademicSessionSelector extends Composite implements AcademicSessionProvider { public static final StudentSectioningMessages MESSAGES = GWT.create(StudentSectioningMessages.class); private Label iSessionLabel; private Hidden iSessionId; private DialogBox iDialog; private WebTable iSessions; private String iName = null; private final SectioningServiceAsync iSectioningService = GWT.create(SectioningService.class); private Vector<AcademicSessionChangeHandler> iAcademicSessionChangeHandlers = new Vector<AcademicSessionChangeHandler>(); private StudentSectioningPage.Mode iMode; public AcademicSessionSelector(StudentSectioningPage.Mode mode) { iMode = mode; iSessionLabel = new Label(MESSAGES.sessionSelectorNoSession(), false); iSessionLabel.setStyleName("unitime-SessionSelector"); iSessionId = new Hidden("sessionId"); VerticalPanel vertical = new VerticalPanel(); vertical.add(iSessionLabel); vertical.add(iSessionId); Label hint = new Label(MESSAGES.sessionSelectorHint()); hint.setStyleName("unitime-Hint"); vertical.add(hint); iDialog = new MyDialogBox(); iDialog.setText(MESSAGES.sessionSelectorSelect()); iDialog.setAnimationEnabled(true); iDialog.setAutoHideEnabled(false); iDialog.setGlassEnabled(true); iDialog.setModal(true); iSessions = new WebTable(); iSessions.setHeader( new WebTable.Row( new WebTable.Cell(MESSAGES.colYear(), 1, "80"), new WebTable.Cell(MESSAGES.colTerm(), 1, "80"), new WebTable.Cell(MESSAGES.colCampus(), 1, "100") )); iSessions.setEmptyMessage(MESSAGES.sessionSelectorLoading()); iDialog.add(iSessions); ClickHandler ch = new ClickHandler() { public void onClick(ClickEvent event) { selectSession(); } }; iSessionLabel.addClickHandler(ch); hint.addClickHandler(ch); iSessions.addRowClickHandler(new WebTable.RowClickHandler() { public void onRowClick(WebTable.RowClickEvent event) { rowSelected(event.getRow()); } }); initWidget(vertical); } private void rowSelected(WebTable.Row row) { iDialog.hide(); iSessionLabel.setText(MESSAGES.sessionSelectorLabel(row.getCell(0).getValue(), row.getCell(1).getValue(), row.getCell(2).getValue())); iName = MESSAGES.sessionName(row.getCell(0).getValue(), row.getCell(1).getValue(), row.getCell(2).getValue()); boolean changed = !row.getId().equals(iSessionId.getValue()); iSessionId.setValue(row.getId()); if (changed) { AcademicSessionChangeEvent changeEvent = new AcademicSessionChangeEvent(Long.valueOf(row.getId())); for (AcademicSessionChangeHandler handler: iAcademicSessionChangeHandlers) handler.onAcademicSessionChange(changeEvent); } iSessions.setSelectedRow(row.getRowIdx()); } public void selectSession() { iDialog.setAutoHideEnabled(getAcademicSessionId()!=null); iSectioningService.listAcademicSessions(iMode.isSectioning(), new AsyncCallback<Collection<String[]>>() { public void onSuccess(Collection<String[]> result) { WebTable.Row[] records = new WebTable.Row[result.size()]; int idx = 0; int lastSession = -1; for (String[] record: result) { WebTable.Row row = new WebTable.Row(record[1], record[2], record[3]); row.setId(record[0]); if (row.getId().equals(iSessionId.getValue())) lastSession = idx; records[idx++] = row; } iSessions.setData(records); if (records.length == 1) iSessions.setSelectedRow(0); if (lastSession >= 0) iSessions.setSelectedRow(lastSession); if (records.length == 1) rowSelected(iSessions.getRows()[0]); else iDialog.center(); } public void onFailure(Throwable caught) { iSessions.clearData(true); iSessions.setEmptyMessage(caught.getMessage()); iDialog.center(); } }); } public void selectSession(final Long sessionId, final AsyncCallback<Boolean> callback) { if (sessionId == null) { selectSession(); callback.onSuccess(false); } else if (sessionId.equals(getAcademicSessionId())) { callback.onSuccess(true); } else { iSectioningService.listAcademicSessions(iMode.isSectioning(), new AsyncCallback<Collection<String[]>>() { public void onSuccess(Collection<String[]> result) { for (String[] record: result) { if (sessionId.toString().equals(record[0])) { selectSession(record); callback.onSuccess(true); return; } } selectSession(); callback.onSuccess(false); } public void onFailure(Throwable caught) { iSessions.clearData(true); iSessions.setEmptyMessage(caught.getMessage()); iDialog.center(); callback.onSuccess(false); } }); } } public void selectSession(String[] session) { if (session == null) { iSessionLabel.setText(MESSAGES.sessionSelectorNoSession()); iSessionId.setValue(null); iName = null; return; } iSessionLabel.setText(MESSAGES.sessionSelectorLabel(session[1], session[2], session[3])); iName = MESSAGES.sessionName(session[1], session[2], session[3]); iSessionId.setValue(session[0]); } public Long getAcademicSessionId() { try { return Long.valueOf(iSessionId.getValue()); } catch (Exception e) { return null; } } public String getAcademicSessionName() { return iName; } public static class AcademicSessionChangeEvent implements AcademicSessionProvider.AcademicSessionChangeEvent { private Long iSessionId; private AcademicSessionChangeEvent(Long sessionId) { iSessionId = sessionId; } public Long getNewAcademicSessionId() { return iSessionId; } } public void addAcademicSessionChangeHandler(AcademicSessionChangeHandler handler) { iAcademicSessionChangeHandlers.add(handler); } private class MyDialogBox extends DialogBox { private MyDialogBox() { super(); } protected void onPreviewNativeEvent(NativePreviewEvent event) { super.onPreviewNativeEvent(event); if (DOM.eventGetType((Event) event.getNativeEvent()) == Event.ONKEYUP) { if (DOM.eventGetKeyCode((Event) event.getNativeEvent()) == KeyCodes.KEY_DOWN) { iSessions.setSelectedRow(iSessions.getSelectedRow()+1); } else if (DOM.eventGetKeyCode((Event) event.getNativeEvent()) == KeyCodes.KEY_UP) { iSessions.setSelectedRow(iSessions.getSelectedRow()==0?iSessions.getRowsCount()-1:iSessions.getSelectedRow()-1); } else if (DOM.eventGetKeyCode((Event) event.getNativeEvent()) == KeyCodes.KEY_ENTER && iSessions.getSelectedRow()>=0) { rowSelected(iSessions.getRows()[iSessions.getSelectedRow()]); } else if (DOM.eventGetKeyCode((Event) event.getNativeEvent()) == KeyCodes.KEY_ESCAPE && getAcademicSessionId()!=null) { iDialog.hide(); } } } } } --- NEW FILE: SuggestionsBox.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.sectioning; import java.util.ArrayList; import java.util.Collection; import org.unitime.timetable.gwt.client.widgets.WebTable; import org.unitime.timetable.gwt.client.widgets.WebTable.RowClickEvent; import org.unitime.timetable.gwt.resources.StudentSectioningConstants; import org.unitime.timetable.gwt.resources.StudentSectioningMessages; import org.unitime.timetable.gwt.resources.StudentSectioningResources; import org.unitime.timetable.gwt.services.SectioningService; import org.unitime.timetable.gwt.services.SectioningServiceAsync; import org.unitime.timetable.gwt.shared.ClassAssignmentInterface; import org.unitime.timetable.gwt.shared.CourseRequestInterface; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Event.NativePreviewEvent; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.VerticalPanel; /** * @author Tomas Muller */ public class SuggestionsBox extends DialogBox { public static final StudentSectioningResources RESOURCES = GWT.create(StudentSectioningResources.class); public static final StudentSectioningMessages MESSAGES = GWT.create(StudentSectioningMessages.class); public static final StudentSectioningConstants CONSTANTS = GWT.create(StudentSectioningConstants.class); private final SectioningServiceAsync iSectioningService = GWT.create(SectioningService.class); private ClassAssignmentInterface.ClassAssignment iAssignment; private AsyncCallback<Collection<ClassAssignmentInterface>> iCallback = null; private ArrayList<ClassAssignmentInterface.ClassAssignment> iCurrent = null; private ArrayList<ClassAssignmentInterface> iResult = null; private ArrayList<SuggestionSelectedHandler> iSuggestionSelectedHandlers = new ArrayList<SuggestionSelectedHandler>(); private WebTable iSuggestions; private HTML iMessages; private ScrollPanel iSuggestionsScroll; private String iSource; public SuggestionsBox() { super(); setText("Alternatives"); setAnimationEnabled(true); setAutoHideEnabled(true); setGlassEnabled(true); setModal(true); VerticalPanel suggestionPanel = new VerticalPanel(); suggestionPanel.setSpacing(5); iSuggestions = new WebTable(); iSuggestions.setHeader(new WebTable.Row( new WebTable.Cell("", 1, "10"), new WebTable.Cell(MESSAGES.colSubject(), 1, "75"), new WebTable.Cell(MESSAGES.colCourse(), 1, "75"), new WebTable.Cell(MESSAGES.colSubpart(), 1, "50"), new WebTable.Cell(MESSAGES.colClass(), 1, "85"), new WebTable.Cell(MESSAGES.colTime(), 1, "175"), new WebTable.Cell(MESSAGES.colDate(), 1, "90"), new WebTable.Cell(MESSAGES.colRoom(), 1, "100"), new WebTable.Cell(MESSAGES.colInstructor(), 1, "100"), new WebTable.Cell(MESSAGES.colParent(), 1, "85"), new WebTable.Cell(MESSAGES.colSaved(), 1, "10"), new WebTable.Cell(MESSAGES.colHighDemand(), 1, "10") )); iSuggestions.setSelectSameIdRows(true); iSuggestions.setEmptyMessage(MESSAGES.suggestionsLoading()); iSuggestionsScroll = new ScrollPanel(iSuggestions); iSuggestionsScroll.setSize("950", "400"); iSuggestionsScroll.setStyleName("unitime-ScrollPanel"); suggestionPanel.add(iSuggestionsScroll); iMessages = new HTML(); suggestionPanel.add(iMessages); iCallback = new AsyncCallback<Collection<ClassAssignmentInterface>>() { public void onFailure(Throwable caught) { iSuggestions.clearData(true); iSuggestions.setEmptyMessage("<font color='red'>" + caught.getMessage() + "</font>"); iMessages.setHTML(""); } public void onSuccess(Collection<ClassAssignmentInterface> result) { iResult = (ArrayList<ClassAssignmentInterface>)result; if (result.isEmpty()) { iSuggestions.clearData(true); iSuggestions.setEmptyMessage(MESSAGES.suggestionsNoAlternative(iSource)); } else { ArrayList<WebTable.Row> rows = new ArrayList<WebTable.Row>(); int lastSize = 0; int suggestionId = 0; for (ClassAssignmentInterface suggestion: result) { if (suggestion.hasMessages()) iMessages.setHTML(suggestion.getMessages("<br>")); if (suggestion.getCourseAssignments().isEmpty()) { suggestionId++; continue; } for (ClassAssignmentInterface.CourseAssignment course: suggestion.getCourseAssignments()) { ArrayList<ClassAssignmentInterface.ClassAssignment> sameCourse = new ArrayList<ClassAssignmentInterface.ClassAssignment>(); if (!course.isFreeTime()) { for (ClassAssignmentInterface.ClassAssignment x: iCurrent) { if (course.getCourseId().equals(x.getCourseId())) sameCourse.add(x); } } else { ClassAssignmentInterface.ClassAssignment clazz = course.getClassAssignments().get(0); for (ClassAssignmentInterface.ClassAssignment x: iCurrent) { if (x.isFreeTime() && x.getDaysString(CONSTANTS.shortDays()).equals(clazz.getDaysString(CONSTANTS.shortDays())) && x.getStart() == clazz.getStart() && x.getLength() == clazz.getLength()) sameCourse.add(x); } } boolean selected = false; if (iAssignment.isFreeTime() && course.isFreeTime() && course.getClassAssignments().get(0).getDaysString(CONSTANTS.shortDays()).equals(iAssignment.getDaysString(CONSTANTS.shortDays())) && course.getClassAssignments().get(0).getStart() == iAssignment.getStart() && course.getClassAssignments().get(0).getLength() == iAssignment.getLength()) selected = true; if (!iAssignment.isFreeTime() && !iAssignment.isAssigned() && iAssignment.getCourseId().equals(course.getCourseId())) selected = true; if (course.isAssigned()) { int clazzIdx = 0; Long selectClassId = null; String selectSubpart = null; if (iAssignment.getSubpartId() != null && iAssignment.getCourseId().equals(course.getCourseId())) { for (ClassAssignmentInterface.ClassAssignment clazz: course.getClassAssignments()) { if (iAssignment.getSubpartId().equals(clazz.getSubpartId())) selectClassId = clazz.getClassId(); } if (selectClassId == null) for (ClassAssignmentInterface.ClassAssignment clazz: course.getClassAssignments()) { if (iAssignment.getSubpart().equals(clazz.getSubpart())) selectSubpart = clazz.getSubpart(); } if (selectClassId == null && selectSubpart == null) selected = true; } clazz: for (ClassAssignmentInterface.ClassAssignment clazz: course.getClassAssignments()) { if (selectClassId != null) selected = selectClassId.equals(clazz.getClassId()); if (selectSubpart != null) selected = selectSubpart.equals(clazz.getSubpart()); ClassAssignmentInterface.ClassAssignment old = null; for (ClassAssignmentInterface.ClassAssignment x: iCurrent) { if (course.isFreeTime()) { if (x.isFreeTime() && x.isCourseAssigned() && x.getDaysString(CONSTANTS.shortDays()).equals(clazz.getDaysString(CONSTANTS.shortDays())) && x.getStart() == clazz.getStart() && x.getLength() == clazz.getLength()) continue clazz; } else { if (clazz.getClassId().equals(x.getClassId())) continue clazz; // the exact same assignment if (clazz.getSubpartId().equals(x.getSubpartId())) { old = x; break; } } } if (old == null && clazzIdx < sameCourse.size()) old = sameCourse.get(clazzIdx); if (old == null && sameCourse.size() == 1 && !sameCourse.get(0).isAssigned()) old = sameCourse.get(0); final WebTable.Row row = new WebTable.Row( new WebTable.Cell(rows.size() == lastSize ? suggestionId + "." : ""), new WebTable.Cell(clazzIdx > 0 ? "" : course.isFreeTime() ? MESSAGES.freeTimeSubject() : course.getSubject()), new WebTable.Cell(clazzIdx > 0 ? "" : course.isFreeTime() ? MESSAGES.freeTimeCourse() : course.getCourseNbr()), new WebTable.Cell(compare(old == null ? null : old.getSubpart(), clazz == null ? null : clazz.getSubpart(), false)), new WebTable.Cell(compare(old == null ? null : old.getSection(), clazz == null ? null : clazz.getSection(), false)), new WebTable.Cell(compare(old == null ? null : old.getTimeString(CONSTANTS.shortDays()), clazz == null ? null : clazz.getTimeString(CONSTANTS.shortDays()), true)), new WebTable.Cell(compare(old == null ? null : old.getDatePattern(), clazz == null ? null : clazz.getDatePattern(), true)), (clazz != null && clazz.hasDistanceConflict() ? new WebTable.IconCell(RESOURCES.distantConflict(), MESSAGES.backToBackDistance(clazz.getBackToBackRooms(), clazz.getBackToBackDistance()), compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true)) : new WebTable.Cell(compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true))), new WebTable.InstructorCell(clazz == null ? null : clazz.getInstructors(), clazz == null ? null : clazz.getInstructorEmails(), ", "), new WebTable.Cell(compare(old == null ? null : old.getParentSection(), clazz == null ? null : clazz.getParentSection(), false)), (clazz != null && clazz.isSaved() ? new WebTable.IconCell(RESOURCES.saved(), null, null) : new WebTable.Cell("")), (clazz != null && clazz.isOfHighDemand() ? new WebTable.IconCell(RESOURCES.highDemand(), MESSAGES.highDemand(clazz.getExpected(), clazz.getAvailableLimit()), null) : new WebTable.Cell(""))); String style = "unitime-ClassRow" + (selected?"Blue":"") + (lastSize > 0 && rows.size() == lastSize ? "First2" : clazzIdx == 0 && !rows.isEmpty() ? "First": ""); row.setId(String.valueOf(suggestionId)); for (WebTable.Cell cell: row.getCells()) cell.setStyleName(style); row.getCell(0).setStyleName("unitime-ClassRow" + (lastSize > 0 && rows.size() == lastSize ? "First2" : "")); rows.add(row); clazzIdx++; } /* if (sameCourse.size() > course.getClassAssignments().size()) { for (int idx = course.getClassAssignments().size(); idx < sameCourse.size(); idx++) { ClassAssignmentInterface.ClassAssignment old = sameCourse.get(idx); ClassAssignmentInterface.ClassAssignment clazz = null; final WebTable.Row row = new WebTable.Row( new WebTable.Cell(rows.size() == lastSize ? suggestionId + "." : ""), new WebTable.Cell(clazzIdx > 0 ? "" : course.isFreeTime() ? "Free" : course.getSubject()), new WebTable.Cell(clazzIdx > 0 ? "" : course.isFreeTime() ? "Time" : course.getCourseNbr()), new WebTable.Cell(compare(old == null ? null : old.getSubpart(), clazz == null ? null : clazz.getSubpart(), false)), new WebTable.Cell(compare(old == null ? null : old.getSection(), clazz == null ? null : clazz.getSection(), false)), //new WebTable.Cell(compare(old == null ? null : old.getLimitString(), clazz == null ? null : clazz.getLimitString(), false)), new WebTable.Cell(compare(old == null ? null : old.getTimeString(), clazz == null ? null : clazz.getTimeString(), true)), new WebTable.Cell(compare(old == null ? null : old.getDatePattern(), clazz == null ? null : clazz.getDatePattern(), true)), (old != null && old.hasDistanceConflict() ? new WebTable.IconCell(RESOURCES.distantConflict(), old.getBackToBackDistanceMessage(), compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true)) : new WebTable.Cell(compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true))), new WebTable.Cell(compare(old == null ? null : old.getInstructors(", "), clazz == null ? null : clazz.getInstructors(", "), true)), new WebTable.Cell(compare(old == null ? null : old.getParentSection(), clazz == null ? null : clazz.getParentSection(), false)), (old != null && old.isSaved() ? new WebTable.IconCell(RESOURCES.saved(), null, null) : new WebTable.Cell(""))); row.setId(String.valueOf(suggestionId)); String style = "unitime-ClassRow" + (lastSize > 0 && rows.size() == lastSize ? "First2" : clazzIdx == 0 && !rows.isEmpty() ? "First": ""); for (WebTable.Cell cell: row.getCells()) cell.setStyleName(style); row.getCell(0).setStyleName("unitime-ClassRow" + (lastSize > 0 && rows.size() == lastSize ? "First2" : "")); rows.add(row); clazzIdx++; } } */ } else { if (sameCourse.isEmpty() || !sameCourse.get(0).isCourseAssigned()) continue; for (int idx = 0; idx < sameCourse.size(); idx++) { ClassAssignmentInterface.ClassAssignment old = sameCourse.get(idx); ClassAssignmentInterface.ClassAssignment clazz = null; WebTable.Row row = new WebTable.Row( new WebTable.Cell(rows.size() == lastSize ? suggestionId + "." : ""), new WebTable.Cell(idx > 0 ? "" : course.isFreeTime() ? MESSAGES.freeTimeSubject() : course.getSubject()), new WebTable.Cell(idx > 0 ? "" : course.isFreeTime() ? MESSAGES.freeTimeCourse() : course.getCourseNbr()), new WebTable.Cell(compare(old == null ? null : old.getSubpart(), clazz == null ? null : clazz.getSubpart(), false)), new WebTable.Cell(compare(old == null ? null : old.getSection(), clazz == null ? null : clazz.getSection(), false)), //new WebTable.Cell(compare(old == null ? null : old.getLimitString(), clazz == null ? null : clazz.getLimitString(), false)), new WebTable.Cell(compare(old == null ? null : old.getTimeString(CONSTANTS.shortDays()), clazz == null ? null : clazz.getTimeString(CONSTANTS.shortDays()), true)), new WebTable.Cell(compare(old == null ? null : old.getDatePattern(), clazz == null ? null : clazz.getDatePattern(), true)), (old != null && old.hasDistanceConflict() ? new WebTable.IconCell(RESOURCES.distantConflict(), MESSAGES.backToBackDistance(old.getBackToBackRooms(), old.getBackToBackDistance()), compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true)) : new WebTable.Cell(compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true))), //new WebTable.Cell(compare(old == null ? null : old.getInstructors(", "), clazz == null ? null : clazz.getInstructors(", "), true)), new WebTable.InstructorCell(old == null ? null : old.getInstructors(), old == null ? null : old.getInstructorEmails(), ", "), new WebTable.Cell(compare(old == null ? null : old.getParentSection(), clazz == null ? null : clazz.getParentSection(), false)), (old != null && old.isSaved() ? new WebTable.IconCell(RESOURCES.saved(), null, null) : new WebTable.Cell("")), (old != null && old.isOfHighDemand() ? new WebTable.IconCell(RESOURCES.highDemand(), MESSAGES.highDemand(old.getExpected(), old.getAvailableLimit()), null) : new WebTable.Cell(""))); row.setId(String.valueOf(suggestionId)); String style = "unitime-ClassRowRed" + (lastSize > 0 && rows.size() == lastSize ? "First2" : idx == 0 && !rows.isEmpty() ? "First": ""); for (WebTable.Cell cell: row.getCells()) cell.setStyleName(style); row.getCell(0).setStyleName("unitime-ClassRow" + (lastSize > 0 && rows.size() == lastSize ? "First2" : "")); rows.add(row); } } } Long lastCourseId = null; current: for (ClassAssignmentInterface.ClassAssignment old: iCurrent) { if (old.isFreeTime()) continue; for (ClassAssignmentInterface.CourseAssignment course: suggestion.getCourseAssignments()) { if (old.getCourseId().equals(course.getCourseId())) continue current; } ClassAssignmentInterface.ClassAssignment clazz = null; WebTable.Row row = new WebTable.Row( new WebTable.Cell(rows.size() == lastSize ? suggestionId + "." : ""), new WebTable.Cell(old.getCourseId().equals(lastCourseId) ? "" : old.isFreeTime() ? MESSAGES.freeTimeSubject() : old.getSubject()), new WebTable.Cell(old.getCourseId().equals(lastCourseId) ? "" : old.isFreeTime() ? MESSAGES.freeTimeCourse() : old.getCourseNbr()), new WebTable.Cell(compare(old == null ? null : old.getSubpart(), clazz == null ? null : clazz.getSubpart(), false)), new WebTable.Cell(compare(old == null ? null : old.getSection(), clazz == null ? null : clazz.getSection(), false)), //new WebTable.Cell(compare(old == null ? null : old.getLimitString(), clazz == null ? null : clazz.getLimitString(), false)), new WebTable.Cell(compare(old == null ? null : old.getTimeString(CONSTANTS.shortDays()), clazz == null ? null : clazz.getTimeString(CONSTANTS.shortDays()), true)), new WebTable.Cell(compare(old == null ? null : old.getDatePattern(), clazz == null ? null : clazz.getDatePattern(), true)), (old != null && old.hasDistanceConflict() ? new WebTable.IconCell(RESOURCES.distantConflict(), MESSAGES.backToBackDistance(old.getBackToBackRooms(), old.getBackToBackDistance()), compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true)) : new WebTable.Cell(compare(old == null ? null : old.getRooms(", "), clazz == null ? null : clazz.getRooms(", "), true))), //new WebTable.Cell(compare(old == null ? null : old.getInstructors(", "), clazz == null ? null : clazz.getInstructors(", "), true)), new WebTable.InstructorCell(old == null ? null : old.getInstructors(), old == null ? null : old.getInstructorEmails(), ", "), new WebTable.Cell(compare(old == null ? null : old.getParentSection(), clazz == null ? null : clazz.getParentSection(), false)), (old != null && old.isSaved() ? new WebTable.IconCell(RESOURCES.saved(), null, null) : new WebTable.Cell("")), (old != null && old.isOfHighDemand() ? new WebTable.IconCell(RESOURCES.highDemand(), MESSAGES.highDemand(old.getExpected(), old.getAvailableLimit()), null) : new WebTable.Cell(""))); row.setId(String.valueOf(suggestionId)); String style = "unitime-ClassRowRed" + (lastSize > 0 && rows.size() == lastSize ? "First2" : !old.getCourseId().equals(lastCourseId) && !rows.isEmpty() ? "First": ""); for (WebTable.Cell cell: row.getCells()) cell.setStyleName(style); row.getCell(0).setStyleName("unitime-ClassRow" + (lastSize > 0 && rows.size() == lastSize ? "First2" : "")); rows.add(row); lastCourseId = old.getCourseId(); } lastSize = rows.size(); suggestionId++; } WebTable.Row[] rowArray = new WebTable.Row[rows.size()]; int idx = 0; for (WebTable.Row row: rows) rowArray[idx++] = row; iSuggestions.setData(rowArray); if (rows.isEmpty()) iSuggestions.setEmptyMessage(MESSAGES.suggestionsNoAlternative(iSource)); } } }; iSuggestions.addRowClickHandler(new WebTable.RowClickHandler() { public void onRowClick(RowClickEvent event) { ClassAssignmentInterface suggestion = iResult.get(Integer.parseInt(event.getRow().getId())); SuggestionSelectedEvent e = new SuggestionSelectedEvent(suggestion); for (SuggestionSelectedHandler h: iSuggestionSelectedHandlers) h.onSuggestionSelected(e); hide(); } }); setWidget(suggestionPanel); } private String compare(String oldVal, String newVal, boolean both) { if (oldVal == null || oldVal.isEmpty()) return (newVal == null || newVal.isEmpty() ? null : newVal); if (newVal == null || newVal.isEmpty()) return "<font color='red'>" + oldVal + "</font>"; if (both) return oldVal.equals(newVal) ? newVal : (both ? oldVal + " → " : "") + newVal; else return oldVal.equals(newVal) ? newVal : newVal; } public void setRow(CourseRequestInterface request, ArrayList<ClassAssignmentInterface.ClassAssignment> rows, int index) { ClassAssignmentInterface.ClassAssignment row = rows.get(index); iAssignment = row; iCurrent = rows; iSource = null; if (row.isFreeTime()) { iSource = MESSAGES.freeTime(row.getDaysString(CONSTANTS.shortDays()), row.getStartString(), row.getEndString()); } else { if (row.getSubpart() == null) iSource = MESSAGES.course(row.getSubject(), row.getCourseNbr()); else iSource = MESS... [truncated message content] |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/server In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/server Added Files: UniTimePrincipal.java SimpleEditServlet.java SectioningServlet.java CalendarServlet.java CurriculaServlet.java SuggestionsBranchAndBound.java AcademicSessionInfo.java SuggestionSelection.java MenuServlet.java Query.java TimeSlot.java SectioningServerUpdater.java CourseInfo.java LookupServlet.java EventServlet.java CourseLoader.java SectioningServer.java DayCode.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: CourseLoader.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.TreeSet; import java.util.Vector; import net.sf.cpsolver.coursett.model.Placement; import net.sf.cpsolver.coursett.model.TimeLocation; import net.sf.cpsolver.ifs.util.ToolBox; import net.sf.cpsolver.studentsct.StudentSectioningModel; import net.sf.cpsolver.studentsct.model.Config; import net.sf.cpsolver.studentsct.model.Course; import net.sf.cpsolver.studentsct.model.CourseRequest; import net.sf.cpsolver.studentsct.model.Enrollment; import net.sf.cpsolver.studentsct.model.FreeTimeRequest; import net.sf.cpsolver.studentsct.model.Offering; import net.sf.cpsolver.studentsct.model.Request; import net.sf.cpsolver.studentsct.model.Section; import net.sf.cpsolver.studentsct.model.Student; import net.sf.cpsolver.studentsct.model.Subpart; import org.apache.log4j.Logger; import org.unitime.timetable.ApplicationProperties; import org.unitime.timetable.model.Assignment; import org.unitime.timetable.model.ClassInstructor; import org.unitime.timetable.model.Class_; import org.unitime.timetable.model.CourseDemand; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.CourseOfferingReservation; import org.unitime.timetable.model.DepartmentalInstructor; import org.unitime.timetable.model.InstrOfferingConfig; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.SchedulingSubpart; import org.unitime.timetable.model.SectioningInfo; import org.unitime.timetable.model.StudentClassEnrollment; import org.unitime.timetable.model.comparators.SchedulingSubpartComparator; /** * @author Tomas Muller */ public class CourseLoader { private static Logger sLog = Logger.getLogger(CourseLoader.class); private AcademicSessionInfo iAcademicSession; private Hashtable<Long, Course> iCourseTable; private Hashtable<Long, Section> iClassTable; private Hashtable<Long, Student> iStudentTable; private Hashtable<Long, CourseInfo> iCourseForId = null; private Hashtable<String, TreeSet<CourseInfo>> iCourseForName = null; private TreeSet<CourseInfo> iCourses = null; private StudentSectioningModel iModel = null; private Hashtable<Long, String> iCourseNames = new Hashtable<Long, String>(); CourseLoader(StudentSectioningModel model, AcademicSessionInfo academicSession, Hashtable<Long, Course> courseTable, Hashtable<Long, Section> classTable, Hashtable<Long, Student> studentTable, Hashtable<Long, CourseInfo> courseForId, Hashtable<String, TreeSet<CourseInfo>> courseForName, TreeSet<CourseInfo> courses) { iAcademicSession = academicSession; iCourseTable = courseTable; iClassTable = classTable; iStudentTable = studentTable; iCourseForId = courseForId; iCourseForName = courseForName; iCourses = courses; iModel = model; } @SuppressWarnings("unchecked") public void updateAll(org.hibernate.Session hibSession) { sLog.info("Updating course infos and the student sectining model for session "+iAcademicSession); synchronized (iCourseTable) { long t0 = System.currentTimeMillis(); iClassTable.clear(); iStudentTable.clear(); iCourseTable.clear(); iCourseForId.clear(); iCourseForName.clear(); iCourses.clear(); iCourseNames.clear(); List<InstructionalOffering> offerings = hibSession.createQuery( "select distinct io from InstructionalOffering io " + "left join fetch io.courseOfferings co " + "left join fetch co.courseReservations r "+ "left join fetch io.instrOfferingConfigs cf " + "left join fetch cf.schedulingSubparts ss " + "left join fetch ss.classes c " + "left join fetch c.assignments a " + "left join fetch a.rooms r " + "left join fetch c.classInstructors i " + "where io.session.uniqueId = :sessionId and io.notOffered = false") .setLong("sessionId", iAcademicSession.getUniqueId()).list(); for (InstructionalOffering offering: offerings) { if (offering.getInstrOfferingConfigs().isEmpty()) continue; for (Iterator<CourseOffering> j = offering.getCourseOfferings().iterator(); j.hasNext();) { CourseOffering course = j.next(); CourseInfo info = new CourseInfo(course); String courseName = (info.getSubjectArea() + " " + info.getCourseNbr()).toLowerCase(); TreeSet<CourseInfo> infos = iCourseForName.get(courseName); if (infos == null) { infos = new TreeSet<CourseInfo>(); iCourseForName.put(courseName, infos); } iCourses.add(info); infos.add(info); iCourseForId.put(course.getUniqueId(), info); if (infos.size() > 1) { for (CourseInfo i: infos) i.setHasUniqueName(false); } } } for (InstructionalOffering offering: offerings) loadOffering(hibSession, offering); if ("true".equals(ApplicationProperties.getProperty("unitime.enrollment.load", "true"))) { List<org.unitime.timetable.model.Student> students = hibSession.createQuery( "select distinct s from Student s " + "left join fetch s.courseDemands as cd " + "left join fetch cd.courseRequests as cr " + "left join fetch s.classEnrollments as e " + "where s.session.uniqueId=:sessionId"). setLong("sessionId",iAcademicSession.getUniqueId()).list(); for (org.unitime.timetable.model.Student student: students) { Student s = loadStudent(student); iModel.addStudent(s); assignStudent(s, student, true); } } List<SectioningInfo> infos = hibSession.createQuery( "select i from SectioningInfo i where i.clazz.schedulingSubpart.instrOfferingConfig.instructionalOffering.session.uniqueId = :sessionId") .setLong("sessionId", iAcademicSession.getUniqueId()) .list(); for (SectioningInfo info : infos) { Section section = iClassTable.get(info.getClazz().getUniqueId()); if (section != null) { section.setSpaceExpected(info.getNbrExpectedStudents()); section.setSpaceHeld(info.getNbrHoldingStudents()); if (section.getLimit() >= 0 && (section.getLimit() - section.getEnrollments().size()) <= section.getSpaceExpected()) sLog.info("Section " + section.getSubpart().getConfig().getOffering().getName() + " " + section.getSubpart().getName() + " " + section.getName() + " has high demand (limit: " + section.getLimit() + ", enrollment: " + section.getEnrollments().size() + ", expected: " + section.getSpaceExpected() + ")"); } } long t1 = System.currentTimeMillis(); sLog.info(" Update of session " + iAcademicSession + " done " + new DecimalFormat("0.0").format((t1 - t0) / 1000.0) + " seconds."); sLog.info(ToolBox.dict2string(iModel.getInfo(), 2)); } } private Offering loadOffering(org.hibernate.Session hibSession, InstructionalOffering io) { if (io.getInstrOfferingConfigs().isEmpty()) { return null; } String courseName = io.getCourseName(); Offering offering = new Offering(io.getUniqueId().longValue(), courseName); for (Iterator<CourseOffering> i = io.getCourseOfferings().iterator(); i.hasNext(); ) { CourseOffering co = i.next(); int projected = (co.getProjectedDemand()==null?0:co.getProjectedDemand().intValue()); boolean unlimited = false; int limit = 0; for (Iterator<InstrOfferingConfig> j = io.getInstrOfferingConfigs().iterator(); j.hasNext(); ) { InstrOfferingConfig ioc = j.next(); if (ioc.isUnlimitedEnrollment()) unlimited = true; limit += ioc.getLimit(); } for (Iterator<CourseOfferingReservation> k = co.getCourseReservations().iterator(); k.hasNext(); ) { CourseOfferingReservation reservation = k.next(); if (reservation.getCourseOffering().equals(co) && reservation.getReserved()!=null) limit = reservation.getReserved(); } if (limit >= 9999) unlimited = true; if (unlimited) limit=-1; Course course = new Course(co.getUniqueId(), co.getSubjectArea().getSubjectAreaAbbreviation(), co.getCourseNbr(), offering, limit, projected); iCourseTable.put(co.getUniqueId(), course); } Hashtable<Long,Section> class2section = new Hashtable<Long,Section>(); Hashtable<Long,Subpart> ss2subpart = new Hashtable<Long, Subpart>(); DecimalFormat df = new DecimalFormat("000"); for (Iterator<InstrOfferingConfig> i = io.getInstrOfferingConfigs().iterator(); i.hasNext(); ) { InstrOfferingConfig ioc = i.next(); Config config = new Config(ioc.getUniqueId(), courseName + " [" + ioc.getName() + "]", offering); TreeSet<SchedulingSubpart> subparts = new TreeSet<SchedulingSubpart>(new SchedulingSubpartComparator()); subparts.addAll(ioc.getSchedulingSubparts()); for (SchedulingSubpart ss: subparts) { String sufix = ss.getSchedulingSubpartSuffix(hibSession); Subpart parentSubpart = (ss.getParentSubpart() == null ? null : (Subpart)ss2subpart.get(ss.getParentSubpart().getUniqueId())); if (ss.getParentSubpart() != null && parentSubpart == null) { sLog.error("Subpart " + ss.getSchedulingSubpartLabel() + " has parent " + ss.getSchedulingSubpartLabel() +", but the appropriate parent subpart is not loaded. [" + iAcademicSession + "]"); } Subpart subpart = new Subpart(ss.getUniqueId().longValue(), df.format(ss.getItype().getItype()) + sufix, ss.getItype().getAbbv().trim(), config, parentSubpart); ss2subpart.put(ss.getUniqueId(), subpart); for (Iterator<Class_> j = ss.getClasses().iterator(); j.hasNext(); ) { Class_ c = j.next(); Section parentSection = (c.getParentClass() == null ? null : (Section)class2section.get(c.getParentClass().getUniqueId())); if (c.getParentClass()!=null && parentSection==null) { sLog.error("Class " + c.getClassLabel() + " has parent " + c.getClassLabel() + ", but the appropriate parent section is not loaded. [" + iAcademicSession + "]"); } Assignment a = c.getCommittedAssignment(); Placement p = (a == null ? null : a.getPlacement()); if (p != null && p.getTimeLocation() != null) { p.getTimeLocation().setDatePattern( p.getTimeLocation().getDatePatternId(), datePatternName(p.getTimeLocation()), p.getTimeLocation().getWeekCode()); } int minLimit = c.getExpectedCapacity(); int maxLimit = c.getMaxExpectedCapacity(); int limit = maxLimit; if (minLimit < maxLimit && p != null) { int roomLimit = Math.round((c.getRoomRatio() == null ? 1.0f : c.getRoomRatio()) * p.getRoomSize()); limit = Math.min(Math.max(minLimit, roomLimit), maxLimit); } if (ioc.isUnlimitedEnrollment() || limit >= 9999) limit = -1; String instructorIds = ""; String instructorNames = ""; for (Iterator<ClassInstructor> k = c.getClassInstructors().iterator(); k.hasNext(); ) { ClassInstructor ci = k.next(); if (!ci.isLead()) continue; if (!instructorIds.isEmpty()) { instructorIds += ":"; instructorNames += ":"; } instructorIds += ci.getInstructor().getUniqueId().toString(); instructorNames += ci.getInstructor().getName(DepartmentalInstructor.sNameFormatShort) + "|" + (ci.getInstructor().getEmail() == null ? "" : ci.getInstructor().getEmail()); } Section section = new Section(c.getUniqueId().longValue(), limit, (c.getExternalUniqueId() == null ? c.getClassSuffix() == null ? c.getSectionNumberString(hibSession) : c.getClassSuffix() : c.getExternalUniqueId()), subpart, p, instructorIds, instructorNames, parentSection); class2section.put(c.getUniqueId(), section); iClassTable.put(c.getUniqueId(), section); } } } return offering; } public Student loadStudent(org.unitime.timetable.model.Student s) { Student student = new Student(s.getUniqueId()); iStudentTable.put(s.getUniqueId(), student); if ("true".equals(ApplicationProperties.getProperty("unitime.enrollment.enabled", "true"))) { TreeSet<CourseDemand> demands = new TreeSet<CourseDemand>(new Comparator<CourseDemand>() { public int compare(CourseDemand d1, CourseDemand d2) { if (d1.isAlternative() && !d2.isAlternative()) return 1; if (!d1.isAlternative() && d2.isAlternative()) return -1; int cmp = d1.getPriority().compareTo(d2.getPriority()); if (cmp != 0) return cmp; return d1.getUniqueId().compareTo(d2.getUniqueId()); } }); demands.addAll(s.getCourseDemands()); for (CourseDemand cd: demands) { if (cd.getFreeTime()!=null) { TimeLocation ft = new TimeLocation( cd.getFreeTime().getDayCode(), cd.getFreeTime().getStartSlot(), cd.getFreeTime().getLength(), 0, 0, -1l, "", iAcademicSession.getFreeTimePattern(), 0); new FreeTimeRequest( cd.getUniqueId(), cd.getPriority(), cd.isAlternative(), student, ft); } else if (!cd.getCourseRequests().isEmpty()) { Vector<Course> courses = new Vector<Course>(); HashSet<Section> assignedSections = new HashSet<Section>(); Config assignedConfig = null; TreeSet<org.unitime.timetable.model.CourseRequest> crs = new TreeSet<org.unitime.timetable.model.CourseRequest>(new Comparator<org.unitime.timetable.model.CourseRequest>() { public int compare(org.unitime.timetable.model.CourseRequest r1, org.unitime.timetable.model.CourseRequest r2) { return r1.getOrder().compareTo(r2.getOrder()); } }); crs.addAll(cd.getCourseRequests()); for (org.unitime.timetable.model.CourseRequest cr: crs) { Course course = iCourseTable.get(cr.getCourseOffering().getUniqueId()); if (course==null) { sLog.warn("Student " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + ") requests course " + cr.getCourseOffering().getCourseName() + " that is not loaded. [" + iAcademicSession + "]"); continue; } if (assignedConfig==null) { HashSet<Long> subparts = new HashSet<Long>(); for (Iterator<StudentClassEnrollment> i = (cr.getClassEnrollments() == null ? s.getClassEnrollments() : cr.getClassEnrollments()).iterator(); i.hasNext(); ) { StudentClassEnrollment enrl = i.next(); Section section = course.getOffering().getSection(enrl.getClazz().getUniqueId()); if (section!=null) { assignedSections.add(section); if (assignedConfig != null && assignedConfig.getId() != section.getSubpart().getConfig().getId()) { sLog.error("There is a problem assigning " + course.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + "): classes from different configurations. [" + iAcademicSession + "]"); } assignedConfig = section.getSubpart().getConfig(); if (!subparts.add(section.getSubpart().getId())) { sLog.error("There is a problem assigning " + course.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + "): two or more classes of the same subpart. [" + iAcademicSession + "]"); } } else { sLog.error("There is a problem assigning " + course.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + "): class " + enrl.getClazz().getClassLabel() + " not known. [" + iAcademicSession + "]"); } } } courses.addElement(course); } if (courses.isEmpty()) continue; CourseRequest request = new CourseRequest( cd.getUniqueId(), cd.getPriority(), cd.isAlternative(), student, courses, cd.isWaitlist()); if (assignedConfig!=null && assignedSections.size() == assignedConfig.getSubparts().size()) { Enrollment enrollment = new Enrollment(request, 0, assignedConfig, assignedSections); request.setInitialAssignment(enrollment); } if (assignedConfig!=null && assignedSections.size() != assignedConfig.getSubparts().size()) { sLog.error("There is a problem assigning " + request.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + ") wrong number of classes (" + "has " + assignedSections.size() + ", expected " + assignedConfig.getSubparts().size() + "). [" + iAcademicSession + "]"); } } } } if (student.getRequests().isEmpty() && !s.getClassEnrollments().isEmpty()) { TreeSet<Course> courses = new TreeSet<Course>(new Comparator<Course>() { public int compare(Course c1, Course c2) { return (c1.getSubjectArea() + " " + c1.getCourseNumber()).compareTo(c2.getSubjectArea() + " " + c2.getCourseNumber()); } }); for (Iterator<StudentClassEnrollment> i = s.getClassEnrollments().iterator(); i.hasNext(); ) { StudentClassEnrollment enrl = i.next(); Course course = iCourseTable.get(enrl.getCourseOffering().getUniqueId()); if (course==null) { sLog.warn("Student " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + ") requests course " + enrl.getCourseOffering().getCourseName()+" that is not loaded. [" + iAcademicSession + "]"); continue; } courses.add(course); } int priority = 0; courses: for (Course course: courses) { Vector<Course> cx = new Vector<Course>(); cx.add(course); CourseRequest request = new CourseRequest( course.getId(), priority++, false, student, cx, false); HashSet<Section> assignedSections = new HashSet<Section>(); Config assignedConfig = null; HashSet<Long> subparts = new HashSet<Long>(); for (Iterator<StudentClassEnrollment> i = s.getClassEnrollments().iterator(); i.hasNext(); ) { StudentClassEnrollment enrl = i.next(); if (course.getId() != enrl.getCourseOffering().getUniqueId()) continue; Section section = course.getOffering().getSection(enrl.getClazz().getUniqueId()); if (section!=null) { assignedSections.add(section); if (assignedConfig != null && assignedConfig.getId() != section.getSubpart().getConfig().getId()) { sLog.error("There is a problem assigning " + request.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + "): classes from different configurations. [" + iAcademicSession + "]"); continue courses; } assignedConfig = section.getSubpart().getConfig(); if (!subparts.add(section.getSubpart().getId())) { sLog.error("There is a problem assigning " + request.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + "): two or more classes of the same subpart. [" + iAcademicSession + "]"); continue courses; } } else { sLog.error("There is a problem assigning " + request.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + "): class " + enrl.getClazz().getClassLabel() + " not known. [" + iAcademicSession + "]"); Section x = iClassTable.get(enrl.getClazz().getUniqueId()); if (x != null) { sLog.info(" but a class with the same id is loaded, but under offering " + x.getSubpart().getConfig().getOffering().getName() + " (id is " + x.getSubpart().getConfig().getOffering().getId() + ", expected " +course.getOffering().getId() + ") [" + iAcademicSession + "]"); } continue courses; } } if (assignedConfig!=null && assignedSections.size() == assignedConfig.getSubparts().size()) { Enrollment enrollment = new Enrollment(request, 0, assignedConfig, assignedSections); request.setInitialAssignment(enrollment); } if (assignedConfig!=null && assignedSections.size() != assignedConfig.getSubparts().size()) { sLog.error("There is a problem assigning " + request.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + "): wrong number of classes (" + "has " + assignedSections.size() + ", expected " + assignedConfig.getSubparts().size() + "). [" + iAcademicSession + "]"); } } } return student; } @SuppressWarnings("unchecked") public void assignStudent(Student student, org.unitime.timetable.model.Student s, boolean tweakLimits) { for (Request r: student.getRequests()) { if (r instanceof CourseRequest && r.getInitialAssignment() != null) { if (r.getModel().conflictValues(r.getInitialAssignment()).isEmpty()) { r.assign(0, r.getInitialAssignment()); } else { CourseRequest cr = (CourseRequest)r; Enrollment enrl = (Enrollment)r.getInitialAssignment(); sLog.error("There is a problem assigning " + cr.getName() + " to " + s.getName(DepartmentalInstructor.sNameFormatInitialLast) + " (" + s.getExternalUniqueId() + ") [" + iAcademicSession + "]"); boolean hasLimit = false, hasOverlap = false; sections: for (Iterator<Section> i = enrl.getSections().iterator(); i.hasNext();) { Section section = i.next(); if (section.getTime() != null) { for (Request q: student.getRequests()) { if (q.getAssignment() == null || !(q instanceof CourseRequest)) continue; Enrollment enrlx = (Enrollment)q.getAssignment(); for (Iterator<Section> j = enrlx.getSections().iterator(); j.hasNext();) { Section sectionx = j.next(); if (sectionx.getTime() == null) continue; if (sectionx.getTime().hasIntersection(section.getTime())) { sLog.info(" " + section.getSubpart().getName() + " " + section.getName() + " " + section.getTime().getLongName() + " overlaps with " + sectionx.getSubpart().getConfig().getOffering().getName() + " " + sectionx.getSubpart().getName() + " " + sectionx.getName() + " " + sectionx.getTime().getLongName()); hasOverlap = true; continue sections; } } } } if (section.getLimit() >= section.getEnrollments().size()) { sLog.info(" " + section.getSubpart().getName() + " " + section.getName() + (section.getTime() == null ? "" : " " + section.getTime().getLongName()) + " has no space available (limit is "+ section.getLimit() + ")"); if (tweakLimits) { section.setLimit(section.getEnrollments().size() + 1); sLog.info(" limit increased to "+section.getLimit()); } hasLimit = true; continue sections; } sLog.info(" " + section.getSubpart().getName() + " " + section.getName() + (section.getTime() == null ? "" : " " + section.getTime().getLongName())); } if (!hasLimit && !hasOverlap) { for (Iterator<Enrollment> i = r.getModel().conflictValues(r.getInitialAssignment()).iterator(); i.hasNext();) { Enrollment enrlx = i.next(); for (Iterator<Section> j = enrlx.getSections().iterator(); j.hasNext();) { Section sectionx = j.next(); sLog.info(" conflicts with " + sectionx.getSubpart().getConfig().getOffering().getName() + " " + sectionx.getSubpart().getName() + " " + sectionx.getName() + (sectionx.getTime() == null ? "" : " " + sectionx.getTime().getLongName())); } if (enrlx.getRequest().getStudent().getId() != student.getId()) sLog.info(" of a different student"); } } if (hasLimit && tweakLimits && r.getModel().conflictValues(r.getInitialAssignment()).isEmpty()) { r.assign(0, r.getInitialAssignment()); } } } } for (Request r: student.getRequests()) { if (r instanceof FreeTimeRequest) { FreeTimeRequest ft = (FreeTimeRequest)r; Enrollment enrollment = ft.createEnrollment(); if (r.getModel().conflictValues(enrollment).isEmpty()) { ft.setInitialAssignment(enrollment); ft.assign(0, enrollment); } } } } public String datePatternName(TimeLocation time) { if (time.getWeekCode().isEmpty()) return time.getDatePatternName(); Calendar cal = Calendar.getInstance(Locale.US); cal.setLenient(true); cal.setTime(iAcademicSession.getDatePatternFirstDate()); int idx = time.getWeekCode().nextSetBit(0); cal.add(Calendar.DAY_OF_YEAR, idx); Date first = null; while (idx < time.getWeekCode().size() && first == null) { if (time.getWeekCode().get(idx)) { int dow = cal.get(Calendar.DAY_OF_WEEK); switch (dow) { case Calendar.MONDAY: if ((time.getDayCode() & DayCode.MON.getCode()) != 0) first = cal.getTime(); break; case Calendar.TUESDAY: if ((time.getDayCode() & DayCode.TUE.getCode()) != 0) first = cal.getTime(); break; case Calendar.WEDNESDAY: if ((time.getDayCode() & DayCode.WED.getCode()) != 0) first = cal.getTime(); break; case Calendar.THURSDAY: if ((time.getDayCode() & DayCode.THU.getCode()) != 0) first = cal.getTime(); break; case Calendar.FRIDAY: if ((time.getDayCode() & DayCode.FRI.getCode()) != 0) first = cal.getTime(); break; case Calendar.SATURDAY: if ((time.getDayCode() & DayCode.SAT.getCode()) != 0) first = cal.getTime(); break; case Calendar.SUNDAY: if ((time.getDayCode() & DayCode.SUN.getCode()) != 0) first = cal.getTime(); break; } } cal.add(Calendar.DAY_OF_YEAR, 1); idx++; } if (first == null) return time.getDatePatternName(); cal.setTime(iAcademicSession.getDatePatternFirstDate()); idx = time.getWeekCode().length() - 1; cal.add(Calendar.DAY_OF_YEAR, idx); Date last = null; while (idx >= 0 && last == null) { if (time.getWeekCode().get(idx)) { int dow = cal.get(Calendar.DAY_OF_WEEK); switch (dow) { case Calendar.MONDAY: if ((time.getDayCode() & DayCode.MON.getCode()) != 0) last = cal.getTime(); break; case Calendar.TUESDAY: if ((time.getDayCode() & DayCode.TUE.getCode()) != 0) last = cal.getTime(); break; case Calendar.WEDNESDAY: if ((time.getDayCode() & DayCode.WED.getCode()) != 0) last = cal.getTime(); break; case Calendar.THURSDAY: if ((time.getDayCode() & DayCode.THU.getCode()) != 0) last = cal.getTime(); break; case Calendar.FRIDAY: if ((time.getDayCode() & DayCode.FRI.getCode()) != 0) last = cal.getTime(); break; case Calendar.SATURDAY: if ((time.getDayCode() & DayCode.SAT.getCode()) != 0) last = cal.getTime(); break; case Calendar.SUNDAY: if ((time.getDayCode() & DayCode.SUN.getCode()) != 0) last = cal.getTime(); break; } } cal.add(Calendar.DAY_OF_YEAR, -1); idx--; } if (last == null) return time.getDatePatternName(); SimpleDateFormat dpf = new SimpleDateFormat("MM/dd"); return dpf.format(first) + (first.equals(last) ? "" : " - " + dpf.format(last)); } } --- NEW FILE: DayCode.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server; import java.util.ArrayList; import java.util.Collection; /** * @author Tomas Muller */ public enum DayCode { MON (64, 0, "M" , "Mon", "Monday"), TUE (32, 1, "T" , "Tue", "Tuesday"), WED (16, 2, "W" , "Wed", "Wednesday"), THU ( 8, 3, "R" , "Thu", "Thursday" ), FRI ( 4, 4, "F" , "Fri", "Friday"), SAT ( 2, 5, "S" , "Sat", "Saturday"), SUN ( 1, 6, "U" , "Sun", "Sunday"); private final int iCode; private final int iIndex; private final String iAbbv; private final String iShort; private final String iName; DayCode(int code, int index, String abbv, String shortName, String name) { iCode = code; iIndex = index; iAbbv = abbv; iShort = shortName; iName = name; } public int getIndex() { return iIndex; } public int getCode() { return iCode; } public String getAbbv() { return iAbbv; } public String getShort() { return iShort; } public String getName() { return iName; } public static int nrDays(int days) { int nrDays = 0; for (DayCode dc: DayCode.values()) if ((days & dc.getCode())!=0) nrDays++; return nrDays; } public static ArrayList<DayCode> toDayCodes(int days) { ArrayList<DayCode> dayCodes = new ArrayList<DayCode>(DayCode.values().length); for (DayCode dc: DayCode.values()) if ((days & dc.getCode())!=0) dayCodes.add(dc); return dayCodes; } public static String toString(int days) { StringBuffer daysStr = new StringBuffer(); for (DayCode dc: DayCode.values()) if ((days & dc.getCode())!=0) daysStr.append(dc.getAbbv()); return daysStr.toString(); } public static ArrayList<DayCode> toDayCodes(String days) { ArrayList<DayCode> dayCodes = new ArrayList<DayCode>(DayCode.values().length); for (DayCode dc: DayCode.values()) if (days.indexOf(dc.getAbbv()) >= 0) dayCodes.add(dc); return dayCodes; } public static ArrayList<DayCode> toDayCodes(Collection<Integer> days) { ArrayList<DayCode> dayCodes = new ArrayList<DayCode>(DayCode.values().length); for (DayCode dc: DayCode.values()) if (days.contains(dc.getIndex())) dayCodes.add(dc); return dayCodes; } public static String toString(ArrayList<DayCode> days) { StringBuffer daysStr = new StringBuffer(); for (DayCode dc: days) daysStr.append(dc.getAbbv()); return daysStr.toString(); } public static int toInt(ArrayList<DayCode> days) { int dayCode = 0; for (DayCode dc: days) dayCode |= dc.getCode(); return dayCode; } public int nrDays(ArrayList<DayCode> days) { return days.size(); } } --- NEW FILE: EventServlet.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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/>. * */ [...992 lines suppressed...] throw (EventException)e; sLog.error(e.getMessage(), e); throw new EventException("Failed to find resources: " + e.getMessage()); } } @Override public Boolean canLookupPeople() throws EventException { try { User user = Web.getUser(getThreadLocalRequest().getSession()); if (user == null) throw new EventException("not authenticated"); return Roles.ADMIN_ROLE.equals(user.getRole()); } catch (Exception e) { if (e instanceof EventException) throw (EventException)e; sLog.error(e.getMessage(), e); throw new EventException(e.getMessage()); } } } --- NEW FILE: MenuServlet.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server; import java.io.File; import java.net.URL; import java.net.URLDecoder; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeSet; import javax.servlet.ServletException; import javax.servlet.http.HttpSession; import net.sf.cpsolver.ifs.util.DataProperties; import org.apache.log4j.Logger; import org.dom4j.Attribute; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.io.SAXReader; import org.unitime.commons.Debug; import org.unitime.commons.User; import org.unitime.commons.hibernate.util.HibernateUtil; import org.unitime.commons.web.Web; import org.unitime.timetable.ApplicationProperties; import org.unitime.timetable.action.PersonalizedExamReportAction; import org.unitime.timetable.form.ListSolutionsForm; import org.unitime.timetable.gwt.services.MenuService; import org.unitime.timetable.gwt.shared.MenuException; import org.unitime.timetable.gwt.shared.MenuInterface; import org.unitime.timetable.model.Department; import org.unitime.timetable.model.Exam; import org.unitime.timetable.model.Roles; import org.unitime.timetable.model.Session; import org.unitime.timetable.model.SolverGroup; import org.unitime.timetable.model.TimetableManager; import org.unitime.timetable.model.UserData; import org.unitime.timetable.model.dao.SessionDAO; import org.unitime.timetable.model.dao.SolverGroupDAO; import org.unitime.timetable.model.dao.StudentDAO; import org.unitime.timetable.solver.SolverProxy; import org.unitime.timetable.solver.WebSolver; import org.unitime.timetable.solver.exam.ExamSolverProxy; import org.unitime.timetable.solver.studentsct.StudentSolverProxy; import org.unitime.timetable.util.Constants; import org.unitime.timetable.util.RoomAvailability; import com.google.gwt.user.server.rpc.RemoteServiceServlet; /** * @author Tomas Muller */ public class MenuServlet extends RemoteServiceServlet implements MenuService { private static final long serialVersionUID = 9021169012914612488L; private static Logger sLog = Logger.getLogger(MenuServlet.class); private static Element iRoot = null; public void init() throws ServletException { try { String menu = ApplicationProperties.getProperty("unitime.menu","menu.xml"); Document document = null; URL menuUrl = ApplicationProperties.class.getClassLoader().getResource(menu); if (menuUrl!=null) { Debug.info("Reading menu from " + URLDecoder.decode(menuUrl.getPath(), "UTF-8") + " ..."); document = (new SAXReader()).read(menuUrl.openStream()); } else if (new File(menu).exists()) { Debug.info("Reading menu from " + menu + " ..."); document = (new SAXReader()).read(new File(menu)); } if (document==null) throw new ServletException("Unable to create menu, reason: resource " + menu + " not found."); if (!"unitime-menu".equals(document.getRootElement().getName())) throw new ServletException("Menu has an unknown format."); iRoot = document.getRootElement(); String customMenu = ApplicationProperties.getProperty("unitime.menu.custom","menu-custom.xml"); Document customDocument = null; URL customMenuUrl = ApplicationProperties.class.getClassLoader().getResource(customMenu); if (customMenuUrl!=null) { Debug.info("Reading custom menu from " + URLDecoder.decode(customMenuUrl.getPath(), "UTF-8") + " ..."); customDocument = (new SAXReader()).read(customMenuUrl.openStream()); } else if (new File(customMenu).exists()) { Debug.info("Reading custom menu from " + customMenu + " ..."); customDocument = (new SAXReader()).read(new File(customMenu)); } if (customDocument != null) { merge(iRoot, customDocument.getRootElement()); } } catch (Exception e) { if (e instanceof ServletException) throw (ServletException)e; throw new ServletException("Unable to initialize, reason: "+e.getMessage(), e); } } private void merge(Element menu, Element custom) { if ("remove".equals(custom.getName())) { menu.getParent().remove(menu); return; } for (Iterator<Attribute> i = custom.attributeIterator(); i.hasNext();) { Attribute a = i.next(); menu.addAttribute(a.getName(), a.getValue()); } for (Iterator<Element> i = custom.elementIterator(); i.hasNext(); ) { Element e = i.next(); if ("condition".equals(e.getName())) { menu.add(e.createCopy()); continue; } if ("new-condition".equals(e.getName())) { for (Iterator<Element> j = menu.elementIterator("condition"); j.hasNext(); ) { menu.remove(j.next()); } Element f = e.createCopy(); f.setName("condition"); menu.add(f); continue; } String name = e.attributeValue("name"); Element x = null; if (name != null) { for (Iterator<Element> j = menu.elementIterator(); j.hasNext(); ) { Element f = j.next(); if (name.equals(f.attributeValue("name"))) { x = f; break; } } } if (x != null) { merge(x, e); } else { int pos = Integer.parseInt(e.attributeValue("position", "-1")); if (pos >= 0) { List<Element> after = new ArrayList<Element>(); for (Iterator<Element> j = menu.elementIterator(); j.hasNext(); ) { Element f = j.next(); if ("condition".equals(f.getName())) continue; if (pos > 0) { pos--; } else { after.add(f); menu.remove(f); } } menu.add(e.createCopy()); for (Element f: after) menu.add(f); } else menu.add(e.createCopy()); } } } public List<MenuInterface> getMenu() throws MenuException { try { org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { // init(); List<MenuInterface> menu = new ArrayList<MenuInterface>(); if (iRoot == null) throw new MenuException("menu is not configured properly"); UserInfo user = new UserInfo(getThreadLocalRequest().getSession()); for (Iterator<Element> i = iRoot.elementIterator(); i.hasNext(); ) { Element element = i.next(); MenuInterface m = getMenu(user, element); if (m != null) menu.add(m); } if (menu.isEmpty()) throw new MenuException("no menu"); return menu; } finally { hibSession.close(); } } catch (Exception e) { if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } private MenuInterface getMenu(UserInfo user, Element menuElement) { MenuInterface menu = new MenuInterface(); menu.setName(menuElement.attributeValue("name")); menu.setTitle(menuElement.attributeValue("title")); menu.setTarget(menuElement.attributeValue("target")); menu.setPage(menuElement.attributeValue("page")); String type = menuElement.attributeValue("type"); if ("gwt".equals(type)) menu.setGWT(true); if ("property".equals(type) && menu.getPage() != null) { menu.setPage(ApplicationProperties.getProperty(menu.getPage())); if (menu.getPage() == null) return null; } for (Iterator<Element> i = menuElement.elementIterator(); i.hasNext(); ) { Element element = i.next(); if ("condition".equals(element.getName())) { if (!check(user, element)) return null; } else { MenuInterface m = getMenu(user, element); if (m != null) menu.addSubMenu(m); } } return menu; } private boolean check(UserInfo userInfo, Element conditionElement) { String cond = conditionElement.getName(); if ("and".equals(cond) || "condition".equals(cond)) { for (Iterator<Element> i = conditionElement.elementIterator(); i.hasNext(); ) { Element element = i.next(); if (!check(userInfo, element)) return false; } return true; } else if ("or".equals(cond)) { for (Iterator<Element> i = conditionElement.elementIterator(); i.hasNext(); ) { Element element = i.next(); if (check(userInfo, element)) return true; } return false; } else if ("not".equals(cond)) { for (Iterator<Element> i = conditionElement.elementIterator(); i.hasNext(); ) { Element element = i.next(); if (check(userInfo, element)) return false; } return true; } else if ("isAuthenticated".equals(cond)) { return userInfo.getUser() != null; } else if ("hasRole".equals(cond)) { User user = userInfo.getUser(); if (user == null) return false; String role = conditionElement.attributeValue("name"); if (role == null) return user.getRole() != null; // has any role return role.equalsIgnoreCase(user.getRole()); } else if ("propertyEquals".equals(cond)) { return conditionElement.attributeValue("value", "true").equalsIgnoreCase(ApplicationProperties.getProperty( conditionElement.attributeValue("name", "dummy"), conditionElement.attributeValue("defaultValue", "false"))); } else if ("hasProperty".equals(cond)) { return ApplicationProperties.getProperty(conditionElement.attributeValue("name", "dummy")) != null; } else if ("canSeeEvents".equals(cond)) { return userInfo.getUser() != null && TimetableManager.canSeeEvents(userInfo.getUser()); } else if ("hasRoomAvailability".equals(cond)) { return RoomAvailability.getInstance() != null; } else if ("hasPersonalReport".equals(cond)) { return userInfo.getUser() != null && PersonalizedExamReportAction.hasPersonalReport(userInfo.getUser()); } else if ("isChameleon".equals(cond)) { return getThreadLocalRequest().getSession().getAttribute("hdnAdminAlias")!=null && getThreadLocalRequest().getSession().getAttribute("hdnAdminAlias").toString().equals("1"); } else if ("isSectioningEnabled".equals(cond)) { return SectioningServer.isEnabled(); } else if ("isStudent".equals(cond)) { return userInfo != null && userInfo.isStudent(); } else if ("isRegistrationEnabled".equals(cond)) { return SectioningServer.isRegistrationEnabled(); } else { User user = userInfo.getUser(); if (user == null) return false; TimetableManager manager = userInfo.getManager(); if (manager == null) return false; Session session = userInfo.getSession(); if (session == null) return false; if ("canSeeCourses".equals(cond)) { return manager.canSeeCourses(session, user); } else if ("canSeeTimetable".equals(cond)) { return manager.canSeeTimetable(session, user); } else if ("canDoTimetable".equals(cond)) { return manager.canDoTimetable(session, user); } else if ("hasASolverGroup".equals(cond)) { return manager.hasASolverGroup(session, user); } else if ("canSectionStudents".equals(cond)) { return manager.canSectionStudents(session, user); } else if ("canSeeExams".equals(cond)) { return manager.canSeeExams(session, user); } else if ("canTimetableExams".equals(cond)) { return manager.canTimetableExams(session, user); } else if ("canAudit".equals(cond)) { return manager.canAudit(session, user); } } sLog.warn("Unknown condition " + cond + "."); return true; } public static class UserInfo { User iUser = null; Session iSession = null; TimetableManager iManager = null; public UserInfo(HttpSession session) { iUser = Web.getUser(session); if (iUser != null) { Long sessionId = (Long) iUser.getAttribute(Constants.SESSION_ID_ATTR_NAME); if (sessionId != null) { iSession = SessionDAO.getInstance().get(sessionId); } iManager = TimetableManager.getManager(iUser); } } public User getUser() { return iUser; } public Session getSession() { return iSession; } public TimetableManager getManager() { return iManager; } public boolean isStudent() { if (getUser() == null) return false; return ((Number)StudentDAO.getInstance().getSession().createQuery("select count(s) from Student s where " + "s.externalUniqueId = :uid") .setString("uid", getUser().getId()).setCacheable(true).uniqueResult()).intValue() > 0; } } public HashMap<String, String> getUserInfo() throws MenuException { try { HashMap<String, String> ret = new HashMap<String, String>(); org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { UserInfo user = new UserInfo(getThreadLocalRequest().getSession()); if (user.getUser() == null) return null; String userName = Constants.toInitialCase(user.getUser().getName(), "-".toCharArray()); ret.put("0Name", userName); String dept = ""; TimetableManager manager = user.getManager(); if (manager!=null) { for (Iterator i=manager.getDepartments().iterator();i.hasNext();) { Department d = (Department)i.next(); if (d.getSessionId().equals(user.getSession().getUniqueId())) { if (dept.length()>0) dept += ","; dept += "<span title='"+d.getHtmlTitle()+"'>"+d.getShortLabel()+"</span>"; } } } else { TreeSet depts = new TreeSet(user.getUser().getDepartments()); for (Iterator i=depts.iterator();i.hasNext();) { dept += i.next().toString(); if (i.hasNext()) dept += ","; } } ret.put("1Dept", dept); String role = user.getUser().getRole(); if (role==null) role = "No Role"; ret.put("2Role", role); if (user.getUser() != null && Roles.ADMIN_ROLE.equals(user.getUser().getRole()) || (getThreadLocalRequest().getSession().getAttribute("hdnAdminAlias")!=null && getThreadLocalRequest().getSession().getAttribute("hdnAdminAlias").toString().equals("1"))) ret.put("Chameleon", ""); } finally { hibSession.close(); } return ret; } catch (Exception e) { if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } public HashMap<String, String> getSessionInfo() throws MenuException { try { HashMap<String, String> ret = new HashMap<String, String>(); org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { UserInfo user = new UserInfo(getThreadLocalRequest().getSession()); if (user.getSession() == null) return null; ret.put("0Session", user.getSession().getLabel()); ret.put("1Status", user.getSession().getStatusType().getLabel()); ret.put("2Database", HibernateUtil.getDatabaseName()); } finally { hibSession.close(); } return ret; } catch (Exception e) { if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } public String getVersion() throws MenuException { return "Version " + Constants.VERSION + "." + Constants.BLD_NUMBER.replaceAll("@build.number@","?") + " built on " + Constants.REL_DATE.replaceAll("@build.date@", "?"); } private String getName(String puid) { return getName(TimetableManager.findByExternalId(puid)); } private String getName(TimetableManager mgr) { if (mgr==null) return null; return mgr.getShortName(); } private String getName(SolverGroup gr) { if (gr==null) return null; return gr.getAbbv(); } public HashMap<String, String> getSolverInfo() throws MenuException { try { HashMap<String, String> ret = new HashMap<String, String>(); org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { SolverProxy solver = WebSolver.getSolver(getThreadLocalRequest().getSession()); ExamSolverProxy examSolver = (solver==null?WebSolver.getExamSolverNoSessionCheck(getThreadLocalRequest().getSession()):null); StudentSolverProxy studentSolver = (solver==null && examSolver==null?WebSolver.getStudentSolverNoSessionCheck(getThreadLocalRequest().getSession()):null); Map progress = (studentSolver!=null?studentSolver.getProgress():examSolver!=null?examSolver.getProgress():solver!=null?solver.getProgress():null); if (progress == null) return null; DataProperties properties = (studentSolver!=null?studentSolver.getProperties():examSolver!=null?examSolver.getProperties():solver.getProperties()); String progressStatus = (String)progress.get("STATUS"); String progressPhase = (String)progress.get("PHASE"); long progressCur = ((Long)progress.get("PROGRESS")).longValue(); long progressMax = ((Long)progress.get("MAX_PROGRESS")).longValue(); String version = (String)progress.get("VERSION"); if (version==null || "-1".equals(version)) version = "N/A"; if (version.indexOf("@build.number@")>=0) version = version.replaceAll("@build.number@","?"); double progressPercent = 100.0*((double)(progressCur<progressMax?progressCur:progressMax))/((double)progressMax); String runnerName = getName(properties.getProperty("General.OwnerPuid","N/A")); Long[] solverGroupId = properties.getPropertyLongArry("General.SolverGroupId",null); String ownerName = ""; if (solverGroupId!=null) { for (int i=0;i<solverGroupId.length;i++) { if (i>0) ownerName += " & "; ownerName += getName((new SolverGroupDAO()).get(solverGroupId[i])); } } if (examSolver!=null) ownerName = Exam.sExamTypes[examSolver.getExamType()]; if (ownerName==null || ownerName.length()==0) ownerName = "N/A"; if (ownerName.equals("N/A")) ownerName = runnerName; if (runnerName.equals("N/A")) runnerName = ownerName; if (!ownerName.equals(runnerName)) ownerName = runnerName+" as "+ownerName; if (ownerName.length() > 50) ownerName = ownerName.substring(0,47) + "..."; ret.put("0Type", (studentSolver!=null?"Student Sectioning Solver":examSolver!=null?"Examinations Solver":"Course Timetabling Solver")); ret.put("4Owner", ownerName); ret.put("5Host", (studentSolver!=null?studentSolver.getHostLabel():examSolver!=null?examSolver.getHostLabel():solver.getHostLabel())); ret.put("1Solver", progressStatus); ret.put("2Phase", progressPhase); if (progressMax>0) ret.put("3Progress", (progressCur<progressMax?progressCur:progressMax) + " of " + progressMax + " (" + Web.format(progressPercent) + "%)"); ret.put("7Version", version); ret.put("6Session", SessionDAO.getInstance().get(properties.getPropertyLong("General.SessionId",null)).getLabel()); Map<String,String> info = null; if (solver != null) { info = solver.bestSolutionInfo(); if (info == null) info = solver.currentSolutionInfo(); } else if (examSolver != null) { info = examSolver.bestSolutionInfo(); if (info == null) info = examSolver.currentSolutionInfo(); } else if (studentSolver != null) { info = studentSolver.bestSolutionInfo(); if (info == null) info = studentSolver.currentSolutionInfo(); } if (info != null) { TreeSet<String> keys = new TreeSet<String>(new ListSolutionsForm.InfoComparator()); keys.addAll(info.keySet()); int idx = 0; for (String key: keys) { ret.put((char)('A' + idx) + key, (String)info.get(key)); idx++; } } } finally { hibSession.close(); } return ret; } catch (Exception e) { sLog.warn("Unable to get solver info: " + e.getMessage()); if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } public String getHelpPage(String title) throws MenuException { if ("true".equals(ApplicationProperties.getProperty("tmtbl.wiki.help", "true")) && ApplicationProperties.getProperty("tmtbl.wiki.url") != null) { return ApplicationProperties.getProperty("tmtbl.wiki.url") + title.trim().replace(' ', '_').replace("(", "").replace(")", "").replace(':', '_'); } else { throw new MenuException("help pages are disabled"); } } public String getUserData(String property) throws MenuException { try { org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { return UserData.getProperty(getThreadLocalRequest().getSession(), property); } finally { hibSession.close(); } } catch (Exception e) { if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } public Boolean setUserData(String property, String value) throws MenuException { try { org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { UserData.setProperty(getThreadLocalRequest().getSession(), property, value); return null; } finally { hibSession.close(); } } catch (Exception e) { if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } public HashMap<String, String> getUserData(Collection<String> property) throws MenuException { try { org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { return UserData.getProperties(getThreadLocalRequest().getSession(), property); } finally { hibSession.close(); } } catch (Exception e) { if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } public Boolean setUserData(List<String[]> property2value) throws MenuException { try { org.hibernate.Session hibSession = SessionDAO.getInstance().getSession(); try { for (String[] p: property2value) UserData.setProperty(getThreadLocalRequest().getSession(), p[0], p[1]); return null; } finally { hibSession.close(); } } catch (Exception e) { if (e instanceof MenuException) throw (MenuException)e; throw new MenuException(e.getMessage()); } } } --- NEW FILE: UniTimePrincipal.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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 ... [truncated message content] |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:10:59
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/client/curricula In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/client/curricula Added Files: ClassificationsEdit.java CurriculumEdit.java CurriculaClassifications.java CurriculumCookie.java CourseCurriculaTable.java CurriculaPage.java CurriculaCourseSelectionBox.java CurriculaTable.java CurriculumProjectionRulesPage.java CurriculaCourses.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: CurriculaCourses.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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/>. * */ [...1849 lines suppressed...] public void openNew() { setText("New group"); iGrOldName = null; iGrName.setText(String.valueOf((char)('A' + getGroups().size()))); iGrType.setSelectedIndex(0); iGrAssign.setVisible(true); iGrDelete.setVisible(false); iGrUpdate.setVisible(false); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { iGrName.setFocus(true); iGrName.selectAll(); } }); center(); } } } --- NEW FILE: CurriculaCourseSelectionBox.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.curricula; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.unitime.timetable.gwt.client.ToolBox; import org.unitime.timetable.gwt.client.widgets.UniTimeDialogBox; import org.unitime.timetable.gwt.client.widgets.UniTimeTabPabel; import org.unitime.timetable.gwt.client.widgets.Validator; import org.unitime.timetable.gwt.client.widgets.WebTable; import org.unitime.timetable.gwt.client.widgets.WebTable.RowDoubleClickEvent; import org.unitime.timetable.gwt.resources.StudentSectioningConstants; import org.unitime.timetable.gwt.resources.StudentSectioningMessages; import org.unitime.timetable.gwt.resources.StudentSectioningResources; import org.unitime.timetable.gwt.services.CurriculaService; import org.unitime.timetable.gwt.services.CurriculaServiceAsync; import org.unitime.timetable.gwt.shared.ClassAssignmentInterface; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.RunAsyncCallback; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.BlurEvent; import com.google.gwt.event.dom.client.BlurHandler; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.FocusEvent; import com.google.gwt.event.dom.client.FocusHandler; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyDownEvent; import com.google.gwt.event.dom.client.KeyDownHandler; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DialogBox; import com.google.gwt.user.client.ui.Focusable; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.SuggestOracle; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.SuggestOracle.Callback; import com.google.gwt.user.client.ui.SuggestOracle.Request; import com.google.gwt.user.client.ui.SuggestOracle.Response; import com.google.gwt.user.client.ui.SuggestOracle.Suggestion; /** * @author Tomas Muller */ public class CurriculaCourseSelectionBox extends Composite implements Validator, Focusable { public static final StudentSectioningResources RESOURCES = GWT.create(StudentSectioningResources.class); public static final StudentSectioningMessages MESSAGES = GWT.create(StudentSectioningMessages.class); public static final StudentSectioningConstants CONSTANTS = GWT.create(StudentSectioningConstants.class); private TextBox iTextField; private SuggestBox iSuggest; private Image iImage; private HorizontalPanel iHPanel; private VerticalPanel iVPanel; private Label iError; private TextBox iFilter; private DialogBox iDialog; private ScrollPanel iCoursesPanel; private VerticalPanel iDialogPanel; private WebTable iCourses, iClasses; private String iLastQuery = null; private Label iCoursesTip; private CourseCurriculaTable iCurricula; private UniTimeTabPabel iCourseDetailsTabPanel; private HTML iCourseDetails; private ScrollPanel iCourseDetailsPanel, iClassesPanel, iCurriculaPanel; private final CurriculaServiceAsync iCurriculaService = GWT.create(CurriculaService.class); private AsyncCallback<Collection<ClassAssignmentInterface.CourseAssignment>> iCourseOfferingsCallback; private AsyncCallback<String> iCourseDetailsCallback; private AsyncCallback<Collection<ClassAssignmentInterface.ClassAssignment>> iCourseClassesCallback; private ArrayList<CourseSelectionChangeHandler> iCourseSelectionChangeHandlers = new ArrayList<CourseSelectionChangeHandler>(); private ArrayList<Validator> iValitaros = new ArrayList<Validator>(); private String iHint = ""; private String iLastCourseLookup = null; private static int sLastSelectedCourseDetailsTab = 0; private List<CourseFinderDialogHandler> iCourseFinderDialogHandlers = new ArrayList<CourseFinderDialogHandler>(); public CurriculaCourseSelectionBox(String name) { SuggestOracle courseOfferingOracle = new SuggestOracle() { public void requestSuggestions(Request request, Callback callback) { if (request.getQuery().equals(iHint)) return; iCurriculaService.listCourseOfferings(request.getQuery(), request.getLimit(), new SuggestCallback(request, callback)); } public boolean isDisplayStringHTML() { return true; } }; iTextField = new TextBox(); iTextField.setStyleName("gwt-SuggestBox"); iTextField.setName(name); iSuggest = new SuggestBox(courseOfferingOracle, iTextField); iTextField.setStyleName("unitime-TextBoxHint"); iImage = new Image(RESOURCES.search_picker()); iImage.addMouseOverHandler(new MouseOverHandler() { public void onMouseOver(MouseOverEvent event) { if (iTextField.isEnabled()) iImage.setResource(RESOURCES.search_picker_Over()); } }); iImage.addMouseOutHandler(new MouseOutHandler() { public void onMouseOut(MouseOutEvent event) { if (iTextField.isEnabled()) iImage.setResource(RESOURCES.search_picker()); } }); iVPanel = new VerticalPanel(); iHPanel = new HorizontalPanel(); iHPanel.add(iSuggest); iHPanel.add(iImage); iVPanel.add(iHPanel); iError = new Label(); iError.setStyleName("unitime-ErrorHint"); iError.setVisible(false); iVPanel.add(iError); iImage.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { if (iTextField.isEnabled()) { openDialogAsync(); } } }); iSuggest.addSelectionHandler(new SelectionHandler<Suggestion>() { public void onSelection(SelectionEvent<Suggestion> event) { CourseSelectionChangeEvent e = new CourseSelectionChangeEvent(iTextField.getText(), !iTextField.getText().isEmpty()); for (CourseSelectionChangeHandler h : iCourseSelectionChangeHandlers) h.onChange(e); } }); iTextField.addChangeHandler(new ChangeHandler() { public void onChange(ChangeEvent event) { CourseSelectionChangeEvent e = new CourseSelectionChangeEvent(iTextField.getText(), false); for (CourseSelectionChangeHandler h : iCourseSelectionChangeHandlers) h.onChange(e); } }); iTextField.addKeyDownHandler(new KeyDownHandler() { public void onKeyDown(KeyDownEvent event) { if (!iTextField.isEnabled()) return; if ((event.getNativeEvent().getKeyCode()=='F' || event.getNativeEvent().getKeyCode()=='f') && event.isControlKeyDown()) { hideSuggestionList(); openDialogAsync(); } if (event.getNativeEvent().getKeyCode()==KeyCodes.KEY_ESCAPE) { hideSuggestionList(); } if ((event.getNativeEvent().getKeyCode()=='S' || event.getNativeEvent().getKeyCode()=='s') && event.isControlKeyDown()) { showSuggestionList(); } } }); iTextField.addBlurHandler(new BlurHandler() { public void onBlur(BlurEvent event) { if (iTextField.getText().isEmpty()) { if (iError.isVisible()) iError.setVisible(false); if (iHint!=null) iTextField.setText(iHint); iTextField.setStyleName("unitime-TextBoxHint"); } } }); iTextField.addFocusHandler(new FocusHandler() { public void onFocus(FocusEvent event) { iTextField.setStyleName("gwt-SuggestBox"); if (iTextField.getText().equals(iHint)) iTextField.setText(""); } }); initWidget(iVPanel); } private void openDialogAsync() { GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { openDialog(); } public void onFailure(Throwable reason) { Label error = new Label(MESSAGES.failedToLoadTheApp(reason.getMessage())); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("loading").setVisible(false); RootPanel.get("body").add(error); } }); } private void openDialog() { final boolean ie = "Microsoft Internet Explorer".equals(Window.Navigator.getAppName()); if (iDialog == null) { iDialog = new UniTimeDialogBox(true, true); iDialog.setText(MESSAGES.courseSelectionDialog()); iFilter = new TextBox(); iFilter.setStyleName("gwt-SuggestBox"); iFilter.setWidth("600"); iCourses = new WebTable(); iCourses.setHeader( new WebTable.Row( new WebTable.Cell(MESSAGES.colSubject(), 1, "80"), new WebTable.Cell(MESSAGES.colCourse(), 1, "80"), new WebTable.Cell(MESSAGES.colTitle(), 1, "400"), new WebTable.Cell("Limit", 1, "60"), new WebTable.Cell("Last‑Like", 1, "60"), new WebTable.Cell("Projected", 1, "60"), new WebTable.Cell("Enrolled", 1, "60") )); iDialogPanel = new VerticalPanel(); iDialogPanel.setSpacing(5); HorizontalPanel filterPanel = new HorizontalPanel(); Label filterText = new Label("Filter:", false); filterText.getElement().getStyle().setMarginRight(5, Unit.PX); filterPanel.setWidth("75px"); filterPanel.add(filterText); filterPanel.setCellHorizontalAlignment(filterText, HasHorizontalAlignment.ALIGN_RIGHT); filterPanel.setCellVerticalAlignment(filterText, HasVerticalAlignment.ALIGN_MIDDLE); filterPanel.add(iFilter); HTML blank = new HTML(" "); blank.setWidth("75px"); filterPanel.add(blank); iDialogPanel.add(filterPanel); iDialogPanel.setCellHorizontalAlignment(filterPanel, HasHorizontalAlignment.ALIGN_CENTER); iDialog.addCloseHandler(new CloseHandler<PopupPanel>() { public void onClose(CloseEvent<PopupPanel> event) { iImage.setResource(RESOURCES.search_picker()); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { setFocus(true); } }); } }); iCoursesPanel = new ScrollPanel(iCourses); iCoursesPanel.setSize("780px", "200px"); iCoursesPanel.setStyleName("unitime-ScrollPanel"); iCourseDetailsTabPanel = new UniTimeTabPabel(); iCourseDetails = new HTML("<table width='100%'></tr><td class='unitime-TableEmpty'>" + MESSAGES.courseSelectionNoCourseSelected() + "</td></tr></table>"); iCourseDetailsPanel = new ScrollPanel(iCourseDetails); iCourseDetailsPanel.setStyleName("unitime-ScrollPanel-inner"); iCourseDetailsTabPanel.add(iCourseDetailsPanel, MESSAGES.courseSelectionDetails(), true); iClasses = new WebTable(); iClasses.setHeader(new WebTable.Row( new WebTable.Cell(MESSAGES.colSubpart(), 1, "50"), new WebTable.Cell(MESSAGES.colClass(), 1, "90"), new WebTable.Cell(MESSAGES.colLimit(), 1, "60"), new WebTable.Cell(MESSAGES.colDays(), 1, "60"), new WebTable.Cell(MESSAGES.colStart(), 1, "60"), new WebTable.Cell(MESSAGES.colEnd(), 1, "60"), new WebTable.Cell(MESSAGES.colDate(), 1, "100"), new WebTable.Cell(MESSAGES.colRoom(), 1, "100"), new WebTable.Cell(MESSAGES.colInstructor(), 1, "120"), new WebTable.Cell(MESSAGES.colParent(), 1, "90"), new WebTable.Cell(MESSAGES.colHighDemand(), 1, "10") )); iClasses.setEmptyMessage(MESSAGES.courseSelectionNoCourseSelected()); iClassesPanel = new ScrollPanel(iClasses); iClassesPanel.setStyleName("unitime-ScrollPanel-inner"); iCourseDetailsTabPanel.add(iClassesPanel, "C<u>l</u>asses", true); iCurricula = new CourseCurriculaTable(false, false); iCurricula.setMessage(MESSAGES.courseSelectionNoCourseSelected()); iCurriculaPanel = new ScrollPanel(iCurricula); iCurriculaPanel.setStyleName("unitime-ScrollPanel-inner"); iCourseDetailsTabPanel.add(iCurriculaPanel, (ie ? "Cu<u>r</u>ricula" : "<u>C</u>urricula"), true); iCoursesTip = new Label(CONSTANTS.courseTips()[(int)(Math.random() * CONSTANTS.courseTips().length)]); iCoursesTip.setStyleName("unitime-Hint"); ToolBox.disableTextSelectInternal(iCoursesTip.getElement()); iCoursesTip.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { String oldText = iCoursesTip.getText(); do { iCoursesTip.setText(CONSTANTS.courseTips()[(int)(Math.random() * CONSTANTS.courseTips().length)]); } while (oldText.equals(iCoursesTip.getText())); } }); if (ie) { iCoursesPanel.setSize("780px", "400px"); iCourseDetailsPanel.setSize("780px", "400px"); iClassesPanel.setSize("780px", "400px"); iCurriculaPanel.setSize("780px", "400px"); iCoursesPanel.setStyleName("unitime-ScrollPanel-inner"); iCourseDetailsTabPanel.insert(iCoursesPanel, MESSAGES.courseSelectionCourses(), true, 0); } else { iCourseDetailsTabPanel.setDeckSize("780", "200"); iCourseDetailsTabPanel.setDeckStyleName("unitime-TabPanel"); iDialogPanel.add(iCoursesPanel); } iDialogPanel.add(iCourseDetailsTabPanel); iDialogPanel.add(iCoursesTip); iDialog.setWidget(iDialogPanel); final Timer finderTimer = new Timer() { @Override public void run() { updateCourses(); } }; iFilter.addKeyUpHandler(new KeyUpHandler() { public void onKeyUp(KeyUpEvent event) { finderTimer.schedule(500); if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER || event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE) { if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { if (iCourses.getSelectedRow()>=0) { WebTable.Row r = iCourses.getRows()[iCourses.getSelectedRow()]; iTextField.setText(MESSAGES.courseName(r.getCell(0).getValue(), r.getCell(1).getValue())); CourseSelectionChangeEvent e = new CourseSelectionChangeEvent(iTextField.getText(), true); for (CourseSelectionChangeHandler h : iCourseSelectionChangeHandlers) h.onChange(e); iTextField.setText(iFilter.getText()); } } iDialog.hide(); iImage.setResource(RESOURCES.search_picker()); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { setFocus(true); } }); } if (event.getNativeKeyCode()==KeyCodes.KEY_DOWN) { iCourses.setSelectedRow(iCourses.getSelectedRow()+1); scrollToSelectedRow(); updateCourseDetails(); } if (event.getNativeKeyCode()==KeyCodes.KEY_UP) { iCourses.setSelectedRow(iCourses.getSelectedRow()==0?iCourses.getRowsCount()-1:iCourses.getSelectedRow()-1); scrollToSelectedRow(); updateCourseDetails(); } if (event.getNativeEvent().getCtrlKey() && (event.getNativeKeyCode()=='c' || event.getNativeKeyCode()=='C')) { iCourseDetailsTabPanel.selectTab(ie ? 0 : 2); event.preventDefault(); } if (event.getNativeEvent().getCtrlKey() && (event.getNativeKeyCode()=='d' || event.getNativeKeyCode()=='D')) { iCourseDetailsTabPanel.selectTab(ie ? 1 : 0); event.preventDefault(); } if (event.getNativeEvent().getCtrlKey() && (event.getNativeKeyCode()=='l' || event.getNativeKeyCode()=='L')) { iCourseDetailsTabPanel.selectTab(ie ? 2 : 1); event.preventDefault(); } if (ie && event.getNativeEvent().getCtrlKey() && (event.getNativeKeyCode()=='r' || event.getNativeKeyCode()=='R')) { iCourseDetailsTabPanel.selectTab(3); event.preventDefault(); } } }); iFilter.addChangeHandler(new ChangeHandler() { public void onChange(ChangeEvent event) { updateCourses(); } }); iCourseDetailsTabPanel.addSelectionHandler(new SelectionHandler<Integer>() { public void onSelection(SelectionEvent<Integer> event) { sLastSelectedCourseDetailsTab = event.getSelectedItem(); } }); iCourses.addRowDoubleClickHandler(new WebTable.RowDoubleClickHandler() { public void onRowDoubleClick(RowDoubleClickEvent event) { WebTable.Row r = event.getRow(); iTextField.setText(MESSAGES.courseName(r.getCell(0).getValue(), r.getCell(1).getValue())); iDialog.hide(); iImage.setResource(RESOURCES.search_picker()); CourseSelectionChangeEvent e = new CourseSelectionChangeEvent(iTextField.getText(), true); for (CourseSelectionChangeHandler h : iCourseSelectionChangeHandlers) h.onChange(e); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { setFocus(true); } }); } }); iCourses.addRowClickHandler(new WebTable.RowClickHandler() { public void onRowClick(WebTable.RowClickEvent event) { iCourses.setSelectedRow(event.getRowIdx()); updateCourseDetails(); } }); iFilter.addBlurHandler(new BlurHandler() { public void onBlur(BlurEvent event) { if (iDialog.isShowing()) { Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { iFilter.setFocus(true); } }); } } }); } CourseFinderDialogEvent e = new CourseFinderDialogEvent(); for (CourseFinderDialogHandler h: iCourseFinderDialogHandlers) h.onOpen(e); iImage.setResource(RESOURCES.search_picker_Down()); iFilter.setText(iTextField.getText().equals(iHint)?"":iTextField.getText()); iCoursesTip.setText(CONSTANTS.courseTips()[(int)(Math.random() * CONSTANTS.courseTips().length)]); iCourseDetailsTabPanel.selectTab(sLastSelectedCourseDetailsTab); iDialog.center(); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { iFilter.setFocus(true); } }); updateCourses(); } @SuppressWarnings("deprecation") public void hideSuggestionList() { iSuggest.hideSuggestionList(); } public void showSuggestionList() { iSuggest.showSuggestionList(); } @Override public void setAccessKey(char a) { iTextField.setAccessKey(a); } public void setWidth(String width) { iSuggest.setWidth(width); } public void clear() { iTextField.setText(iHint); if (!iHint.isEmpty()) iTextField.setStyleName("unitime-TextBoxHint"); iError.setText(""); iError.setVisible(false); } public void setError(String error) { iError.setText(error); iError.setTitle(null); iError.setVisible(!iError.getText().isEmpty()); } public boolean hasError() { return iError.isVisible(); } private void scrollToSelectedRow() { if (iCourses.getSelectedRow()<0) return; Element scroll = iCoursesPanel.getElement(); Element item = iCourses.getTable().getRowFormatter().getElement(iCourses.getSelectedRow()); if (item==null) return; int realOffset = 0; while (item !=null && !item.equals(scroll)) { realOffset += item.getOffsetTop(); item = item.getOffsetParent(); } scroll.setScrollTop(realOffset - scroll.getOffsetHeight() / 2); } public void addCourseSelectionChangeHandler(CourseSelectionChangeHandler CourseSelectionChangeHandler) { iCourseSelectionChangeHandlers.add(CourseSelectionChangeHandler); } public String getCourse() { return (iTextField.getText().equals(iHint) ? "" : iTextField.getText()); } public void setCourse(String course, boolean fireChangeEvent) { iTextField.setText(course); if (iTextField.getText().isEmpty()) { if (iHint!=null) iTextField.setText(iHint); iTextField.setStyleName("unitime-TextBoxHint"); } else { iTextField.setStyleName("gwt-SuggestBox"); } if (fireChangeEvent) { CourseSelectionChangeEvent e = new CourseSelectionChangeEvent(iTextField.getText(), course != null && !course.isEmpty()); for (CourseSelectionChangeHandler h : iCourseSelectionChangeHandlers) h.onChange(e); } } public void setEnabled(boolean enabled) { if (enabled) { iTextField.setReadOnly(false); iImage.setVisible(true); iImage.setResource(RESOURCES.search_picker()); iTextField.getElement().getStyle().clearBorderColor(); iTextField.getElement().getStyle().clearBackgroundColor(); } else { iTextField.setReadOnly(true); iImage.setVisible(false); iImage.setResource(RESOURCES.search_picker_Disabled()); iTextField.getElement().getStyle().setBorderColor("transparent"); iTextField.getElement().getStyle().setBackgroundColor("transparent"); } } public boolean isEnabled() { return iTextField.isEnabled(); } private void updateCourses() { if (iCourseOfferingsCallback==null) { iCourseOfferingsCallback = new AsyncCallback<Collection<ClassAssignmentInterface.CourseAssignment>>() { public void onFailure(Throwable caught) { iCourses.clearData(true); iCourses.setEmptyMessage(caught.getMessage()); } public void onSuccess(Collection<ClassAssignmentInterface.CourseAssignment> result) { WebTable.Row[] records = new WebTable.Row[result.size()]; int idx = 0; boolean hasProj = false, hasEnrl = false, hasLastLike = false; int selectRow = -1; for (ClassAssignmentInterface.CourseAssignment record: result) { records[idx] = new WebTable.Row( record.getSubject(), record.getCourseNbr(), record.getTitle(), record.getLimitString(), record.getLastLikeString(), record.getProjectedString(), record.getEnrollmentString()); if (!hasEnrl && !record.getEnrollmentString().isEmpty()) hasEnrl = true; if (!hasProj && !record.getProjectedString().isEmpty()) hasProj = true; if (!hasLastLike && !record.getLastLikeString().isEmpty()) hasLastLike = true; records[idx].setId(record.getCourseId().toString()); if (iFilter.getText().equalsIgnoreCase(record.getSubject() + " " + record.getCourseNbr())) selectRow = idx; idx++; } iCourses.setData(records); iCourses.setColumnVisible(5, hasProj); iCourses.setColumnVisible(6, hasEnrl); iCourses.setColumnVisible(7, hasLastLike); if (records.length == 1) selectRow = 0; if (selectRow >= 0) { iCourses.setSelectedRow(selectRow); updateCourseDetails(); } } }; } if (iFilter.getText().equals(iLastQuery)) return; if (iFilter.getText().isEmpty()) { iCourses.setEmptyMessage(MESSAGES.courseSelectionNoCourseFilter()); } else { iCourses.setEmptyMessage(MESSAGES.courseSelectionLoadingCourses()); iCurriculaService.listCourseOfferings(iFilter.getText(), 100, iCourseOfferingsCallback); } iLastQuery = iFilter.getText(); } private void updateCourseDetails() { if (iCourseDetailsCallback==null) { iCourseDetailsCallback = new AsyncCallback<String>() { public void onFailure(Throwable caught) { iCourseDetails.setHTML("<table width='100%'></tr><td class='unitime-TableEmpty'><font color='red'>"+caught.getMessage()+"</font></td></tr></table>"); } public void onSuccess(String result) { iCourseDetails.setHTML(result); } }; } if (iCourseClassesCallback==null) { iCourseClassesCallback = new AsyncCallback<Collection<ClassAssignmentInterface.ClassAssignment>>() { public void onFailure(Throwable caught) { iClasses.setEmptyMessage(caught.getMessage()); } public void onSuccess(Collection<ClassAssignmentInterface.ClassAssignment> result) { if (!result.isEmpty()) { WebTable.Row[] rows = new WebTable.Row[result.size()]; int idx = 0; Long lastSubpartId = null; for (ClassAssignmentInterface.ClassAssignment clazz: result) { WebTable.Row row = new WebTable.Row( new WebTable.Cell(clazz.getSubpart()), new WebTable.Cell(clazz.getSection()), new WebTable.Cell(clazz.getLimitString()), new WebTable.Cell(clazz.getDaysString(CONSTANTS.shortDays())), new WebTable.Cell(clazz.getStartString()), new WebTable.Cell(clazz.getEndString()), new WebTable.Cell(clazz.getDatePattern()), new WebTable.Cell(clazz.getRooms(", ")), new WebTable.Cell(clazz.getInstructors(", ")), new WebTable.Cell(clazz.getParentSection()), (clazz.isOfHighDemand() ? new WebTable.IconCell(RESOURCES.highDemand(), MESSAGES.highDemand(clazz.getExpected(), clazz.getAvailableLimit()), null) : new WebTable.Cell(""))); row.setId(clazz.getClassId().toString()); String styleName = "unitime-ClassRow"; if (lastSubpartId != null && !clazz.getSubpartId().equals(lastSubpartId)) styleName += "First"; if (!clazz.isAvailable()) styleName += "Unavail"; for (WebTable.Cell cell: row.getCells()) cell.setStyleName(styleName); rows[idx++] = row; lastSubpartId = clazz.getSubpartId(); } iClasses.setData(rows); } else { String courseName = iFilter.getText(); try { WebTable.Row row = iCourses.getRows()[iCourses.getSelectedRow()]; courseName = MESSAGES.courseName(row.getCell(0).getValue(), row.getCell(1).getValue()); } catch (Exception e) {} iClasses.setEmptyMessage(MESSAGES.courseSelectionNoClasses(courseName)); } } }; } if (iCourses.getSelectedRow()<0) { iCourseDetails.setHTML("<table width='100%'></tr><td class='unitime-TableEmpty'>" + MESSAGES.courseSelectionNoCourseSelected() + "</td></tr></table>"); iClasses.setEmptyMessage(MESSAGES.courseSelectionNoCourseSelected()); iClasses.clearData(true); iCurricula.setMessage(MESSAGES.courseSelectionNoCourseSelected()); iCurricula.clear(false); } else { WebTable.Row row = iCourses.getRows()[iCourses.getSelectedRow()]; String courseName = MESSAGES.courseName(row.getCell(0).getValue(), row.getCell(1).getValue()); if (courseName.equals(iLastCourseLookup)) return; iCourseDetails.setHTML("<table width='100%'></tr><td class='unitime-TableEmpty'>" + MESSAGES.courseSelectionLoadingDetails() + "</td></tr></table>"); iCourseDetailsPanel.setVisible(true); iClasses.clearData(true); iClasses.setEmptyMessage(MESSAGES.courseSelectionLoadingClasses()); iCurriculaService.retrieveCourseDetails(courseName, iCourseDetailsCallback); iCurriculaService.listClasses(courseName, iCourseClassesCallback); iCurricula.setCourseName(courseName); iLastCourseLookup = courseName; } } @Override public void setFocus(boolean focus) { iTextField.setFocus(focus); if (focus) iTextField.selectAll(); } public class CourseSelectionChangeEvent{ private String iCourse; private boolean iValid; public CourseSelectionChangeEvent(String course, boolean valid) { iCourse = course; iValid = valid; } public String getCourse() { return iCourse; } public boolean isValid() { return iValid; } public CurriculaCourseSelectionBox getSource() { return CurriculaCourseSelectionBox.this; } } public interface CourseSelectionChangeHandler{ public void onChange(CourseSelectionChangeEvent evt); } public class SuggestCallback implements AsyncCallback<Collection<ClassAssignmentInterface.CourseAssignment>> { private Request iRequest; private Callback iCallback; public SuggestCallback(Request request, Callback callback) { iRequest = request; iCallback = callback; } public void onFailure(Throwable caught) { ArrayList<Suggestion> suggestions = new ArrayList<Suggestion>(); suggestions.add(new SimpleSuggestion("<font color='red'>"+caught.getMessage()+"</font>", "")); iCallback.onSuggestionsReady(iRequest, new Response(suggestions)); } public void onSuccess(Collection<ClassAssignmentInterface.CourseAssignment> result) { ArrayList<Suggestion> suggestions = new ArrayList<Suggestion>(); for (ClassAssignmentInterface.CourseAssignment suggestion: result) { String courseName = MESSAGES.courseName(suggestion.getSubject(), suggestion.getCourseNbr()); String courseNameWithTitle = (suggestion.getTitle() == null ? courseName : MESSAGES.courseNameWithTitle(suggestion.getSubject(), suggestion.getCourseNbr(), suggestion.getTitle())); suggestions.add(new SimpleSuggestion(courseNameWithTitle, courseName)); } iCallback.onSuggestionsReady(iRequest, new Response(suggestions)); } } public static class SimpleSuggestion implements Suggestion { private String iDisplay, iReplace; public SimpleSuggestion(String display, String replace) { iDisplay = display; iReplace = replace; } public SimpleSuggestion(String replace) { this(replace, replace); } public String getDisplayString() { return iDisplay; } public String getReplacementString() { return iReplace; } } public void setHint(String hint) { if (iTextField.getText().equals(iHint)) { iTextField.setText(hint); iTextField.setStyleName("unitime-TextBoxHint"); } iHint = hint; } public String getHint() { return iHint; } public static interface Validator { public String validate(CurriculaCourseSelectionBox source); } public void addValidator(Validator validator) { iValitaros.add(validator); } public void hideError() { iError.setVisible(false); } public void validate(final AsyncCallback<String> callback) { if (iTextField.getText().isEmpty() || iTextField.getText().equals(iHint)) { iError.setVisible(false); callback.onSuccess(null); return; } for (Validator validator: iValitaros) { String message = validator.validate(this); if (message!=null) { iError.setText(message); iError.setTitle(null); iError.setVisible(true); callback.onSuccess(message); return ; } } iError.setVisible(false); callback.onSuccess(null); } public void addFocusHandler(FocusHandler h) { iTextField.addFocusHandler(h); } public void addBlurHandler(BlurHandler h) { iTextField.addBlurHandler(h); } @Override public int getTabIndex() { return iTextField.getTabIndex(); } @Override public void setTabIndex(int index) { iTextField.setTabIndex(index); } public class CourseFinderDialogEvent { public CurriculaCourseSelectionBox getSource() { return CurriculaCourseSelectionBox.this; } } public interface CourseFinderDialogHandler { public void onOpen(CourseFinderDialogEvent e); } public void addCourseFinderDialogHandler(CourseFinderDialogHandler h) { iCourseFinderDialogHandlers.add(h); } } --- NEW FILE: CurriculumEdit.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.curricula; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.TreeSet; import org.unitime.timetable.gwt.client.curricula.CurriculaClassifications.ExpectedChangedEvent; import org.unitime.timetable.gwt.client.curricula.CurriculaClassifications.NameChangedEvent; import org.unitime.timetable.gwt.client.page.UniTimePageLabel; import org.unitime.timetable.gwt.client.widgets.LoadingWidget; import org.unitime.timetable.gwt.client.widgets.SimpleForm; import org.unitime.timetable.gwt.client.widgets.UniTimeHeaderPanel; import org.unitime.timetable.gwt.client.widgets.UniTimeTextBox; import org.unitime.timetable.gwt.client.widgets.UniTimeWidget; import org.unitime.timetable.gwt.services.CurriculaService; import org.unitime.timetable.gwt.services.CurriculaServiceAsync; import org.unitime.timetable.gwt.shared.CurriculumInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.AcademicAreaInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.AcademicClassificationInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.CourseInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.CurriculumClassificationInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.CurriculumStudentsInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.DepartmentInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.MajorInterface; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.ValueBoxBase; /** * @author Tomas Muller */ public class CurriculumEdit extends Composite { private final CurriculaServiceAsync iService = GWT.create(CurriculaService.class); private SimpleForm iCurriculaTable; private UniTimeHeaderPanel iTitleAndButtons; private UniTimeWidget<TextBox> iCurriculumAbbv, iCurriculumName; private UniTimeWidget<ListBox> iCurriculumMajors, iCurriculumArea, iCurriculumDept; private CurriculaClassificationsPanel iCurriculumClasfTable = null; private boolean iDefaultAbbv = false, iDefaultName = false; private List<AcademicAreaInterface> iAreas = new ArrayList<AcademicAreaInterface>(); private List<DepartmentInterface> iDepts = new ArrayList<DepartmentInterface>(); private List<MajorInterface> iMajors = new ArrayList<MajorInterface>(); private List<AcademicClassificationInterface> iClassifications = new ArrayList<AcademicClassificationInterface>(); private CurriculumInterface iCurriculum = null; private CurriculaCourses iCurriculumCourses; private List<EditFinishedHandler> iEditFinishedHandlers = new ArrayList<EditFinishedHandler>(); private boolean iAreaHasNoMajors = false; private Mode iMode; private boolean iSaved = false; public static enum Mode { ADD("Add Curriculum", true, true), EDIT("Edit Curriculum", true, true), DETAILS("Curriculum Detail", false, false), DIALOG(null, true, false); private String iTitle; private boolean iEditable, iEditableDetails; Mode(String title, boolean editable, boolean details) { iTitle = title; iEditable = editable; iEditableDetails = details; } public boolean hasTitle() { return iTitle != null; } public String getTitle() { return iTitle; } public boolean isEditable() { return iEditable; } public boolean areDetailsEditable() { return iEditableDetails; } } public CurriculumEdit() { ClickHandler backHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { if (iMode == Mode.EDIT) { // back to detail screen loadCurriculum(Mode.DETAILS); } else { EditFinishedEvent e = new EditFinishedEvent(); for (EditFinishedHandler h: iEditFinishedHandlers) { if (iSaved) h.onSave(e); else h.onBack(e); } } } }; ClickHandler saveHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { if (saveCurriculum()) { showLoading("Saving curriculum " + iCurriculum.getName() + " ..."); iService.saveCurriculum(iCurriculum, new AsyncCallback<Long>() { @Override public void onFailure(Throwable caught) { hideLoading(); iTitleAndButtons.setErrorMessage("Validation failed (" + caught.getMessage() + ")."); } @Override public void onSuccess(Long result) { if (iMode == Mode.EDIT) { // back to details page iCurriculum.setId(result); reload(Mode.DETAILS); iSaved = true; } else { EditFinishedEvent e = new EditFinishedEvent(); for (EditFinishedHandler h: iEditFinishedHandlers) { h.onSave(e); } } hideLoading(); } }); } else { iTitleAndButtons.setErrorMessage("Validation failed, see errors below."); } } }; ClickHandler deleteHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { if (!Window.confirm("Do you realy want to delete this curriculum?")) return; showLoading("Deleting curriculum " + iCurriculum.getName() + " ..."); iService.deleteCurriculum(iCurriculum.getId(), new AsyncCallback<Boolean>() { @Override public void onFailure(Throwable caught) { iTitleAndButtons.setErrorMessage("Delete failed (" + caught.getMessage() + ")."); hideLoading(); } @Override public void onSuccess(Boolean result) { EditFinishedEvent e = new EditFinishedEvent(); for (EditFinishedHandler h: iEditFinishedHandlers) { h.onDelete(e); } hideLoading(); } }); } }; ClickHandler printHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { Window.print(); } }; ClickHandler editHandler = new ClickHandler() { @Override public void onClick(ClickEvent event) { loadCurriculum(Mode.EDIT); } }; iCurriculaTable = new SimpleForm(); iTitleAndButtons = new UniTimeHeaderPanel("Curriculum Details"); iTitleAndButtons.addButton("edit", "<u>E</u>dit", 'e', 75, editHandler); iTitleAndButtons.addButton("save", "<u>S</u>ave", 's', 75, saveHandler); iTitleAndButtons.addButton("delete", "<u>D</u>elete", 'd', 75, deleteHandler); iTitleAndButtons.addButton("print", "<u>P</u>rint", 'p', 75, printHandler); iTitleAndButtons.addButton("back", "<u>B</u>ack", 'b', 75, backHandler); iCurriculaTable.addHeaderRow(iTitleAndButtons); iCurriculumAbbv = new UniTimeWidget<TextBox>(new UniTimeTextBox(20, ValueBoxBase.TextAlignment.LEFT)); iCurriculaTable.addRow("Abbreviation:", iCurriculumAbbv); iCurriculumAbbv.getWidget().addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { iDefaultAbbv = false; iCurriculumAbbv.clearHint(); } }); iCurriculumName = new UniTimeWidget<TextBox>(new UniTimeTextBox(60, 500)); iCurriculaTable.addRow("Name:", iCurriculumName); iCurriculumName.getWidget().addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { iDefaultName = false; iCurriculumName.clearHint(); } }); iCurriculumArea = new UniTimeWidget<ListBox>(new ListBox(false)); iCurriculumArea.getWidget().setWidth("300px"); iCurriculumArea.getWidget().setStyleName("unitime-TextBox"); iCurriculumArea.getWidget().setVisibleItemCount(1); iCurriculaTable.addRow("Academic Area:", iCurriculumArea); iCurriculumArea.getWidget().addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { if (iDefaultName || iDefaultAbbv) { try { if (iCurriculumArea.getWidget().getSelectedIndex() == 0) { if (iDefaultAbbv) iCurriculumAbbv.getWidget().setText(""); if (iDefaultName) iCurriculumName.getWidget().setText(""); } else { AcademicAreaInterface area = iAreas.get(iCurriculumArea.getWidget().getSelectedIndex() - 1); if (iDefaultAbbv) iCurriculumAbbv.getWidget().setText(area.getAbbv()); if (iDefaultName) iCurriculumName.getWidget().setText(area.getName()); } } catch (Exception e) {} } iCurriculumArea.clearHint(); loadMajors(true); } }); iCurriculumMajors = new UniTimeWidget<ListBox>(new ListBox(true)); iCurriculumMajors.getWidget().setWidth("300px"); iCurriculumMajors.getWidget().setStyleName("unitime-TextBox"); iCurriculumMajors.getWidget().setVisibleItemCount(3); iCurriculumMajors.getWidget().setHeight("100px"); iCurriculaTable.addRow("Major(s):", iCurriculumMajors); iCurriculumMajors.getWidget().addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { try { String defaultAbbv = "", defaultName = ""; AcademicAreaInterface area = iAreas.get(iCurriculumArea.getWidget().getSelectedIndex() - 1); defaultAbbv = area.getAbbv(); defaultName = area.getName(); String majors = ""; for (int i = 0; i < iCurriculumMajors.getWidget().getItemCount(); i++) { if (iCurriculumMajors.getWidget().isItemSelected(i)) { MajorInterface m = iMajors.get(i); if (!defaultAbbv.contains("/")) { defaultAbbv += "/"; defaultName += " / "; } else { defaultAbbv += ","; defaultName += ", "; } defaultAbbv += m.getCode(); defaultName += m.getName(); if (!majors.isEmpty()) majors += "<br>"; majors += m.getName(); } } if (defaultName.length() > 60) defaultName = defaultName.substring(0, 60); if (defaultAbbv.length() > 20) defaultAbbv = defaultAbbv.substring(0, 20); if (iDefaultAbbv) iCurriculumAbbv.getWidget().setText(defaultAbbv); if (iDefaultName) iCurriculumName.getWidget().setText(defaultName); iCurriculumMajors.setPrintText(majors); } catch (Exception e) {} loadEnrollments(true); } }); iCurriculumDept = new UniTimeWidget<ListBox>(new ListBox(false)); iCurriculumDept.getWidget().setWidth("300px"); iCurriculumDept.getWidget().setStyleName("unitime-TextBox"); iCurriculumDept.getWidget().setVisibleItemCount(1); iCurriculaTable.addRow("Department:", iCurriculumDept); iCurriculaTable.addRow("Last Change:", new Label("",false)); iCurriculaTable.getRowFormatter().setVisible(6, false); iCurriculumDept.getWidget().addChangeHandler(new ChangeHandler() { @Override public void onChange(ChangeEvent event) { iCurriculumDept.clearHint(); } }); iCurriculaTable.addHeaderRow("Curriculum Classifications"); iCurriculumClasfTable = new CurriculaClassificationsPanel(new CurriculaClassifications()); iCurriculaTable.addRow(iCurriculumClasfTable); iCurriculumCourses = new CurriculaCourses(); iCurriculaTable.addHeaderRow("Course Projections"); iCurriculaTable.addRow(iCurriculumCourses); iCurriculaTable.addNotPrintableBottomRow(iTitleAndButtons.clonePanel(null)); initWidget(iCurriculaTable); } public Mode getMode() { return iMode; } private void loadCurriculum(Mode mode) { iMode = mode; if (iMode.hasTitle()) UniTimePageLabel.getInstance().setPageName(iMode.getTitle()); if (iCurriculum.getId() == null) { iDefaultAbbv = true; iDefaultName = true; } else { iDefaultAbbv = false; iDefaultName = false; } if (iDepts.isEmpty() || iAreas.isEmpty()) iCurriculum.setEditable(false); iCurriculumAbbv.clearHint(); iCurriculumName.clearHint(); iCurriculumArea.clearHint(); iCurriculumDept.clearHint(); iCurriculumClasfTable.clearHint(); iTitleAndButtons.clearMessage(); iTitleAndButtons.setEnabled("delete", iMode == Mode.DETAILS && iCurriculum.getId() != null && iCurriculum.isEditable()); iTitleAndButtons.setEnabled("save", iCurriculum.isEditable() && iMode.isEditable()); iTitleAndButtons.setEnabled("edit", iCurriculum.isEditable() && !iMode.isEditable()); iTitleAndButtons.setEnabled("print", iMode == Mode.DETAILS); if (iCurriculum.hasLastChange() && iMode == Mode.DETAILS) { ((Label)iCurriculaTable.getWidget(6, 1)).setText(iCurriculum.getLastChange()); iCurriculaTable.getRowFormatter().setVisible(6, true); } else { iCurriculaTable.getRowFormatter().setVisible(6, false); } iCurriculumAbbv.getWidget().setText(iCurriculum.getAbbv()); iCurriculumAbbv.getWidget().setReadOnly(!iCurriculum.isEditable() || !iMode.areDetailsEditable() || !iMode.isEditable()); iCurriculumName.getWidget().setText(iCurriculum.getName()); iCurriculumName.getWidget().setReadOnly(!iCurriculum.isEditable() || !iMode.areDetailsEditable() || !iMode.isEditable()); iCurriculumArea.getWidget().setSelectedIndex(0); if (iCurriculum.getAcademicArea() != null) { for (int i = 0; i < iAreas.size(); i++) if (iAreas.get(i).getId().equals(iCurriculum.getAcademicArea().getId())) iCurriculumArea.getWidget().setSelectedIndex(1 + i); } iCurriculumArea.setText(iCurriculum.getAcademicArea() == null ? "" : iCurriculum.getAcademicArea().getName()); iCurriculumArea.setReadOnly(!iCurriculum.isEditable() || !iMode.areDetailsEditable() || !iMode.isEditable()); iCurriculumDept.getWidget().setSelectedIndex(0); if (iCurriculum.getDepartment() != null) { for (int i = 0; i < iDepts.size(); i++) if (iDepts.get(i).getId().equals(iCurriculum.getDepartment().getId())) iCurriculumDept.getWidget().setSelectedIndex(1 + i); } iCurriculumDept.setText(iCurriculum.getDepartment() == null ? "" : iCurriculum.getDepartment().getLabel()); iCurriculumDept.setReadOnly(!iCurriculum.isEditable() || !iMode.areDetailsEditable() || !iMode.isEditable()); iCurriculumMajors.setReadOnly(!iCurriculum.isEditable() || !iMode.areDetailsEditable() || !iMode.isEditable()); iCurriculumMajors.setText(iCurriculum.getCodeMajorNames("<br>")); iCurriculumMajors.setPrintText(iCurriculum.getCodeMajorNames("<br>")); loadMajors(iMode.areDetailsEditable()); iCurriculumClasfTable.populate(iCurriculum.getClassifications()); iCurriculumClasfTable.setReadOnly(!iCurriculum.isEditable() || !iMode.isEditable()); iCurriculumCourses.populate(iCurriculum, iMode.isEditable()); for (int col = 0; col < iClassifications.size(); col++) { if (iCurriculumClasfTable.getWidget().getExpected(col) == null) iCurriculumCourses.setVisible(col, false); } } public boolean saveCurriculum() { boolean ret = true; iCurriculum.setAbbv(iCurriculumAbbv.getWidget().getText()); if (iCurriculum.getAbbv().isEmpty()) { iCurriculumAbbv.setErrorHint("Curriculum abbreviation must be filled in."); ret = false; } iCurriculum.setName(iCurriculumName.getWidget().getText()); if (iCurriculum.getName().isEmpty()) { iCurriculumName.setErrorHint("Curriculum name must be filled in."); ret = false; } if (iCurriculumArea.getWidget().getSelectedIndex() <= 0) { iCurriculumArea.setErrorHint("An academic area must be selected."); ret = false; } else { AcademicAreaInterface a = new AcademicAreaInterface(); a.setId(Long.valueOf(iCurriculumArea.getWidget().getValue(iCurriculumArea.getWidget().getSelectedIndex()))); iCurriculum.setAcademicArea(a); } if (iCurriculum.hasMajors()) { iCurriculum.getMajors().clear(); } for (int i = 0; i < iCurriculumMajors.getWidget().getItemCount(); i++) { if (iCurriculumMajors.getWidget().isItemSelected(i)) { MajorInterface m = new MajorInterface(); m.setId(Long.valueOf(iCurriculumMajors.getWidget().getValue(i))); iCurriculum.addMajor(m); } } if (!iCurriculum.hasMajors()) for (int i = 0; i < iCurriculumMajors.getWidget().getItemCount(); i++) { MajorInterface m = new MajorInterface(); m.setId(Long.valueOf(iCurriculumMajors.getWidget().getValue(i))); iCurriculum.addMajor(m); } if (iCurriculumMajors.getWidget().getItemCount() == 0 && iCurriculumArea.getWidget().getSelectedIndex() > 0 && !iAreaHasNoMajors) { iCurriculumArea.setErrorHint("Selected academic area has no majors without a curriculum."); ret = false; } if (iCurriculumDept.getWidget().getSelectedIndex() <= 0) { iCurriculumDept.setErrorHint("A controlling department must be selected."); ret = false; } else { DepartmentInterface d = new DepartmentInterface(); d.setId(Long.valueOf(iCurriculumDept.getWidget().getValue(iCurriculumDept.getWidget().getSelectedIndex()))); iCurriculum.setDepartment(d); } if (!iCurriculumClasfTable.getWidget().saveCurriculum(iCurriculum)) { ret = false; } if (!iCurriculum.hasClassifications()) { iCurriculumClasfTable.setErrorHint("At least some students must be expected."); ret = false; } if (!iCurriculumCourses.saveCurriculum(iCurriculum)) { ret = false; } return ret; } private void loadMajors(final boolean showEmptyCourses) { if (iCurriculumArea.getWidget().getSelectedIndex() > 0) { showLoading("Loading majors ..."); iService.loadMajors(iCurriculum.getId(), Long.valueOf(iCurriculumArea.getWidget().getValue(iCurriculumArea.getWidget().getSelectedIndex())), new AsyncCallback<TreeSet<MajorInterface>>() { @Override public void onFailure(Throwable caught) { hideLoading(); } @Override public void onSuccess(TreeSet<MajorInterface> result) { if (result == null) { iAreaHasNoMajors = true; result = new TreeSet<MajorInterface>(); } else { iAreaHasNoMajors = false; } String defaultAbbv = "", defaultName = ""; AcademicAreaInterface area = null; try { if (iCurriculumArea.getWidget().getSelectedIndex() > 0) { area = iAreas.get(iCurriculumArea.getWidget().getSelectedIndex() - 1); defaultAbbv = area.getAbbv(); defaultName = area.getName(); } } catch (Exception e) {} iMajors.clear(); iMajors.addAll(result); iCurriculumMajors.getWidget().clear(); int idx = 0; boolean allSelected = true; CurriculumCookie.getInstance().getCurriculaDisplayMode(); for (MajorInterface m: result) { iCurriculumMajors.getWidget().addItem(m.getCode() + " - " + m.getName(), m.getId().toString()); if (iCurriculum != null && iCurriculum.hasMajors()) { iCurriculumMajors.getWidget().setItemSelected(idx, iCurriculum.getMajors().contains(m)); if (iCurriculum.getMajors().contains(m)) { if (!defaultAbbv.contains("/")) { defaultAbbv += "/"; defaultName += " / "; } else { defaultAbbv += ","; defaultName += ", "; } defaultAbbv += m.getCode(); defaultName += m.getName(); } else { allSelected = false; } } idx++; } if (defaultName.length() > 60) defaultName = defaultName.substring(0, 60); if (defaultAbbv.length() > 20) defaultAbbv = defaultAbbv.substring(0, 20); iDefaultAbbv = defaultAbbv.equals(iCurriculumAbbv.getWidget().getText()); iDefaultName = defaultName.equalsIgnoreCase(iCurriculumName.getWidget().getText()); if (!iDefaultAbbv && allSelected && area != null && area.getAbbv().equals(iCurriculumAbbv.getWidget().getText())) iDefaultAbbv = true; if (!iDefaultName && allSelected && area != null && area.getName().equalsIgnoreCase(iCurriculumName.getWidget().getText())) iDefaultName = true; iCurriculumMajors.getWidget().setVisibleItemCount(iCurriculumMajors.getWidget().getItemCount() <= 3 ? 3 : iCurriculumMajors.getWidget().getItemCount() > 10 ? 10 : iCurriculumMajors.getWidget().getItemCount()); loadEnrollments(showEmptyCourses); hideLoading(); } }); } else { iCurriculumMajors.getWidget().clear(); } } private void loadEnrollments(final boolean showEmptyCourses) { if (iCurriculumArea.getWidget().getSelectedIndex() >= 0) { final Long areaId = Long.valueOf(iCurriculumArea.getWidget().getValue(iCurriculumArea.getWidget().getSelectedIndex())); final List<Long> majorIds = new ArrayList<Long>(); for (int i = 0; i < iCurriculumMajors.getWidget().getItemCount(); i++) { if (iCurriculumMajors.getWidget().isItemSelected(i)) majorIds.add(Long.valueOf(iCurriculumMajors.getWidget().getValue(i))); } if (majorIds.isEmpty()) { for (int i = 0; i < iCurriculumMajors.getWidget().getItemCount(); i++) { majorIds.add(Long.valueOf(iCurriculumMajors.getWidget().getValue(i))); } } if (majorIds.isEmpty() && !iAreaHasNoMajors) return; showLoading("Loading course enrollments ..."); iService.computeEnrollmentsAndLastLikes(areaId, majorIds, new AsyncCallback<HashMap<String,CurriculumStudentsInterface[]>>() { @Override public void onFailure(Throwable caught) { hideLoading(); } @Override public void onSuccess(HashMap<String, CurriculumStudentsInterface[]> result) { CurriculumStudentsInterface[] x = result.get(""); for (int col = 0; col < iClassifications.size(); col++) { iCurriculumClasfTable.getWidget().setEnrollment(col, x == null || x[col] == null ? null : x[col].getEnrollment()); iCurriculumClasfTable.getWidget().setLastLike(col, x == null || x[col] == null ? null : x[col].getLastLike()); iCurriculumClasfTable.getWidget().setProjection(col, x == null || x[col] == null ? null : x[col].getProjection()); } iCurriculumCourses.updateEnrollmentsAndLastLike(result, showEmptyCourses); if (iCurriculumClasfTable.isShowingAllColumns()) iCurriculumClasfTable.getWidget().showAllColumns(); else iCurriculumClasfTable.getWidget().hideEmptyColumns(); hideLoading(); } }); } } public void showLoading(String message) { LoadingWidget.getInstance().show(message); } public void hideLoading() { LoadingWidget.getInstance().hide(); } public static class EditFinishedEvent { } public static interface EditFinishedHandler { public void onBack(EditFinishedEvent evt); public void onDelete(EditFinishedEvent evt); public void onSave(EditFinishedEvent evt); } public void addEditFinishedHandler(EditFinishedHandler h) { iEditFinishedHandlers.add(h); } public void addNew() { iSaved = false; iCurriculum = new CurriculumInterface(); iCurriculum.setEditable(true); if (iDepts.size() == 1) { DepartmentInterface d = iDepts.get(0); iCurriculumDept.getWidget().setSelectedIndex(1); iCurriculum.setDepartment(d); } loadCurriculum(Mode.ADD); } public void edit(CurriculumInterface curriculum, boolean detailsEditable) { iSaved = false; iCurriculum = curriculum; loadCurriculum(detailsEditable ? Mode.DETAILS : Mode.DIALOG); } public void setupAreas(TreeSet<AcademicAreaInterface> result) { iAreas.clear(); iAreas.addAll(result); iCurriculumArea.getWidget().clear(); iCurriculumArea.getWidget().addItem("Select ...", ""); for (AcademicAreaInterface area: result) { iCurriculumArea.getWidget().addItem(area.getAbbv() + " - " + area.getName(), area.getId().toString()); } } public void setupDepartments(TreeSet<DepartmentInterface> result) { iDepts.clear(); iDepts.addAll(result); iCurriculumDept.getWidget().clear(); iCurriculumDept.getWidget().addItem("Select ...", ""); for (DepartmentInterface dept: result) { iCurriculumDept.getWidget().addItem(dept.getLabel(), dept.getId().toString()); } } public void setupClassifications(TreeSet<AcademicClassificationInterface> result) { iClassifications.clear(); iClassifications.addAll(result); iCurriculumClasfTable.getWidget().setup(iClassifications); iCurriculumCourses.link(iCurriculumClasfTable.getWidget()); } public void showOnlyCourses(TreeSet<CourseInterface> courses) { iCurriculumCourses.showOnlyCourses(courses); } private static class CurriculaClassificationsPanel extends UniTimeWidget<CurriculaClassifications> { private Label iHint; public CurriculaClassificationsPanel(CurriculaClassifications classifications) { super(classifications); iHint = new Label(); iHint.setStyleName("unitime-Hint"); iHint.setVisible(true); iHint.addStyleName("unitime-NoPrint"); getPanel().insert(iHint, 1); iHint.setText("Show all columns."); iHint.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (isShowingAllColumns()) { getWidget().hideEmptyColumns(); iHint.setText("Show all columns."); } else { getWidget().showAllColumns(); iHint.setText("Hide empty columns."); } } }); getWidget().addExpectedChangedHandler(new CurriculaClassifications.ExpectedChangedHandler() { @Override public void expectedChanged(ExpectedChangedEvent e) { clearHint(); } }); getWidget().addNameChangedHandler(new CurriculaClassifications.NameChangedHandler() { @Override public void nameChanged(NameChangedEvent e) { clearHint(); } }); } public boolean isShowingAllColumns() { return iHint.getText().equals("Hide empty columns."); } public void populate(TreeSet<CurriculumClassificationInterface> classifications) { getWidget().populate(classifications); if (isShowingAllColumns()) getWidget().showAllColumns(); else getWidget().hideEmptyColumns(); } public void setReadOnly(boolean readOnly) { getWidget().setEnabled(!readOnly); iHint.setVisible(!readOnly); } } public void reload(final Mode mode) { showLoading("Loading curriculum " + iCurriculum.getName() + " ..."); iService.loadCurriculum(iCurriculum.g... [truncated message content] |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/shared In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/shared Added Files: MenuInterface.java CurriculaException.java SimpleEditException.java EventInterface.java PersonInterface.java SimpleEditInterface.java MenuException.java CourseRequestInterface.java EventException.java LookupException.java SectioningException.java AcademicSessionProvider.java CurriculumInterface.java SectioningExceptionType.java ClassAssignmentInterface.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: SimpleEditException.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; /** * @author Tomas Muller */ public class SimpleEditException extends RuntimeException { private static final long serialVersionUID = -6933848623255654126L; public SimpleEditException() { super(); } public SimpleEditException(String message) { super(message); } } --- NEW FILE: SimpleEditInterface.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import com.google.gwt.user.client.rpc.IsSerializable; /** * @author Tomas Muller */ public class SimpleEditInterface implements IsSerializable { public static enum Type { area("Academic Areas"), classification("Academic Classifications"), major("Majors"), minor("Minors"); private String iPageName; Type(String pageName) { iPageName = pageName; } public String getTitle() { return iPageName; } } public static enum FieldType { text, toggle, list, multi; } private Type iType = null; private List<Record> iRecords = new ArrayList<Record>(); private Field[] iFields = null; private boolean iEditable = true; private int[] iSort = null; public SimpleEditInterface() { } public SimpleEditInterface(Type type, Field... fields) { iType = type; iFields = fields; } public Type getType() { return iType; } public List<Record> getRecords() { return iRecords; } public Record addRecord(Long uniqueId) { Record r = new Record(uniqueId, iFields.length); iRecords.add(r); return r; } public Record insertEmptyRecord(int pos) { Record r = new Record(null, iFields.length); iRecords.add(pos, r); return r; } public void moveRecord(int row, int before) { Record r = iRecords.get(row); iRecords.remove(row); iRecords.add(before + (row < before ? -1 : 0), r); } public Record getRecord(Long uniqueId) { for (Record r: iRecords) if (r.getUniqueId() != null && r.getUniqueId().equals(uniqueId)) return r; return null; } public List<Record> getNewRecords() { List<Record> ret = new ArrayList<Record>(); for (Record r: iRecords) { if (r.getUniqueId() != null || r.isEmpty()) continue; ret.add(r); } return ret; } public Field[] getFields() { return iFields; } public int indexOf(String name) { for (int i = 0; i < iFields.length; i++) if (iFields[i].getName().equals(name)) return i; return -1; } public boolean isEditable() { return iEditable; } public void setEditable(boolean editable) { iEditable = editable; } public int[] getSortBy() { return iSort; } public void setSortBy(int... columns) { iSort = columns; } public Comparator<Record> getComparator() { return new RecordComparator(); } public class RecordComparator implements Comparator<Record> { public int compare(Record r1, Record r2) { if (getSortBy() != null) { for (int i: getSortBy()) { String s1 = r1.getText(getFields()[i], i); String s2 = r2.getText(getFields()[i], i); int cmp = s1.compareTo(s2); if (cmp != 0) return cmp; } } else { for (int i = 0; i < r1.getValues().length; i++) { String s1 = r1.getText(getFields()[i], i); String s2 = r2.getText(getFields()[i], i); int cmp = s1.compareTo(s2); if (cmp != 0) return cmp; } } return r1.getUniqueId().compareTo(r2.getUniqueId()); } } public static class Record implements IsSerializable { private Long iUniqueId = null; private String[] iValues = null; public Record() { } public Record(Long uniqueId, int nrFields) { iUniqueId = uniqueId; iValues = new String[nrFields]; for (int i = 0; i < nrFields; i++) iValues[i] = null; } public Long getUniqueId() { return iUniqueId; } public void setUniqueId(Long uniqueId) { iUniqueId = uniqueId; } public void setField(int index, String value) { iValues[index] = value; } public String getField(int index) { return iValues[index]; } public void addToField(int index, String value) { if (iValues[index] == null) iValues[index] = value; else iValues[index] += "|" + value; } public String[] getValues(int index) { return (iValues[index] == null ? new String[] {} : iValues[index].split("\\|")); } public String[] getValues() { return iValues; } public void setValues(String[] values) { iValues = values; } public String getText(Field f, int index) { String value = getField(index); if (value == null) return ""; if (f.getType() == FieldType.list) { for (ListItem item: f.getValues()) { if (item.getValue().equals(value)) return item.getText(); } } else if (f.getType() == FieldType.multi) { String text = ""; for (String val: getValues(index)) { for (ListItem item: f.getValues()) { if (item.getValue().equals(val)) { if (!text.isEmpty()) text += ", "; text += item.getText(); } } } return text; } return value; } public boolean isEmpty() { if (getUniqueId() != null) return false; for (String v: iValues) { if (v != null && !v.isEmpty()) return false; } return true; } } public static class ListItem implements IsSerializable { private String iValue, iText; public ListItem() {} public ListItem(String value, String text) { iValue = value; iText = text; } public String getValue() { return iValue; } public String getText() { return iText; } } public static class Field implements IsSerializable { private String iName = null; private FieldType iType = null; private int iLength = 0, iWidth = 0; private List<ListItem> iValues = null; public Field() {} public Field(String name, FieldType type, int width) { iName = name; iType = type; iWidth = width; } public Field(String name, FieldType type, int width, int length) { this(name, type, width); iLength = length; } public Field(String name, FieldType type, int width, List<ListItem> values) { this(name, type, width); iValues = values; } public String getName() { return iName; } public FieldType getType() { return iType; } public int getLength() { return iLength; } public int getWidth() { return iWidth; } public List<ListItem> getValues() { return iValues; } public void addValue(ListItem item) { if (iValues == null) iValues = new ArrayList<ListItem>(); iValues.add(item); } public int hashCode() { return getName().hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof Field)) return false; return getName().equals(((Field)o).getName()); } } } --- NEW FILE: EventException.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; /** * @author Tomas Muller */ public class EventException extends RuntimeException { private static final long serialVersionUID = 5742835800885383453L; public EventException() { super(); } public EventException(String message) { super(message); } } --- NEW FILE: EventInterface.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.TreeSet; import com.google.gwt.user.client.rpc.IsSerializable; /** * @author Tomas Muller */ public class EventInterface implements Comparable<EventInterface>, IsSerializable { private Long iEventId; private String iEventName; private String iEventType; private TreeSet<MeetingInterface> iMeetings = null; private String iSponsor, iInstructor, iContact, iEmail; private List<String> iCourseNames = null; private String iInstruction = null; private Integer iInstructionType = null; private List<String> iExternalIds = null; public static enum ResourceType { ROOM("room", "Room Timetable"), SUBJECT("subject", "Subject Timetable"), CURRICULUM("curriculum", "Curriculum Timetable"), DEPARTMENT("department", "Departmental Timetable"), PERSON("person", "Personal Timetable"); private String iLabel; private String iPageTitle; ResourceType(String label, String title) { iLabel = label; iPageTitle = title; } public String getLabel() { return iLabel; } public String getPageTitle() { return iPageTitle; } } public EventInterface() {} public Long getId() { return iEventId; } public void setId(Long id) { iEventId = id; } public String getName() { return iEventName; } public void setName(String name) { iEventName = name; } public String getType() { return iEventType; } public void setType(String type) { iEventType = type; } public String getSponsor() { return iSponsor; } public void setSponsor(String sponsor) { iSponsor = sponsor; } public boolean hasSponsor() { return iSponsor != null && !iSponsor.isEmpty(); } public String getInstructor() { return iInstructor; } public void setInstructor(String instructor) { iInstructor = instructor; } public boolean hasInstructor() { return iInstructor != null && !iInstructor.isEmpty(); } public String getEmail() { return iEmail; } public void setEmail(String email) { iEmail = email; } public String getContact() { return iContact; } public void setContact(String contact) { iContact = contact; } public boolean hasContact() { return iContact != null && !iContact.isEmpty(); } public boolean hasMeetings() { return iMeetings != null && !iMeetings.isEmpty(); } public void addMeeting(MeetingInterface meeting) { if (iMeetings == null) iMeetings = new TreeSet<MeetingInterface>(); iMeetings.add(meeting); } public TreeSet<MeetingInterface> getMeetings() { return iMeetings; } public boolean hasCourseNames() { return iCourseNames != null && !iCourseNames.isEmpty(); } public void addCourseName(String name) { if (iCourseNames == null) iCourseNames = new ArrayList<String>(); iCourseNames.add(name); } public List<String> getCourseNames() { return iCourseNames; } public boolean hasInstruction() { return iInstruction != null && !iInstruction.isEmpty(); } public String getInstruction() { return iInstruction; } public void setInstruction(String instruction) { iInstruction = instruction; } public boolean hasInstructionType() { return iInstructionType != null; } public Integer getInstructionType() { return iInstructionType; } public void setInstructionType(Integer type) { iInstructionType = type; } public boolean hasExternalIds() { return iExternalIds != null && !iExternalIds.isEmpty(); } public List<String> getExternalIds() { return iExternalIds; } public void addExternalId(String externalId) { if (iExternalIds == null) iExternalIds = new ArrayList<String>(); iExternalIds.add(externalId); } public int hashCode() { return getId().hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof EventInterface)) return false; return getId().equals(((EventInterface)o).getId()); } public int compareTo(EventInterface event) { int cmp = getType().compareTo(event.getType()); if (cmp != 0) return cmp; if (hasInstructionType()) { cmp = getInstructionType().compareTo(event.getInstructionType()); if (cmp != 0) return cmp; } cmp = getName().compareTo(event.getName()); if (cmp != 0) return cmp; return getId().compareTo(event.getId()); } public static class IdValueInterface implements IsSerializable { private String iId, iValue; private boolean iSelected = false; public IdValueInterface() {} public IdValueInterface(String id, String value) { iId = id; iValue = value; } public String getId() { return iId; } public void setId(String id) { iId = id; } public String getValue() { return iValue; } public void setValue(String value) { iValue = value; } public boolean isSelected() { return iSelected; } public void setSelected(boolean selected) { iSelected = selected; } } public static class ResourceInterface implements IsSerializable, Comparable<ResourceInterface> { private ResourceType iResourceType; private Long iResourceId; private String iExternalId; private String iAbbreviation; private String iResourceName; private String iTitle; private Long iSessionId; private String iSessionName; private String iSessionAbbv; private List<WeekInterface> iWeeks = null; private String iCalendar; public ResourceInterface() {} public ResourceType getType() { return iResourceType; } public void setType(ResourceType type) { iResourceType = type; } public Long getId() { return iResourceId; } public void setId(Long id) { iResourceId = id; } public String getExternalId() { return iExternalId; } public void setExternalId(String id) { iExternalId = id; } public boolean hasAbbreviation() { return iAbbreviation != null && !iAbbreviation.isEmpty(); } public String getAbbreviation() { return iAbbreviation; } public void setAbbreviation(String abbv) { iAbbreviation = abbv; } public String getName() { return iResourceName; } public void setName(String name) { iResourceName = name; } public Long getSessionId() { return iSessionId; } public void setSessionId(Long sessionId) { iSessionId = sessionId; } public String getSessionName() { return iSessionName; } public void setSessionName(String sessionName) { iSessionName = sessionName; } public String getSessionAbbv() { return iSessionAbbv; } public void setSessionAbbv(String sessionAbbv) { iSessionAbbv = sessionAbbv; } public boolean hasCalendar() { return iCalendar != null && !iCalendar.isEmpty(); } public String getCalendar() { return iCalendar; } public void setCalendar(String calendar) { iCalendar = calendar; } public boolean hasTitle() { return iTitle != null && !iTitle.isEmpty(); } public String getTitle() { return iTitle; } public void setTitle(String title) { iTitle = title; } public boolean hasWeeks() { return iWeeks != null && !iWeeks.isEmpty(); } public List<WeekInterface> getWeeks() { return iWeeks; } public void addWeek(WeekInterface week) { if (iWeeks == null) iWeeks = new ArrayList<WeekInterface>(); iWeeks.add(week); } public String toString() { return getType().getLabel() + " " + getName(); } public boolean equals(Object o) { if (o == null || !(o instanceof ResourceInterface)) return false; return ((ResourceInterface)o).getId().equals(getId()); } public int hashCode() { return getId().hashCode(); } public int compareTo(ResourceInterface r) { if (hasAbbreviation()) { int cmp = getAbbreviation().compareTo(r.getAbbreviation()); if (cmp != 0) return cmp; } int cmp = getName().compareTo(r.getName()); if (cmp != 0) return cmp; return getId().compareTo(r.getId()); } } public static class WeekInterface implements IsSerializable { private int iDayOfYear; private List<String> iDayNames = new ArrayList<String>(); public WeekInterface() {} public int getDayOfYear() { return iDayOfYear; } public void setDayOfYear(int dayOfYear) { iDayOfYear = dayOfYear; } public void addDayName(String name) { iDayNames.add(name); } public List<String> getDayNames() { return iDayNames; } public String getName() { return getDayNames().get(0) + " - " + getDayNames().get(getDayNames().size() - 1); } } public static class MeetingInterface implements Comparable<MeetingInterface>, IsSerializable { private ResourceInterface iLocation; private Long iMeetingId; private String iMeetingTime; private String iMeetingDate; private int iStartSlot; private int iEndSlot; private int iDayOfWeek; private int iDayOfYear; private boolean iPast; private String iApprovalDate = null; private Long iStartTime, iStopTime; public MeetingInterface() {} public Long getId() { return iMeetingId; } public void setId(Long id) { iMeetingId = id; } public String getMeetingDate() { return iMeetingDate; } public void setMeetingDate(String date) { iMeetingDate = date; } public int getStartSlot() { return iStartSlot; } public void setStartSlot(int slot) { iStartSlot = slot; } public int getEndSlot() { return iEndSlot; } public void setEndSlot(int slot) { iEndSlot = slot; } public int getDayOfWeek() { return iDayOfWeek; } public void setDayOfWeek(int dayOfWeek) { iDayOfWeek = dayOfWeek; } public int getDayOfYear() { return iDayOfYear; } public void setDayOfYear(int dayOfYear) { iDayOfYear = dayOfYear; } public String getMeetingTime() { return iMeetingTime; } public void setMeetingTime(String time) { iMeetingTime = time; } public ResourceInterface getLocation() { return iLocation; } public String getLocationName() { return (iLocation == null ? "" : iLocation.getName()); } public void setLocation(ResourceInterface resource) { iLocation = resource; } public boolean isPast() { return iPast; } public void setPast(boolean past) { iPast = past; } public boolean isApproved() { return iApprovalDate != null; } public String getApprovalDate() { return iApprovalDate; } public void setApprovalDate(String date) { iApprovalDate = date; } public Long getStopTime() { return iStopTime; } public void setStopTime(Long stopTime) { iStopTime = stopTime; } public Long getStartTime() { return iStartTime; } public void setStartTime(Long startTime) { iStartTime = startTime; } public int compareTo(MeetingInterface meeting) { int cmp = new Integer(getDayOfYear()).compareTo(meeting.getDayOfYear()); if (cmp != 0) return cmp; cmp = getLocationName().compareTo(meeting.getLocationName()); if (cmp != 0) return cmp; return getId().compareTo(meeting.getId()); } public int hashCode() { return getId().hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof MeetingInterface)) return false; return getId().equals(((MeetingInterface)o).getId()); } } public static boolean equals(Object o1, Object o2) { return (o1 == null ? o2 == null : o1.equals(o2)); } public static class MultiMeetingInterface implements Comparable<MultiMeetingInterface>, IsSerializable { private TreeSet<MeetingInterface> iMeetings; private boolean iPast = false; public MultiMeetingInterface(TreeSet<MeetingInterface> meetings, boolean past) { iMeetings = meetings; iPast = past; } public boolean isPast() { return iPast; } public TreeSet<MeetingInterface> getMeetings() { return iMeetings; } public int compareTo(MultiMeetingInterface m) { return getMeetings().first().compareTo(m.getMeetings().first()); } public String getDays() { return getDays(new String[] {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}, new String[] {"M", "T", "W", "Th", "F", "S", "Su"}); } public String getDays(String[] dayNames, String[] shortDyNames) { int nrDays = 0; int dayCode = 0; for (MeetingInterface meeting : getMeetings()) { int dc = (1 << meeting.getDayOfWeek()); if ((dayCode & dc)==0) nrDays++; dayCode |= dc; } String ret = ""; for (int i = 0; i < 7; i++) { if ((dayCode & (1 << i)) != 0) ret += (nrDays == 1 ? dayNames : shortDyNames)[i]; } return ret; } public String getMeetingTime() { return getDays() + " " + iMeetings.first().getMeetingTime(); } public String getMeetingDates() { if (iMeetings.size() == 1) return iMeetings.first().getMeetingDate(); return iMeetings.first().getMeetingDate() + " - " + iMeetings.last().getMeetingDate(); } public String getLocationName() { return iMeetings.first().getLocationName(); } } public static TreeSet<MultiMeetingInterface> getMultiMeetings(Collection<MeetingInterface> meetings, boolean checkApproval, boolean checkPast) { TreeSet<MultiMeetingInterface> ret = new TreeSet<MultiMeetingInterface>(); HashSet<MeetingInterface> meetingSet = new HashSet<MeetingInterface>(meetings); while (!meetingSet.isEmpty()) { MeetingInterface meeting = null; for (MeetingInterface m : meetingSet) if (meeting==null || meeting.compareTo(m) > 0) meeting = m; meetingSet.remove(meeting); HashMap<Integer,MeetingInterface> similar = new HashMap<Integer, MeetingInterface>(); TreeSet<Integer> dow = new TreeSet<Integer>(); dow.add(meeting.getDayOfWeek()); for (MeetingInterface m : meetingSet) { if (m.getMeetingTime().equals(meeting.getMeetingTime()) && m.getLocationName().equals(meeting.getLocationName()) && (!checkPast || m.isPast() == meeting.isPast()) && (!checkApproval || m.isApproved() == meeting.isApproved())) { dow.add(m.getDayOfWeek()); similar.put(m.getDayOfYear(),m); } } TreeSet<MeetingInterface> multi = new TreeSet<MeetingInterface>(); multi.add(meeting); if (!similar.isEmpty()) { int w = meeting.getDayOfWeek(); int y = meeting.getDayOfYear(); while (true) { do { y ++; w = (w + 1) % 7; } while (!dow.contains(w)); MeetingInterface m = similar.get(y); if (m == null) break; multi.add(m); meetingSet.remove(m); } } ret.add(new MultiMeetingInterface(multi, meeting.isPast())); } return ret; } } --- NEW FILE: ClassAssignmentInterface.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; import java.util.ArrayList; import com.google.gwt.user.client.rpc.IsSerializable; /** * @author Tomas Muller */ public class ClassAssignmentInterface implements IsSerializable { private ArrayList<CourseAssignment> iAssignments = new ArrayList<CourseAssignment>(); private ArrayList<String> iMessages = null; public ClassAssignmentInterface() {} public ArrayList<CourseAssignment> getCourseAssignments() { return iAssignments; } public void add(CourseAssignment a) { iAssignments.add(a); } public void clear() { iAssignments.clear(); if (iMessages != null) iMessages.clear(); } public void addMessage(String message) { if (iMessages == null) iMessages = new ArrayList<String>(); iMessages.add(message); } public boolean hasMessages() { return iMessages != null && !iMessages.isEmpty(); } public ArrayList<String> getMessages() { return iMessages; } public String getMessages(String delim) { String ret = ""; if (iMessages == null) return ret; for (String message: iMessages) { if (!ret.isEmpty()) ret += delim; ret += message; } return ret; } public static class CourseAssignment implements IsSerializable { private Long iCourseId = null; private boolean iAssigned = true; private String iSubject, iCourseNbr, iTitle, iNote; private boolean iHasUniqueName = true; private Integer iLimit = null, iProjected = null, iEnrollment = null, iLastLike = null; private ArrayList<String> iOverlaps = null; private boolean iNotAvailable = false; private String iInstead; private ArrayList<ClassAssignment> iAssignments = new ArrayList<ClassAssignment>(); public Long getCourseId() { return iCourseId; } public void setCourseId(Long courseId) { iCourseId = courseId; } public boolean isFreeTime() { return (iCourseId == null); } public boolean isAssigned() { return iAssigned; } public void setAssigned(boolean assigned) { iAssigned = assigned; } public String getSubject() { return iSubject; } public void setSubject(String subject) { iSubject = subject; } public String getCourseNbr() { return iCourseNbr; } public void setCourseNbr(String courseNbr) { iCourseNbr = courseNbr; } public String getTitle() { return iTitle; } public void setTitle(String title) { iTitle = title; } public String getNote() { return iNote; } public void setNote(String note) { iNote = note; } public boolean hasUniqueName() { return iHasUniqueName; } public void setHasUniqueName(boolean hasUniqueName) { iHasUniqueName = hasUniqueName; } public void addOverlap(String overlap) { if (iOverlaps == null) iOverlaps = new ArrayList<String>(); iOverlaps.add(overlap); } public ArrayList<String> getOverlaps() { return iOverlaps; } public boolean isNotAvailable() { return iNotAvailable; } public void setNotAvailable(boolean notAvailable) { iNotAvailable = notAvailable; } public void setInstead(String instead) { iInstead = instead; } public String getInstead() { return iInstead; } public ArrayList<ClassAssignment> getClassAssignments() { return iAssignments; } public ClassAssignment addClassAssignment() { ClassAssignment a = new ClassAssignment(this); iAssignments.add(a); return a; } public Integer getLimit() { return iLimit; } public void setLimit(Integer limit) { iLimit = limit; } public String getLimitString() { if (iLimit == null) return ""; if (iLimit < 0) return "∞"; return iLimit.toString(); } public Integer getProjected() { return iProjected; } public void setProjected(Integer projected) { iProjected = projected; } public String getProjectedString() { if (iProjected == null || iProjected == 0) return ""; if (iProjected < 0) return "∞"; return iProjected.toString(); } public Integer getLastLike() { return iLastLike; } public void setLastLike(Integer lastLike) { iLastLike = lastLike; } public String getLastLikeString() { if (iLastLike == null || iLastLike == 0) return ""; if (iLastLike < 0) return "∞"; return iLastLike.toString(); } public Integer getEnrollment() { return iEnrollment; } public void setEnrollment(Integer enrollment) { iEnrollment = enrollment; } public String getEnrollmentString() { if (iEnrollment == null || iEnrollment == 0) return ""; if (iEnrollment < 0) return "∞"; return iEnrollment.toString(); } } public static class ClassAssignment implements IsSerializable { private boolean iCourseAssigned = true; private Long iCourseId, iClassId, iSubpartId; private ArrayList<Integer> iDays = new ArrayList<Integer>(); private int iStart, iLength, iBreakTime = 0; private ArrayList<String> iInstructos = new ArrayList<String>(); private ArrayList<String> iInstructoEmails = new ArrayList<String>(); private ArrayList<String> iRooms = new ArrayList<String>(); private boolean iAlternative = false, iHasAlternatives = true, iDistanceConflict = false; private String iDatePattern = null; private String iSubject, iCourseNbr, iSubpart, iSection, iParentSection; private int[] iLimit = null; private boolean iPin = false; private int iBackToBackDistance = 0; private String iBackToBackRooms = null; private boolean iSaved = false; private Integer iExpected = null; public ClassAssignment() {} public ClassAssignment(CourseAssignment course) { iCourseId = course.getCourseId(); iSubject = course.getSubject(); iCourseNbr = course.getCourseNbr(); iCourseAssigned = course.isAssigned(); } public Long getCourseId() { return iCourseId; } public void setCourseId(Long courseId) { iCourseId = courseId; } public boolean isFreeTime() { return (iCourseId == null); } public boolean isCourseAssigned() { return iCourseAssigned; } public void setCourseAssigned(boolean courseAssigned) { iCourseAssigned = courseAssigned; } public String getSubject() { return iSubject; } public void setSubject(String subject) { iSubject = subject; } public String getCourseNbr() { return iCourseNbr; } public void setCourseNbr(String courseNbr) { iCourseNbr = courseNbr; } public String getSubpart() { return iSubpart; } public void setSubpart(String subpart) { iSubpart = subpart; } public String getSection() { return iSection; } public void setSection(String section) { iSection = section; } public String getParentSection() { return iParentSection; } public void setParentSection(String parentSection) { iParentSection = parentSection; } public boolean isAlternative() { return iAlternative; } public void setAlternative(boolean alternative) { iAlternative = alternative; } public Long getClassId() { return iClassId; } public void setClassId(Long classId) { iClassId = classId; } public Long getSubpartId() { return iSubpartId; } public void setSubpartId(Long subpartId) { iSubpartId = subpartId; } public void addDay(int day) { if (iDays == null) iDays = new ArrayList<Integer>(); iDays.add(day); } public ArrayList<Integer> getDays() { return iDays; } public String getDaysString(String[] shortDays) { if (iDays == null) return ""; String ret = ""; for (int day: iDays) ret += shortDays[day]; return ret; } public boolean isAssigned() { return iDays != null && !iDays.isEmpty(); } public int getStart() { return iStart; } public void setStart(int start) { iStart = start; } public String getStartString() { if (!isAssigned()) return ""; int h = iStart / 12; int m = 5 * (iStart % 12); return (h > 12 ? h - 12 : h) + ":" + (m < 10 ? "0" : "") + m + (h == 24 ? "a" : h >= 12 ? "p" : "a"); } public int getLength() { return iLength; } public void setLength(int length) { iLength = length; } public String getEndString() { if (!isAssigned()) return ""; int h = (5 * (iStart + iLength) - iBreakTime) / 60; int m = (5 * (iStart + iLength) - iBreakTime) % 60; return (h > 12 ? h - 12 : h) + ":" + (m < 10 ? "0" : "") + m + (h == 24 ? "a" : h >= 12 ? "p" : "a"); } public String getTimeString(String[] shortDays) { if (!isAssigned()) return ""; return getDaysString(shortDays) + " " + getStartString() + " - " + getEndString(); } public int getBreakTime() { return iBreakTime; } public void setBreakTime(int breakTime) { iBreakTime = breakTime; } public boolean hasDatePattern() { return iDatePattern != null && !iDatePattern.isEmpty(); } public String getDatePattern() { return iDatePattern; } public void setDatePattern(String datePattern) { iDatePattern = datePattern; } public boolean hasInstructors() { return iInstructos != null && !iInstructos.isEmpty(); } public void addInstructor(String instructor) { if (iInstructos == null) iInstructos = new ArrayList<String>(); iInstructos.add(instructor); } public ArrayList<String> getInstructors() { return iInstructos; } public String getInstructors(String delim) { if (iInstructos == null) return ""; String ret = ""; for (String instructor: iInstructos) { if (!ret.isEmpty()) ret += delim; ret += instructor; } return ret; } public String getInstructorWithEmails(String delim) { if (iInstructos == null) return ""; String ret = ""; for (int i = 0; i < iInstructos.size(); i++) { if (!ret.isEmpty()) ret += delim; String email = (iInstructoEmails != null && i < iInstructoEmails.size() ? iInstructoEmails.get(i) : null); if (email != null && !email.isEmpty()) { ret += "<A class=\"unitime-SimpleLink\" href=\"mailto:" + email + "\">" + iInstructos.get(i) + "</A>"; } else ret += iInstructos.get(i); } return ret; } public boolean hasInstructorEmails() { return iInstructoEmails != null && !iInstructoEmails.isEmpty(); } public void addInstructoEmailr(String instructorEmail) { if (iInstructoEmails == null) iInstructoEmails = new ArrayList<String>(); iInstructoEmails.add(instructorEmail); } public ArrayList<String> getInstructorEmails() { return iInstructoEmails; } public boolean hasRoom() { return iRooms != null && !iRooms.isEmpty(); } public void addRoom(String room) { if (iRooms == null) iRooms = new ArrayList<String>(); iRooms.add(room); } public ArrayList<String> getRooms() { return iRooms; } public String getRooms(String delim) { if (iRooms == null) return ""; String ret = ""; for (String room: iRooms) { if (!ret.isEmpty()) ret += delim; ret += room; } return ret; } public boolean isUnlimited() { return iLimit != null && iLimit[1] >= 9999; } public int[] getLimit() { return iLimit; } public void setLimit(int[] limit) { iLimit = limit; } public String getLimitString() { if (iLimit == null) return ""; if (iLimit[1] >= 9999 || iLimit[1] < 0) return "∞"; if (iLimit[0] < 0) return String.valueOf(iLimit[1]); return (iLimit[1] - iLimit[0]) + " / " + iLimit[1]; } public boolean isAvailable() { if (iLimit == null) return true; if (iLimit[0] < 0) return (iLimit[1] == 0); return iLimit[0] < iLimit[1]; } public int getAvailableLimit() { if (iLimit == null) return 9999; if (iLimit[0] < 0) return 9999; return iLimit[1] - iLimit[0]; } public boolean isPinned() { return iPin; } public void setPinned(boolean pin) { iPin = pin; } public boolean hasAlternatives() { return iHasAlternatives; } public void setHasAlternatives(boolean alternatives) { iHasAlternatives = alternatives; } public boolean hasDistanceConflict() { return iDistanceConflict; } public void setDistanceConflict(boolean distanceConflict) { iDistanceConflict = distanceConflict; } public int getBackToBackDistance() { return iBackToBackDistance; } public void setBackToBackDistance(int backToBackDistance) { iBackToBackDistance = backToBackDistance; } public String getBackToBackRooms() { return iBackToBackRooms; } public void setBackToBackRooms(String backToBackRooms) { iBackToBackRooms = backToBackRooms; } public boolean isSaved() { return iSaved; } public void setSaved(boolean saved) { iSaved = saved; } public void setExpected(int expected) { iExpected = expected; } public void setExpected(double expected) { iExpected = (int)Math.ceil(expected); } public boolean hasExpected() { return iExpected != null; } public int getExpected() { return (iExpected == null ? 0 : iExpected); } public boolean isOfHighDemand() { return isAvailable() && !isUnlimited() && hasExpected() && getExpected() > getAvailableLimit(); } } } --- NEW FILE: MenuException.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; /** * @author Tomas Muller */ public class MenuException extends RuntimeException { private static final long serialVersionUID = -2768727468340429993L; public MenuException() { super(); } public MenuException(String message) { super(message); } } --- NEW FILE: CurriculaException.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; /** * @author Tomas Muller */ public class CurriculaException extends RuntimeException { private static final long serialVersionUID = 2144948330211931475L; public CurriculaException() { super(); } public CurriculaException(String message) { super(message); } } --- NEW FILE: SectioningException.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; /** * @author Tomas Muller */ public class SectioningException extends RuntimeException { private static final long serialVersionUID = 1L; private SectioningExceptionType iType = SectioningExceptionType.UNKNOWN; private String iProblem = "N/A"; public SectioningException() { super(); } public SectioningException(SectioningExceptionType type, String problem, Throwable cause) { super(cause); if (type != null) iType = type; if (problem != null) iProblem = problem; } public SectioningException(SectioningExceptionType type, String problem) { this(type, problem, null); } public SectioningException(SectioningExceptionType type, Throwable cause) { this(type, cause.getMessage(), cause); } public SectioningException(SectioningExceptionType type) { this(type, null, null); } public String getProblem() { return iProblem; } public SectioningExceptionType getType() { return iType; } public String getMessage() { return iType.message(iProblem); } } --- NEW FILE: LookupException.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; /** * @author Tomas Muller */ public class LookupException extends RuntimeException { private static final long serialVersionUID = -1612532554365430022L; public LookupException() { super(); } public LookupException(String message) { super(message); } } --- NEW FILE: CurriculumInterface.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.shared; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import com.google.gwt.user.client.rpc.IsSerializable; /** * @author Tomas Muller */ public class CurriculumInterface implements IsSerializable, Comparable<CurriculumInterface> { private Long iId; private String iAbbv, iName; private boolean iEditable = false; private String iLastChange = null; private AcademicAreaInterface iAcademicArea; private TreeSet<MajorInterface> iMajors; private DepartmentInterface iDept; private TreeSet<CurriculumClassificationInterface> iClasf; private TreeSet<CourseInterface> iCourses; public CurriculumInterface() {} public Long getId() { return iId; } public void setId(Long id) { iId = id; } public String getName() { return iName; } public void setName(String name) { iName = name; } public String getAbbv() { return iAbbv; } public void setAbbv(String abbv) { iAbbv = abbv; } public String getLastChange() { return iLastChange; } public void setLastChange(String lastChange) { iLastChange = lastChange; } public boolean hasLastChange() { return iLastChange != null && !iLastChange.isEmpty(); } public AcademicAreaInterface getAcademicArea() { return iAcademicArea; } public void setAcademicArea(AcademicAreaInterface area) { iAcademicArea = area; } public TreeSet<MajorInterface> getMajors() { return iMajors; } public boolean hasMajors() { return iMajors != null && !iMajors.isEmpty(); } public void addMajor(MajorInterface major) { if (iMajors == null) iMajors = new TreeSet<MajorInterface>(); iMajors.add(major); } public String getMajorNames(String delim) { String ret = ""; if (iMajors == null) return ret; for (MajorInterface major: iMajors) { if (!ret.isEmpty()) ret += delim; ret += major.getName(); } return ret; } public String getMajorCodes(String delim) { String ret = ""; if (iMajors == null) return ret; for (MajorInterface major: iMajors) { if (!ret.isEmpty()) ret += delim; ret += major.getCode(); } return ret; } public String getCodeMajorNames(String delim) { String ret = ""; if (iMajors == null) return ret; for (MajorInterface major: iMajors) { if (!ret.isEmpty()) ret += delim; ret += major.getCode() + " - " + major.getName(); } return ret; } public DepartmentInterface getDepartment() { return iDept; } public void setDepartment(DepartmentInterface dept) { iDept = dept; } public TreeSet<CurriculumClassificationInterface> getClassifications() { return iClasf; } public boolean hasClassifications() { return iClasf != null; } public void addClassification(CurriculumClassificationInterface clasf) { if (iClasf == null) iClasf = new TreeSet<CurriculumClassificationInterface>(); iClasf.add(clasf); } public TreeSet<CourseInterface> getCourses() { return iCourses; } public boolean hasCourses() { return iCourses != null && !iCourses.isEmpty(); } public void addCourse(CourseInterface course) { if (iCourses == null) iCourses = new TreeSet<CourseInterface>(); iCourses.add(course); } public Integer getExpected() { if (!hasClassifications()) return null; int ret = 0; for (CurriculumClassificationInterface c: getClassifications()) ret += (c.getExpected() == null ? 0 : c.getExpected()); return ret; } public Integer getEnrollment() { if (!hasClassifications()) return null; int ret = 0; for (CurriculumClassificationInterface c: getClassifications()) ret += (c.getEnrollment() == null ? 0 : c.getEnrollment()); return ret; } public Integer getLastLike() { if (!hasClassifications()) return null; int ret = 0; for (CurriculumClassificationInterface c: getClassifications()) ret += (c.getLastLike() == null ? 0 : c.getLastLike()); return ret; } public Integer getProjection() { if (!hasClassifications()) return null; int ret = 0; for (CurriculumClassificationInterface c: getClassifications()) ret += (c.getProjection() == null ? 0 : c.getProjection()); return ret; } public String getExpectedString() { if (!hasClassifications()) return "?"; Integer count = getExpected(); return (count == null ? "N/A" : count.toString()); } public String getLastLikeString() { if (!hasClassifications()) return "?"; Integer count = getLastLike(); return (count == null ? "N/A" : count.toString()); } public String getProjectionString() { if (!hasClassifications()) return "?"; Integer count = getProjection(); return (count == null ? "N/A" : count.toString()); } public String getEnrollmentString() { if (!hasClassifications()) return "?"; Integer count = getEnrollment(); return (count == null ? "N/A" : count.toString()); } public void setEditable(boolean editable) { iEditable = editable; } public boolean isEditable() { return iEditable; } public boolean equals(Object o) { if (o == null || !(o instanceof CurriculumInterface)) return false; return getId().equals(((CurriculumInterface)o).getId()); } public int hashCode() { return getId().hashCode(); } public int compareTo(CurriculumInterface curriculum) { int cmp = getAbbv().compareTo(curriculum.getAbbv()); if (cmp != 0) return cmp; return getId().compareTo(curriculum.getId()); } public static class AcademicAreaInterface implements IsSerializable, Comparable<AcademicAreaInterface> { private Long iAreaId; private String iAreaAbbv, iAreaName; public AcademicAreaInterface() {} public Long getId() { return iAreaId; } public void setId(Long id) { iAreaId = id; } public String getAbbv() { return iAreaAbbv; } public void setAbbv(String abbv) { iAreaAbbv = abbv; } public String getName() { return iAreaName; } public void setName(String name) { iAreaName = name; } public boolean equals(Object o) { if (o == null || !(o instanceof AcademicAreaInterface)) return false; return getId().equals(((AcademicAreaInterface)o).getId()); } public int hashCode() { return getId().hashCode(); } public int compareTo(AcademicAreaInterface area) { int cmp = getAbbv().compareTo(area.getAbbv()); if (cmp != 0) return cmp; return getId().compareTo(area.getId()); } } public static class MajorInterface implements IsSerializable, Comparable<MajorInterface> { private Long iMajorId; private String iMajorCode, iMajorName; public MajorInterface() {} public Long getId() { return iMajorId; } public void setId(Long id) { iMajorId = id; } public String getCode() { return iMajorCode; } public void setCode(String code) { iMajorCode = code; } public String getName() { return iMajorName; } public void setName(String name) { iMajorName = name; } public boolean equals(Object o) { if (o == null || !(o instanceof MajorInterface)) return false; return getId().equals(((MajorInterface)o).getId()); } public int hashCode() { return getId().hashCode(); } public int compareTo(MajorInterface major) { if (getCode() != null) { int cmp = getCode().compareTo(major.getCode()); if (cmp != 0) return cmp; } return getId().compareTo(major.getId()); } } public static class DepartmentInterface implements IsSerializable, Comparable<DepartmentInterface> { private Long iDeptId; private String iDeptCode, iDeptAbbv, iDeptName; public DepartmentInterface() {} public Long getId() { return iDeptId; } public void setId(Long id) { iDeptId = id; } public String getCode() { return iDeptCode; } public void setCode(String code) { iDeptCode = code; } public String getAbbv() { return iDeptAbbv; } public void setAbbv(String abbv) { iDeptAbbv = abbv; } public String getName() { return iDeptName; } public void setName(String name) { iDeptName = name; } public String getLabel() { return iDeptCode + " - " + iDeptName; } public boolean equals(Object o) { if (o == null || !(o instanceof DepartmentInterface)) return false; return getId().equals(((DepartmentInterface)o).getId()); } public int hashCode() { return getId().hashCode(); } public int compareTo(DepartmentInterface dept) { int cmp = getLabel().compareTo(dept.getLabel()); if (cmp != 0) return cmp; return getId().compareTo(dept.getId()); } } public static class AcademicClassificationInterface implements IsSerializable, Comparable<AcademicClassificationInterface> { private Long iClasfId; private String iClasfCode, iClasfName; public AcademicClassificationInterface() {} public Long getId() { return iClasfId; } public void setId(Long id) { iClasfId = id; } public String getCode() { return iClasfCode; } public void setCode(String code) { iClasfCode = code; } public String getName() { return iClasfName; } public void setName(String name) { iClasfName = name; } public boolean equals(Object o) { if (o == null || !(o instanceof AcademicClassificationInterface)) return false; return getId().equals(((AcademicClassificationInterface)o).getId()); } public int hashCode() { return getId().hashCode(); } public int compareTo(AcademicClassificationInterface clasf) { int cmp = getCode().compareTo(clasf.getCode()); if (cmp != 0) return cmp; cmp = getName().compareTo(clasf.getName()); if (cmp != 0) return cmp; return getId().compareTo(clasf.getId()); } } public static class CurriculumClassificationInterface implements IsSerializable, Comparable<CurriculumClassificationInterface> { private Long iCurriculumId, iClasfId; private String iName; private Integer iNrStudents = null, iEnrollment = null, iLastLike = null, iProjection = null; private AcademicClassificationInterface iClasf; private TreeSet<CurriculumCourseInterface> iCourses = null; public CurriculumClassificationInterface() {} public Long getId() { return iClasfId; } public void setId(Long id) { iClasfId = id; } public Long getCurriculumId() { return iCurriculumId; } public void setCurriculumId(Long curriculumId) { iCurriculumId = curriculumId; } public String getName() { return iName; } public void setName(String name) { iName = name; } public Integer getExpected() { return iNrStudents; } public void setExpected(Integer nrStudents) { iNrStudents = nrStudents; } public Integer getEnrollment() { return iEnrollment; } public void setEnrollment(Integer enrollment) { iEnrollment = enrollment; } public Integer getLastLike() { return iLastLike; } public void setLastLike(Integer lastLike) { iLastLike = lastLike; } public Integer getProjection() { return iProjection; } public void setProjection(Integer projection) { iProjection = projection; } public AcademicClassificationInterface getAcademicClassification() { return iClasf; } public void setAcademicClassification(AcademicClassificationInterface clasf) { iClasf = clasf; } public TreeSet<CurriculumCourseInterface> getCourses() { return iCourses; } public boolean hasCourses() { return iCourses != null && !iCourses.isEmpty(); } public void addCourse(CurriculumCourseInterface course) { if (iCourses == null) iCourses = new TreeSet<CurriculumCourseInterface>(); iCourses.add(course); } public boolean equals(Object o) { if (o == null || !(o instanceof CurriculumClassificationInterface)) return false; return getId().equals(((CurriculumClassificationInterface)o).getId()); } public int hashCode() { return getId().hashCode(); } public int compareTo(CurriculumClassificationInterface clasf) { int cmp = getAcademicClassification().compareTo(clasf.getAcademicClassification()); if (cmp != 0) return cmp; return getId().compareTo(clasf.getId()); } } public static class CourseInterface implements IsSerializable, Comparable<CourseInterface> { private Long iCourseId; private String iCourseName; private List<CurriculumCourseInterface> iCurriculumCourses; private TreeSet<CurriculumCourseGroupInterface> iGroups; public CourseInterface() {} public Long getId() { return iCourseId; } public void setId(Long id) { iCourseId = id; } public String getCourseName() { return iCourseName; } public void setCourseName(String courseName) { iCourseName = courseName; } public boolean hasCurriculumCourses() { return iCurriculumCourses != null && !iCurriculumCourses.isEmpty(); } public void setCurriculumCourse(int idx, CurriculumCourseInterface course) { if (iCurriculumCourses == null) iCurriculumCourses = new ArrayList<CurriculumCourseInterface>(); if (idx < iCurriculumCourses.size()) { iCurriculumCourses.set(idx, course); } else { while (iCurriculumCourses.size()<idx) iCurriculumCourses.add(null); iCurriculumCourses.add(course); } } public CurriculumCourseInterface getCurriculumCourse(int idx) { if (iCurriculumCourses == null || idx >= iCurriculumCourses.size()) return null; return iCurriculumCourses.get(idx); } public List<CurriculumCourseInterface> getCurriculumCourses() { return iCurriculumCourses; } public boolean equals(Object o) { if (o == null || !(o instanceof CourseInterface)) return false; return getId().equals(((CourseInterface)o).getId()); } public boolean hasGroups() { return iGroups != null && !iGroups.isEmpty(); } public void addGroup(CurriculumCourseGroupInterface group) { if (iGroups == null) iGroups = new TreeSet<CurriculumCourseGroupInterface>(); iGroups.add(group); } public TreeSet<CurriculumCourseGroupInterface> getGroups() { return iGroups; } public int hashCode() { return getId().hashCode(); } private int firstClassification() { if (!hasCurriculumCourses()) return -1; for (int i = 0; i < iCurriculumCourses.size(); i++) { CurriculumCourseInterface c = iCurriculumCourses.get(i); if (c == null) continue; if (c.getShare() > 0.0f) return i; } return iCurriculumCourses.size(); } private int highestClassification() { if (!hasCurriculumCourses()) return -1; int best = iCurriculumCourses.size(); double bestShare = -1.0f; for (int i = 0; i < iCurriculumCourses.size(); i++) { CurriculumCourseInterface c = iCurriculumCourses.get(i); if (c == null) continue; if (c.getShare() > bestShare) { bestShare = c.getShare(); best = i; } } return best; } public int compareTo(CourseInterface course) { if (hasCurriculumCourses()) { int a = highestClassification(); int b = course.highestClassification(); if (a < b) return -1; if (a > b) return 1; if (a <= iCurriculumCourses.size()) { CurriculumCourseInterface c = getCurriculumCourse(a); CurriculumCourseInterface d = course.getCurriculumCourse(a); int cmp = Double.compare(d == null ? 0f : d.getShare(), c == null ? 0f : c.getShare()); if (cmp != 0) return cmp; } a = firstClassification(); b = course.firstClassification(); if (a < b) return -1; if (a > b) return 1; while (a <= iCurriculumCourses.size()) { CurriculumCourseInterface c = getCurriculumCourse(a); CurriculumCourseInterface d = course.getCurriculumCourse(a); int cmp = Double.compare(d == null ? 0f : d.getShare(), c == null ? 0f : c.getShare()); if (cmp != 0) return cmp; a++; } } int cmp = getCourseName().compareTo(course.ge... [truncated message content] |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:10:58
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/resources In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/resources Added Files: StudentSectioningResources.java StudentSectioningMessages.properties StudentSectioningMessages.java GwtResources.java StudentSectioningConstants.java StudentSectioningExceptions.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: StudentSectioningMessages.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.resources; import com.google.gwt.i18n.client.Messages; /** * @author Tomas Muller */ public interface StudentSectioningMessages extends Messages { /* Common column names */ @DefaultMessage("Lock") String colLock(); @DefaultMessage("Subject") String colSubject(); @DefaultMessage("Course") String colCourse(); @DefaultMessage("Type") String colSubpart(); @DefaultMessage("Class") String colClass(); @DefaultMessage("Avail") String colLimit(); @DefaultMessage("Days") String colDays(); @DefaultMessage("Time") String colTime(); @DefaultMessage("Start") String colStart(); @DefaultMessage("End") String colEnd(); @DefaultMessage("Date") String colDate(); @DefaultMessage("Room") String colRoom(); @DefaultMessage("Instructor") String colInstructor(); @DefaultMessage("Requires") String colParent(); @DefaultMessage(" ") String colSaved(); @DefaultMessage(" ") String colHighDemand(); @DefaultMessage("Title") String colTitle(); @DefaultMessage("Note") String colNote(); @DefaultMessage("Year") String colYear(); @DefaultMessage("Term") String colTerm(); @DefaultMessage("Campus") String colCampus(); /* Academic Session Selector messages */ @DefaultMessage("No academic session is selected.") String sessionSelectorNoSession(); @DefaultMessage("Click here to change the session.") String sessionSelectorHint(); @DefaultMessage("Select Academic Session ...") String sessionSelectorSelect(); @DefaultMessage("Loading academic sessions ...") String sessionSelectorLoading(); @DefaultMessage("Session: {1} {0} ({2})") String sessionSelectorLabel(String year, String term, String campus); @DefaultMessage("{1} {0} ({2})") String sessionName(String year, String term, String campus); /* Course Requests Table messages */ @DefaultMessage("Scheduling") String courseRequestsScheduling(); @DefaultMessage("Validation failed, see above for errors.") String validationFailed(); @DefaultMessage("Course {0} used multiple times.") String validationMultiple(String course); @DefaultMessage("No course provided.") String validationNoCourse(); @DefaultMessage("No alternative for a free time.") String validationFreeTimeWithAlt(); @DefaultMessage("No free time alternative.") String validationAltFreeTime(); @DefaultMessage("No first alternative provided.") String validationSecondAltWithoutFirst(); @DefaultMessage("Course {0} does not exist.") String validationCourseNotExists(String course); @DefaultMessage("Course does not exist.") String validationUnknownCourseNotExists(); @DefaultMessage("Courses") String courseRequestsCourses(); @DefaultMessage("{0}. Priority") String courseRequestsPriority(int i); @DefaultMessage("Alternatives") String courseRequestsAlternatives(); @DefaultMessage("{0}. Alternative") String courseRequestsAlternative(int i); @DefaultMessage("Alternative to {0}") String courseRequestsHintAlt(String course); @DefaultMessage("Alt. to {0} & {1}") String courseRequestsHintAlt2(String course, String altCourse); @DefaultMessage("Course with the second highest priority.") String courseRequestsHint1(); @DefaultMessage("Enter a course name, e.g., ENG 10600") String courseRequestsHint3(); @DefaultMessage("or a free time, e.g., Free MWF 7:30 - 8:30") String courseRequestsHint4(); @DefaultMessage("Course with the lowest priority.") String courseRequestsHint8(); @DefaultMessage("Alternative(s) to all the courses above.") String courseRequestsHintA0(); /* Course Selection Box messages */ @DefaultMessage("Course Finder") String courseSelectionDialog(); @DefaultMessage("No course selected.") String courseSelectionNoCourseSelected(); @DefaultMessage("<u>D</u>etails") String courseSelectionDetails(); @DefaultMessage("<u>L</u>ist of classes") String courseSelectionClasses(); @DefaultMessage("<u>C</u>ourses") String courseSelectionCourses(); @DefaultMessage("Free <u>T</u>ime") String courseSelectionFreeTime(); @DefaultMessage("{0} {1}") String courseName(String subject, String courseNbr); @DefaultMessage("{0} {1} - {2}") String courseNameWithTitle(String subject, String courseNbr, String title); @DefaultMessage("No course filter set.") String courseSelectionNoCourseFilter(); @DefaultMessage("Looking for courses ...") String courseSelectionLoadingCourses(); @DefaultMessage("Course {0} has no classes.") String courseSelectionNoClasses(String course); @DefaultMessage("Loading classes ...") String courseSelectionLoadingClasses(); @DefaultMessage("Loading course details ...") String courseSelectionLoadingDetails(); @DefaultMessage("Invalid free time.") String invalidFreeTime(); @DefaultMessage("No free time entered.") String courseSelectionNoFreeTime(); @DefaultMessage("Unable to interpret {0} as free time (error at position {1}).") String invalidFreeTimeGeneric(String text, int pos); @DefaultMessage("Unable to interpret {0} as free time (expected a day or a number at position {1}).") String invalidFreeTimeExpectedDayOrNumber(String text, int pos); @DefaultMessage("Unable to interpret {0} as free time (expected a number at position {1}).") String invalidFreeTimeExpectedNumber(String text, int pos); @DefaultMessage("Unable to interpret {0} as free time (start time before {1}).") String invalidFreeTimeStartBeforeFirst(String text, String first); @DefaultMessage("Unable to interpret {0} as free time (start time after {1}).") String invalidFreeTimeStartAfterLast(String text, String last); @DefaultMessage("Unable to interpret {0} as free time (end time before {1}).") String invalidFreeTimeEndBeforeFirst(String text, String first); @DefaultMessage("Unable to interpret {0} as free time (end time after {1}).") String invalidFreeTimeEndAfterLast(String text, String last); @DefaultMessage("Unable to interpret {0} as free time (start time is not before end time).") String invalidFreeTimeStartNotBeforeEnd(String text); @DefaultMessage("Unable to interpret {0} as free time (invalid start time).") String invalidFreeTimeInvalidStartTime(String text); @DefaultMessage("Unable to interpret {0} as free time (invalid end time).") String invalidFreeTimeInvalidEndTime(String text); /* Suggestion Box messages */ @DefaultMessage("Waiting for alternatives ...") String suggestionsLoading(); @DefaultMessage("Alternatives for {0}") String suggestionsAlternatives(String source); @DefaultMessage("There are no alternatives for {0}.") String suggestionsNoAlternative(String source); @DefaultMessage("Free Time {0} {1} - {2}") String freeTime(String days, String start, String end); @DefaultMessage("{0} {1}") String course(String subject, String course); @DefaultMessage("{0} {1} {2} {3}") String clazz(String subject, String course, String subpart, String section); /* Time Grid messages */ @DefaultMessage("Send {0} an email.") String sendEmail(String name); @DefaultMessage("(~{0} min)") String distanceConflict(int distanceInMinutes); /* Student Sectioning widget messags */ @DefaultMessage("<u>P</u>revious") String buttonPrev(); @DefaultMessage("<u>N</u>ext") String buttonNext(); @DefaultMessage("<u>E</u>nroll") String buttonEnroll(); @DefaultMessage("P<u>r</u>int") String buttonPrint(); @DefaultMessage("E<u>x</u>port") String buttonExport(); @DefaultMessage("<u>S</u>ave") String buttonSave(); @DefaultMessage("<u>L</u>ist of Classes") String tabClasses(); @DefaultMessage("<u>T</u>imetable") String tabTimetable(); @DefaultMessage("Requests stored.") String saveRequestsOK(); @DefaultMessage("Unable to store requests: {0}") String saveRequestsFail(String reason); @DefaultMessage("Success!") String enrollOK(); @DefaultMessage("Enrollment failed: {0}") String enrollFailed(String reason); @DefaultMessage("Student Schedule") String studentSchedule(); @DefaultMessage("Preliminary Student Schedule") String studentScheduleNotEnrolled(); @DefaultMessage("Free") String freeTimeSubject(); @DefaultMessage("Time") String freeTimeCourse(); @DefaultMessage("Computed schedule is empty.") String noSchedule(); /* User Authentication messages */ @DefaultMessage("User: Not authenticated") String userNotAuthenticated(); @DefaultMessage("Click here to authenticate.") String userHint(); @DefaultMessage("Click here to log in.") String userHintLogin(); @DefaultMessage("Click here to log out.") String userHintLogout(); @DefaultMessage("You can close the window now.") String userHintClose(); @DefaultMessage("Please Log In ...") String dialogAuthenticate(); @DefaultMessage("Username:") String username(); @DefaultMessage("Password:") String password(); @DefaultMessage("Log In") String buttonUserLogin(); @DefaultMessage("Guest") String buttonUserSkip(); @DefaultMessage("Lookup") String buttonUserLookup(); @DefaultMessage("Guest") String userGuest(); @DefaultMessage("User: {0}") String userLabel(String user); /* Validation Error messages */ @DefaultMessage("Please wait ...") String pleaseWait(); /* Web Table messages */ @DefaultMessage("No data.") String tableEmpty(); /* Interface messages */ @DefaultMessage("Distance to travel from {0} is approx. {1} minutes.") String backToBackDistance(String rooms, int distanceInMinutes); @DefaultMessage("∞") String unlimited(); @DefaultMessage("Not available.") String classNotAvailable(); @DefaultMessage("Conflicts with ") String conflictWith(); @DefaultMessage("or ") String conflictWithOr(); @DefaultMessage(", assigned {0} instead") String conflictAssignedAlternative(String alt); @DefaultMessage("Failed to load the application ({0}).") String failedToLoadTheApp(String message); @DefaultMessage("Expected {0} students, but only {1} spaces are available, please try to avoid this class.") String highDemand(int expected, int available); } --- NEW FILE: StudentSectioningConstants.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.resources; import com.google.gwt.i18n.client.Constants; /** * @author Tomas Muller */ public interface StudentSectioningConstants extends Constants { @DefaultStringArrayValue({ "Tip: Use Ctrl+1 (or Ctrl+Alt+1) to navigate to the first course, Ctrl+2 to the second, Ctrl+A to the first alternative, Ctr+B to the second alternative, etc.", "Tip: Use Ctrl+Arrow to navigate, Ctrl+Shift+Up and Ctrl+Shith+Down to move a line around.", "Tip: Use Ctrl+F to open the Course Finder dialog.", "Tip: Use Ctrl+N (or Ctrl+Alt+N in some browsers) to validate the screen and go next.", "Tip: Start entering the name (e.g., ENGL 10600) of the course or a part of its title (e.g., History) to see suggestions.", "Tip: The Alternatives below are here to ensure that you get a desired number of courses even when a course (and its alternatives) are not available.", "Tip: Enter a free time to aviod getting classes in time you need for something else.", "Tip: All courses above a free time should not overlap with the free time (you will get the course even when the only possibility is to break the free time).", "Tip: All courses below a free time can not overlap with the free time (you will only get the course if there are sections that do not break the free time).", "Tip: Clik this tip to see another tip.", "Tip: There are no alternative free times.", "Tip: Try not to break too many standard time patterns with a free time (see the numbers in the Course Finder dialog).", "Tip: Use Esc to hide suggestions, Ctrl+S to show suggestions." }) String[] tips(); @DefaultStringArrayValue({ "Tip: Use Up and Down to navigate through courses, Enter to select one.", "Tip: Start entering the name of a course (e.g., ENGL 10600) or a part of its title (e.g., History) to see suggestions.", "Tip: Click on a course to see its details.", "Tip: Doubleclik on a course to select it.", "Tip: Press Esc to close the dialog, Enter to select the inputed text or the selected course."}) String[] courseTips(); @DefaultStringArrayValue({ "Tip: Enter a free time (e.g., Monday 8am - 10am) or use the mouse to select it.", "Tip: The numbers in the selected times counts the number of overlapping standard time patterns (3x50, 2x75, 1x150), try to avoid overlapping too many of those."}) String[] freeTimeTips(); @DefaultStringValue("Free ") String freePrefix(); @DefaultStringArrayValue({ "7:30a", "8:00a", "8:30a", "9:00a", "9:30a", "10:00a", "10:30a", "11:00a", "11:30a", "12:00p", "12:30p", "1:00p", "1:30p", "2:00p", "2:30p", "3:00p", "3:30p", "4:00p", "4:30p", "5:00p", "5:30p", "6:00p", "6:30p", "7:00p", "7:30p" }) String[] freeTimePeriods(); @DefaultStringArrayValue({"Mon", "Tue", "Wed", "Thu", "Fri"}) String[] freeTimeDays(); @DefaultStringArrayValue({"M", "T", "W", "R", "F"}) String[] freeTimeShortDays(); @DefaultStringArrayValue({"Monday", "Tuesday", "Wednesday", "Thursday", "Friday"}) String[] freeTimeLongDays(); @DefaultStringArrayValue({"0", "2", "6", "8", "12", "14", "15", "16", "17", "18", "19", "20"}) String[] freeTimeOneDay150(); @DefaultStringArrayValue({"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}) String[] longDays(); @DefaultStringArrayValue({"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}) String[] days(); @DefaultStringArrayValue({"M", "T", "W", "R", "F", "S", "U"}) String[] shortDays(); @DefaultStringArrayValue({ "blue", "green", "orange", "yellow", "pink", "purple", "teal", "darkpurple", "steelblue", "lightblue", "lightgreen", "yellowgreen", "redorange", "lightbrown", "lightpurple", "grey", "bluegrey", "lightteal", "yellowgrey", "brown"}) String[] meetingColors(); @DefaultStringValue("red") String freeTimeColor(); @DefaultBooleanValue(false) boolean printReportShowUserName(); @DefaultIntValue(12) int numberOfCourses(); @DefaultIntValue(3) int numberOfAlternatives(); } --- NEW FILE: GwtResources.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.resources; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.ImageResource; /** * @author Tomas Muller */ public interface GwtResources extends ClientBundle, com.google.gwt.user.client.ui.Tree.Resources { @Source("org/unitime/timetable/gwt/resources/icons/loading.gif") ImageResource loading(); @Source("org/unitime/timetable/gwt/resources/icons/loading_small.gif") ImageResource loading_small(); @Source("org/unitime/timetable/gwt/resources/icons/help_icon.gif") ImageResource help(); @Source("org/unitime/timetable/gwt/resources/icons/expand_node_btn.gif") ImageResource treeClosed(); @Source("org/unitime/timetable/gwt/resources/icons/collapse_node_btn.gif") ImageResource treeOpen(); @Source("org/unitime/timetable/gwt/resources/icons/end_node_btn.gif") ImageResource treeLeaf(); @Source("org/unitime/timetable/gwt/resources/icons/minimize.gif") ImageResource menu_opened(); @Source("org/unitime/timetable/gwt/resources/icons/minimize_RO.gif") ImageResource menu_opened_hover(); @Source("org/unitime/timetable/gwt/resources/icons/openMenu.gif") ImageResource menu_closed(); @Source("org/unitime/timetable/gwt/resources/icons/openMenu_RO.gif") ImageResource menu_closed_hover(); @Source("org/unitime/timetable/gwt/resources/icons/action_add.png") ImageResource add(); @Source("org/unitime/timetable/gwt/resources/icons/action_delete.png") ImageResource delete(); } --- NEW FILE: StudentSectioningResources.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.resources; import com.google.gwt.resources.client.ClientBundle; import com.google.gwt.resources.client.ImageResource; /** * @author Tomas Muller */ public interface StudentSectioningResources extends ClientBundle { @Source("org/unitime/timetable/gwt/resources/icons/up_Down.png") ImageResource up_Down(); @Source("org/unitime/timetable/gwt/resources/icons/up.png") ImageResource up(); @Source("org/unitime/timetable/gwt/resources/icons/up_Over.png") ImageResource up_Over(); @Source("org/unitime/timetable/gwt/resources/icons/down_Down.png") ImageResource down_Down(); @Source("org/unitime/timetable/gwt/resources/icons/down.png") ImageResource down(); @Source("org/unitime/timetable/gwt/resources/icons/down_Over.png") ImageResource down_Over(); @Source("org/unitime/timetable/gwt/resources/icons/search_picker_Disabled.png") ImageResource search_picker_Disabled(); @Source("org/unitime/timetable/gwt/resources/icons/search_picker_Down.png") ImageResource search_picker_Down(); @Source("org/unitime/timetable/gwt/resources/icons/search_picker_Normal.png") ImageResource search_picker_Normal(); @Source("org/unitime/timetable/gwt/resources/icons/search_picker_Over.png") ImageResource search_picker_Over(); @Source("org/unitime/timetable/gwt/resources/icons/search_picker.png") ImageResource search_picker(); @Source("org/unitime/timetable/gwt/resources/icons/roadrunner16.png") ImageResource distantConflict(); @Source("org/unitime/timetable/gwt/resources/icons/save.png") ImageResource saved(); @Source("org/unitime/timetable/gwt/resources/icons/lock.png") ImageResource locked(); @Source("org/unitime/timetable/gwt/resources/icons/lock_unlock.png") ImageResource unlocked(); @Source("org/unitime/timetable/gwt/resources/icons/printer.png") ImageResource print(); @Source("org/unitime/timetable/gwt/resources/icons/letter.png") ImageResource email(); @Source("org/unitime/timetable/gwt/resources/icons/application.png") ImageResource calendar(); @Source("org/unitime/timetable/gwt/resources/icons/comments.png") ImageResource comments(); @Source("org/unitime/timetable/gwt/resources/icons/group.png") ImageResource highDemand(); } --- NEW FILE: StudentSectioningMessages.properties --- colClass=CRN --- NEW FILE: StudentSectioningExceptions.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.resources; import com.google.gwt.i18n.client.Messages; /** * @author Tomas Muller */ public interface StudentSectioningExceptions extends Messages { @DefaultMessage("Course {0} does not exist.") String courseDoesNotExist(String course); @DefaultMessage("Academic session {0} does not exist.") String sessionDoesNotExist(String session); @DefaultMessage("Academic session not selected.") String noAcademicSession(); @DefaultMessage("No suitable academic sessions found.") String noSuitableAcademicSessions(); @DefaultMessage("No classes found for {0}.") String noClassesForCourse(String course); @DefaultMessage("Unable to compute a schedule ({0}).") String sectioningFailed(String message); @DefaultMessage("Too many bad attempts, login disabled.") String tooManyLoginAttempts(); @DefaultMessage("User name not provided.") String loginNoUsername(); @DefaultMessage("Wrong username and/or password.") String loginFailed(); @DefaultMessage("Login failed ({0}).") String loginFailedUnknown(String message); @DefaultMessage("User is not logged in.") String userNotLoggedIn(); @DefaultMessage("Unable to load section information ({0}).") String customSectionNamesFailed(String reason); @DefaultMessage("Unable to retrive course details ({0}).") String customCourseDetailsFailed(String reason); @DefaultMessage("Unable to retrive class details ({0}).") String customSectionLimitsFailed(String reason); @DefaultMessage("Course detail interface not provided.") String noCustomCourseDetails(); @DefaultMessage("Last academic session failed ({0}).") String lastAcademicSessionFailed(String message); @DefaultMessage("Not a student.") String noStudent(); @DefaultMessage("Wrong student id.") String badStudentId(); @DefaultMessage("No requests stored for the student.") String noRequests(); @DefaultMessage("Wrong academic session.") String badSession(); @DefaultMessage("Your are not authenticated, please log in first.") String enrollNotAuthenticated(); @DefaultMessage("Your are not registered as a student in {0}.") String enrollNotStudent(String session); @DefaultMessage("Unable to enroll into {0}, the class is no longer available.") String enrollNotAvailable(String clazz); @DefaultMessage("This feature is not supported in the current environment.") String notSupportedFeature(); @DefaultMessage("No schedule stored for the student.") String noSchedule(); @DefaultMessage("No courses provided.") String noCourse(); @DefaultMessage("Unable to compute a schedule (no solution found).") String noSolution(); @DefaultMessage("{0}") String unknown(String reason); } |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:10:57
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/client/page In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/client/page Added Files: UniTimeMenuBar.java UniTimePageLabel.java UniTimeSideBar.java UniTimeBack.java Refresh.java UniTimeVersion.java UniTimePageHeader.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: UniTimeMenuBar.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.page; import java.util.List; import org.unitime.timetable.gwt.client.Client; import org.unitime.timetable.gwt.client.Pages; import org.unitime.timetable.gwt.client.ToolBox; import org.unitime.timetable.gwt.client.Client.GwtPageChangeEvent; import org.unitime.timetable.gwt.client.Client.GwtPageChangedHandler; import org.unitime.timetable.gwt.client.widgets.LoadingWidget; import org.unitime.timetable.gwt.client.widgets.UniTimeFrameDialog; import org.unitime.timetable.gwt.services.MenuService; import org.unitime.timetable.gwt.services.MenuServiceAsync; import org.unitime.timetable.gwt.shared.MenuInterface; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.RunAsyncCallback; import com.google.gwt.event.logical.shared.ResizeEvent; import com.google.gwt.event.logical.shared.ResizeHandler; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.Window.ScrollEvent; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.MenuBar; import com.google.gwt.user.client.ui.MenuItem; import com.google.gwt.user.client.ui.MenuItemSeparator; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; /** * @author Tomas Muller */ public class UniTimeMenuBar extends Composite { protected final MenuServiceAsync iService = GWT.create(MenuService.class); private MenuBar iMenu; private SimplePanel iSimple = null; private int iLastScrollLeft = 0, iLastScrollTop = 0, iLastClientWidth = 0; private Timer iMoveTimer; public UniTimeMenuBar(boolean absolute) { iMenu = new MenuBar(); iMenu.setVisible(false); iMenu.addStyleName("unitime-NoPrint"); iMenu.addStyleName("unitime-Menu"); initWidget(iMenu); if (absolute) { DOM.setStyleAttribute(iMenu.getElement(), "position", "absolute"); move(false); iMoveTimer = new Timer() { @Override public void run() { move(true); } }; Window.addResizeHandler(new ResizeHandler() { @Override public void onResize(ResizeEvent event) { delayedMove(); } }); Window.addWindowScrollHandler(new Window.ScrollHandler() { @Override public void onWindowScroll(ScrollEvent event) { delayedMove(); } }); Client.addGwtPageChangedHandler(new GwtPageChangedHandler() { @Override public void onChange(GwtPageChangeEvent event) { delayedMove(); } }); iSimple = new SimplePanel(); new Timer() { @Override public void run() { delayedMove(); } }.scheduleRepeating(5000); } iService.getMenu(new AsyncCallback<List<MenuInterface>>() { @Override public void onSuccess(List<MenuInterface> result) { initMenu(iMenu, result, 0); iMenu.setVisible(true); if (iSimple != null) iSimple.setHeight(String.valueOf(iMenu.getOffsetHeight())); } @Override public void onFailure(Throwable caught) { } }); } private void move(boolean show) { iLastClientWidth = Window.getClientWidth(); iLastScrollLeft = Window.getScrollLeft(); iLastScrollTop = Window.getScrollTop(); iMenu.setWidth(String.valueOf(iLastClientWidth - 2)); DOM.setStyleAttribute(iMenu.getElement(), "left", String.valueOf(iLastScrollLeft)); DOM.setStyleAttribute(iMenu.getElement(), "top", String.valueOf(iLastScrollTop)); iMenu.setVisible(true); } private boolean needsMove() { return iLastClientWidth != Window.getClientWidth() || iLastScrollLeft != Window.getScrollLeft() || iLastScrollTop != Window.getScrollTop(); } private void delayedMove() { if (needsMove()) { iMenu.setVisible(false); iMoveTimer.schedule(100); } } private void initMenu(MenuBar menu, List<MenuInterface> items, int level) { MenuItemSeparator lastSeparator = null; for (final MenuInterface item: items) { if (item.isSeparator()) { lastSeparator = new MenuItemSeparator(); menu.addSeparator(lastSeparator); } else if (item.hasSubMenus()) { if (item.getPage() == null) { MenuBar m = new MenuBar(true); initMenu(m, item.getSubMenus(), level + 1); menu.addItem(new MenuItem(item.getName().replace(" ", " "), true, m)); } else { menu.addItem(new MenuItem(item.getName().replace(" ", " "), true, new Command() { @Override public void execute() { if (item.isGWT()) //openPageAsync(item.getPage()); openUrl(item.getName(), "gwt.jsp?page=" + item.getPage(), item.getTarget()); else { openUrl(item.getName(), item.getPage(), item.getTarget()); } } })); initMenu(menu, item.getSubMenus(), level); } } else { menu.addItem(new MenuItem(item.getName().replace(" ", " "), true, new Command() { @Override public void execute() { if (item.getPage() != null) { if (item.isGWT()) //openPageAsync(item.getPage()); openUrl(item.getName(), "gwt.jsp?page=" + item.getPage(), item.getTarget()); else { openUrl(item.getName(), item.getPage(), item.getTarget()); } } } })); } } if (level == 0 && lastSeparator != null) { lastSeparator.setStyleName("unitime-BlankSeparator"); lastSeparator.setWidth("100%"); } } protected void openUrl(final String name, final String url, String target) { if (target == null) LoadingWidget.getInstance().show(); if ("dialog".equals(target)) { UniTimeFrameDialog.openDialog(name, url); } else if ("download".equals(target)) { ToolBox.open(url); } else { ToolBox.open(GWT.getHostPageBaseURL() + url); } } protected void openPageAsync(final String page) { LoadingWidget.getInstance().show(); if (RootPanel.get("UniTimeGWT:Body") == null) { ToolBox.open(GWT.getHostPageBaseURL() + "gwt.jsp?page=" + page); return; } RootPanel.get("UniTimeGWT:Body").clear(); RootPanel.get("UniTimeGWT:Body").getElement().setInnerHTML(null); GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { openPage(page); LoadingWidget.getInstance().hide(); } public void onFailure(Throwable reason) { Label error = new Label("Failed to load the page (" + reason.getMessage() + ")"); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("UniTimeGWT:Body").add(error); LoadingWidget.getInstance().hide(); } }); } protected void openPage(String page) { try { for (Pages p: Pages.values()) { if (p.name().equals(page)) { LoadingWidget.getInstance().setMessage("Loading " + p.title() + " ..."); UniTimePageLabel.getInstance().setTitle(p.title()); RootPanel.get("UniTimeGWT:Body").add(p.widget()); return; } } Label error = new Label("Failed to load the page (" + (page == null ? "page not provided" : "page " + page + " not registered" ) + ")"); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("UniTimeGWT:Body").add(error); } catch (Exception e) { Label error = new Label("Failed to load the page (" + e.getMessage() + ")"); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("UniTimeGWT:Body").add(error); } } public void insert(final RootPanel panel) { panel.add(this); panel.setVisible(true); if (iSimple != null) { iSimple.setHeight(String.valueOf(iMenu.getOffsetHeight())); panel.add(iSimple); } } } --- NEW FILE: UniTimePageLabel.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.page; import org.unitime.timetable.gwt.client.widgets.UniTimeFrameDialog; import org.unitime.timetable.gwt.resources.GwtResources; import org.unitime.timetable.gwt.services.MenuService; import org.unitime.timetable.gwt.services.MenuServiceAsync; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Cursor; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; /** * @author Tomas Muller */ public class UniTimePageLabel extends Composite { public static final GwtResources RESOURCES = GWT.create(GwtResources.class); private final MenuServiceAsync iService = GWT.create(MenuService.class); private HorizontalPanel iPanel; private Label iName; private Image iHelp; private String iUrl = null; private static UniTimePageLabel sInstance = null; private UniTimePageLabel() { iPanel = new HorizontalPanel(); iName = new Label(); iName.setStyleName("unitime-Title"); iHelp = new Image(RESOURCES.help()); iHelp.setVisible(false); iHelp.getElement().getStyle().setCursor(Cursor.POINTER); iPanel.add(iName); iPanel.add(iHelp); iPanel.setCellVerticalAlignment(iHelp, HasVerticalAlignment.ALIGN_TOP); initWidget(iPanel); iHelp.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (iUrl == null) return; UniTimeFrameDialog.openDialog(iName.getText() + " Help", iUrl); } }); } public static UniTimePageLabel getInstance() { if (sInstance == null) sInstance = new UniTimePageLabel(); return sInstance; } public void insert(final RootPanel panel) { String title = panel.getElement().getInnerText(); if (title != null && !title.isEmpty()) setPageName(title); panel.getElement().setInnerText(null); panel.add(this); panel.setVisible(true); } public void setPageName(String title) { Window.setTitle("UniTime 3.2| " + title); iName.setText(title); iHelp.setTitle(title + " Help"); iHelp.setVisible(false); iService.getHelpPage(title, new AsyncCallback<String>() { @Override public void onFailure(Throwable caught) { iHelp.setVisible(false); iUrl = null; } @Override public void onSuccess(String result) { iHelp.setVisible(true); iUrl = result; } }); } } --- NEW FILE: UniTimePageHeader.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.page; import java.util.HashMap; import java.util.TreeSet; import org.unitime.timetable.gwt.client.ToolBox; import org.unitime.timetable.gwt.services.MenuService; import org.unitime.timetable.gwt.services.MenuServiceAsync; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.PopupPanel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.VerticalPanel; /** * @author Tomas Muller */ public class UniTimePageHeader extends Composite { private final MenuServiceAsync iService = GWT.create(MenuService.class); private HorizontalPanel iPanel = new HorizontalPanel(); private VerticalPanelWithHint iSolverInfo, iSessionInfo, iUserInfo; public UniTimePageHeader() { iSolverInfo = new VerticalPanelWithHint(); iPanel.add(iSolverInfo); iPanel.setCellHorizontalAlignment(iSolverInfo, HasHorizontalAlignment.ALIGN_LEFT); iSolverInfo.getElement().getStyle().setPaddingRight(30, Unit.PX); iUserInfo = new VerticalPanelWithHint(); iPanel.add(iUserInfo); iPanel.setCellHorizontalAlignment(iUserInfo, HasHorizontalAlignment.ALIGN_CENTER); iUserInfo.getElement().getStyle().setPaddingRight(30, Unit.PX); iSessionInfo = new VerticalPanelWithHint(); iPanel.add(iSessionInfo); iPanel.setCellHorizontalAlignment(iSessionInfo, HasHorizontalAlignment.ALIGN_RIGHT); initWidget(iPanel); reloadSessionInfo(); reloadUserInfo(); reloadSolverInfo(); } public void insert(final RootPanel panel) { if (panel.getWidgetCount() > 0) return; panel.add(this); panel.setVisible(true); } public void reloadSessionInfo() { iService.getSessionInfo(new AsyncCallback<HashMap<String,String>>() { @Override public void onSuccess(HashMap<String, String> result) { iSessionInfo.clear(); iSessionInfo.setHint(result); if (result == null) return; HTML sessionLabel = new HTML(result.get("0Session"), false); sessionLabel.setStyleName("unitime-SessionSelector"); iSessionInfo.add(sessionLabel); HTML hint = new HTML("Click here to change the session / role.", false); hint.setStyleName("unitime-Hint"); iSessionInfo.add(hint); ClickHandler c = new ClickHandler() { @Override public void onClick(ClickEvent event) { ToolBox.open(GWT.getHostPageBaseURL() + "selectPrimaryRole.do?list=Y"); } }; sessionLabel.addClickHandler(c); hint.addClickHandler(c); } @Override public void onFailure(Throwable caught) { iSessionInfo.clear(); iSessionInfo.setHint(null); } }); } public void reloadUserInfo() { iService.getUserInfo(new AsyncCallback<HashMap<String,String>>() { @Override public void onSuccess(HashMap<String, String> result) { iUserInfo.clear(); iUserInfo.setHint(result); if (result == null) return; HTML userLabel = new HTML(result.get("0Name"), false); userLabel.setStyleName("unitime-SessionSelector"); iUserInfo.add(userLabel); HTML hint = new HTML(result.get("2Role"), false); hint.setStyleName("unitime-Hint"); iUserInfo.add(hint); if (result.containsKey("Chameleon")) { ClickHandler c = new ClickHandler() { @Override public void onClick(ClickEvent event) { ToolBox.open(GWT.getHostPageBaseURL() + "chameleon.do"); } }; userLabel.addClickHandler(c); hint.addClickHandler(c); } } @Override public void onFailure(Throwable caught) { iUserInfo.clear(); iUserInfo.setHint(null); } }); } public void reloadSolverInfo() { iService.getSolverInfo(new AsyncCallback<HashMap<String,String>>() { @Override public void onSuccess(HashMap<String, String> result) { iSolverInfo.clear(); boolean hasSolver = false; try { iSolverInfo.setHint(result); if (result != null) { HTML userLabel = new HTML(result.get("1Solver"), false); userLabel.setStyleName("unitime-SessionSelector"); iSolverInfo.add(userLabel); HTML hint = new HTML(result.get("0Type"), false); hint.setStyleName("unitime-Hint"); iSolverInfo.add(hint); final String type = result.get("0Type"); ClickHandler c = new ClickHandler() { @Override public void onClick(ClickEvent event) { if (type.equals("Course Timetabling Solver")) ToolBox.open(GWT.getHostPageBaseURL() + "solver.do"); else if (type.equals("Examinations Solver")) ToolBox.open(GWT.getHostPageBaseURL() + "examSolver.do"); else ToolBox.open(GWT.getHostPageBaseURL() + "studentSolver.do"); } }; userLabel.addClickHandler(c); hint.addClickHandler(c); hasSolver = true; } } catch (Exception e) {} Timer t = new Timer() { @Override public void run() { reloadSolverInfo(); } }; t.schedule(hasSolver ? 1000 : 60000); } @Override public void onFailure(Throwable caught) { Timer t = new Timer() { @Override public void run() { reloadSolverInfo(); } }; t.schedule(5000); } }); } public static class VerticalPanelWithHint extends VerticalPanel { private PopupPanel iHintPanel = null; private Timer iShowHint, iHideHint = null; private HTML iHint = null; private int iX, iY; public VerticalPanelWithHint() { super(); iHint = new HTML("", false); iHintPanel = new PopupPanel(); iHintPanel.setWidget(iHint); iHintPanel.setStyleName("unitime-PopupHint"); sinkEvents(Event.ONMOUSEOVER); sinkEvents(Event.ONMOUSEOUT); sinkEvents(Event.ONMOUSEMOVE); iShowHint = new Timer() { @Override public void run() { iHintPanel.setPopupPositionAndShow(new PopupPanel.PositionCallback() { @Override public void setPosition(int offsetWidth, int offsetHeight) { int maxX = Window.getScrollLeft() + Window.getClientWidth() - offsetWidth - 10; iHintPanel.setPopupPosition(Math.min(iX, maxX), iY); } }); } }; iHideHint = new Timer() { @Override public void run() { iHintPanel.hide(); } }; } public void setHint(HashMap<String,String> hint) { String html = ""; if (hint != null && !hint.isEmpty()) { html += "<table cellspacing=\"0\" cellpadding=\"3\">"; TreeSet<String> keys = new TreeSet<String>(hint.keySet()); for (String key: keys) { String val = hint.get(key); if (val.isEmpty()) continue; String style = ""; if (key.startsWith("A")) style = "border-top: 1px dashed #AB8B00;"; html += "<tr><td style=\"" + style + "\">" + key.substring(1) + ":</td><td style=\"" + style + "\">" + val + "</td></tr>"; } html += "</table>"; } iHint.setHTML(html); } public void onBrowserEvent(Event event) { if (iHint.getText().isEmpty()) return; iX = 10 + event.getClientX() + getElement().getOwnerDocument().getScrollLeft(); iY = 10 + event.getClientY() + getElement().getOwnerDocument().getScrollTop(); switch (DOM.eventGetType(event)) { case Event.ONMOUSEMOVE: if (iHintPanel.isShowing()) { int maxX = Window.getScrollLeft() + Window.getClientWidth() - iHintPanel.getOffsetWidth() - 10; iHintPanel.setPopupPosition(Math.min(iX, maxX), iY); } else { iShowHint.cancel(); iShowHint.schedule(1000); } break; case Event.ONMOUSEOUT: iShowHint.cancel(); if (iHintPanel.isShowing()) iHideHint.schedule(1000); break; } } } } --- NEW FILE: UniTimeSideBar.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.page; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import org.unitime.timetable.gwt.client.Client; import org.unitime.timetable.gwt.client.ToolBox; import org.unitime.timetable.gwt.client.Client.GwtPageChangeEvent; import org.unitime.timetable.gwt.client.Client.GwtPageChangedHandler; import org.unitime.timetable.gwt.client.widgets.LoadingWidget; import org.unitime.timetable.gwt.client.widgets.UniTimeFrameDialog; import org.unitime.timetable.gwt.resources.GwtResources; import org.unitime.timetable.gwt.services.MenuService; import org.unitime.timetable.gwt.services.MenuServiceAsync; import org.unitime.timetable.gwt.shared.MenuInterface; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Style.Display; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.event.dom.client.MouseOverEvent; import com.google.gwt.event.dom.client.MouseOverHandler; import com.google.gwt.event.logical.shared.CloseEvent; import com.google.gwt.event.logical.shared.CloseHandler; import com.google.gwt.event.logical.shared.OpenEvent; import com.google.gwt.event.logical.shared.OpenHandler; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Cookies; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.DisclosurePanel; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.StackPanel; import com.google.gwt.user.client.ui.Tree; import com.google.gwt.user.client.ui.TreeItem; /** * @author Tomas Muller */ public class UniTimeSideBar extends Composite { protected final MenuServiceAsync iService = GWT.create(MenuService.class); public static final GwtResources RESOURCES = GWT.create(GwtResources.class); private Timer iScrollTimer = null; private SimplePanel iPanel; private DisclosurePanel iDisclosurePanel; private MyStackPanel iStackPanel; private Tree iTree; private int iTop = 0; public UniTimeSideBar(boolean useStackPanel) { iPanel = new SimplePanel(); iPanel.addStyleName("unitime-NoPrint"); final HorizontalPanel header = new HorizontalPanel(); final Label menuLabel = new Label("Navigation", false); menuLabel.setVisible(false); menuLabel.setStyleName("unitime-MenuHeaderLabel"); header.add(menuLabel); final Image menuImage = new Image(RESOURCES.menu_closed()); header.add(menuImage); header.setCellHorizontalAlignment(menuImage, HasHorizontalAlignment.ALIGN_RIGHT); header.setCellVerticalAlignment(menuImage, HasVerticalAlignment.ALIGN_MIDDLE); header.setStyleName("unitime-MenuHeaderClose"); iDisclosurePanel = new DisclosurePanel(); iDisclosurePanel.setHeader(header); menuImage.addMouseOverHandler(new MouseOverHandler() { @Override public void onMouseOver(MouseOverEvent event) { menuImage.setResource(iDisclosurePanel.isOpen() ? RESOURCES.menu_opened_hover() : RESOURCES.menu_closed_hover()); } }); menuImage.addMouseOutHandler(new MouseOutHandler() { @Override public void onMouseOut(MouseOutEvent event) { menuImage.setResource(iDisclosurePanel.isOpen() ? RESOURCES.menu_opened() : RESOURCES.menu_closed()); } }); iDisclosurePanel.addOpenHandler(new OpenHandler<DisclosurePanel>() { @Override public void onOpen(OpenEvent<DisclosurePanel> event) { menuImage.setResource(iDisclosurePanel.isOpen() ? RESOURCES.menu_opened() : RESOURCES.menu_closed()); menuLabel.setVisible(iDisclosurePanel.isOpen()); header.setStyleName("unitime-MenuHeader" + (iDisclosurePanel.isOpen() ? "Open" : "Close")); saveState(); } }); iDisclosurePanel.addCloseHandler(new CloseHandler<DisclosurePanel>() { @Override public void onClose(CloseEvent<DisclosurePanel> event) { menuImage.setResource(iDisclosurePanel.isOpen() ? RESOURCES.menu_opened() : RESOURCES.menu_closed()); menuLabel.setVisible(iDisclosurePanel.isOpen()); header.setStyleName("unitime-MenuHeader" + (iDisclosurePanel.isOpen() ? "Open" : "Close")); saveState(); } }); iStackPanel = new MyStackPanel(); iTree = new Tree(RESOURCES, true); iTree.addOpenHandler(new OpenHandler<TreeItem>() { @Override public void onOpen(OpenEvent<TreeItem> event) { saveState(); } }); iTree.addCloseHandler(new CloseHandler<TreeItem>() { @Override public void onClose(CloseEvent<TreeItem> event) { saveState(); } }); SimplePanel simple = new SimplePanel(); if (useStackPanel) simple.setWidget(iStackPanel); else simple.setWidget(iTree); iDisclosurePanel.add(simple); iPanel.setWidget(iDisclosurePanel); iPanel.setHeight("100%"); DOM.setStyleAttribute(iDisclosurePanel.getElement(), "position", "relative"); initWidget(iPanel); iService.getMenu(new AsyncCallback<List<MenuInterface>>() { @Override public void onSuccess(List<MenuInterface> result) { initMenu(result); } @Override public void onFailure(Throwable caught) { } }); iScrollTimer = new Timer() { @Override public void run() { DOM.setStyleAttribute(iDisclosurePanel.getElement(), "top", String.valueOf(iTop)); } }; Window.addWindowScrollHandler(new Window.ScrollHandler() { @Override public void onWindowScroll(Window.ScrollEvent event) { int fromTop = Math.max(Window.getScrollTop() - iPanel.getAbsoluteTop(), 0); // 20 pixels for the top menu int fromBottom = Window.getClientHeight() + Window.getScrollTop() - iDisclosurePanel.getOffsetHeight() - 60; iDisclosurePanel.getAbsoluteTop(); if (fromTop <= fromBottom) { iTop = fromTop; } else { if (fromBottom <= iTop && iTop <= fromTop) { } else if (iTop > fromTop) { iTop = fromTop; } else { iTop = fromBottom; } } iScrollTimer.schedule(100); } }); Client.addGwtPageChangedHandler(new GwtPageChangedHandler() { @Override public void onChange(GwtPageChangeEvent event) { int fromTop = Math.max(Window.getScrollTop() - iPanel.getAbsoluteTop(), 0); // 20 pixels for the top menu int fromBottom = Window.getClientHeight() + Window.getScrollTop() - iDisclosurePanel.getOffsetHeight() - 60; iDisclosurePanel.getAbsoluteTop(); if (fromTop <= fromBottom) { iTop = fromTop; } else { if (fromBottom <= iTop && iTop <= fromTop) { } else if (iTop > fromTop) { iTop = fromTop; } else { iTop = fromBottom; } } iScrollTimer.schedule(100); } }); } public boolean isOpenned(String name) { String sideBarCookie = Cookies.getCookie("UniTime:SideBar"); return sideBarCookie != null && sideBarCookie.indexOf("|"+name+"|") >= 0; } private void openedNodes(List<String> ret, TreeItem item) { if (item.getState()) ret.add(item.getText()); for (int i = 0; i < item.getChildCount(); i++) openedNodes(ret, item.getChild(i)); } public void saveState() { List<String> nodes = new ArrayList<String>(); if (iStackPanel.isAttached()) { nodes.add(iStackPanel.getStackText(iStackPanel.getSelectedIndex())); for (int i = 0; i < iStackPanel.getWidgetCount(); i++) { if (iStackPanel.getWidget(i) instanceof Tree) { Tree t = (Tree)iStackPanel.getWidget(i); for (int j = 0; j < t.getItemCount(); j++) { openedNodes(nodes, t.getItem(j)); } } } } else { for (int i = 0; i < iTree.getItemCount(); i++) { openedNodes(nodes, iTree.getItem(i)); } } String sideBarCookie = ""; if (iDisclosurePanel.isOpen()) sideBarCookie += "Root"; for (String node: nodes) { if (!sideBarCookie.isEmpty()) sideBarCookie += "|"; sideBarCookie += node; } Cookies.setCookie("UniTime:SideBar", sideBarCookie); } private void openNodes(Set<String> nodes, TreeItem item) { if (nodes.contains(item.getText())) item.setState(true); for (int i = 0; i < item.getChildCount(); i++) openNodes(nodes, item.getChild(i)); } public void restoreState() { Set<String> nodes = new HashSet<String>(); String sideBarCookie = Cookies.getCookie("UniTime:SideBar"); if (sideBarCookie != null) for (String node: sideBarCookie.split("\\|")) nodes.add(node); iDisclosurePanel.setOpen(nodes.contains("Root")); if (iStackPanel.isAttached()) for (int i = 0 ; i < iStackPanel.getWidgetCount(); i++) { if (nodes.contains(iStackPanel.getStackText(i))) { iStackPanel.showStack(i); } if (iStackPanel.getWidget(i) instanceof Tree) { Tree t = (Tree)iStackPanel.getWidget(i); for (int j = 0; j < t.getItemCount(); j++) { openNodes(nodes, t.getItem(j)); } } } else for (int i = 0; i < iTree.getItemCount(); i++) { openNodes(nodes, iTree.getItem(i)); } } public void insert(final RootPanel panel) { panel.add(this); panel.setVisible(true); } private TreeItem generateItem(final MenuInterface item) { Label label = new Label(item.getName(), false); TreeItem treeItem = new TreeItem(label); if (item.getPage() != null) { label.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if (item.isGWT()) openUrl(item.getName(), "gwt.jsp?page=" + item.getPage(), item.getTarget()); else { openUrl(item.getName(), item.getPage(), item.getTarget()); } } }); } if (item.hasSubMenus()) for (MenuInterface subItem: item.getSubMenus()) if (!subItem.isSeparator()) treeItem.addItem(generateItem(subItem)); return treeItem; } private void initMenu(List<MenuInterface> items) { for (final MenuInterface item: items) { if (item.isSeparator()) continue; iTree.addItem(generateItem(item)); if (item.hasSubMenus()) { Tree tree = new Tree(RESOURCES, true); for (MenuInterface subItem: item.getSubMenus()) if (!subItem.isSeparator()) tree.addItem(generateItem(subItem)); iStackPanel.add(tree, item.getName()); tree.addOpenHandler(new OpenHandler<TreeItem>() { @Override public void onOpen(OpenEvent<TreeItem> event) { saveState(); } }); tree.addCloseHandler(new CloseHandler<TreeItem>() { @Override public void onClose(CloseEvent<TreeItem> event) { saveState(); } }); } else { iStackPanel.add(new Command() { @Override public void execute() { if (item.isGWT()) openUrl(item.getName(), "gwt.jsp?page=" + item.getPage(), item.getTarget()); else { openUrl(item.getName(), item.getPage(), item.getTarget()); } } }, item.getName()); } } restoreState(); iStackPanel.setActive(true); } protected void openUrl(final String name, final String url, String target) { if (target == null) LoadingWidget.getInstance().show(); if ("dialog".equals(target)) { UniTimeFrameDialog.openDialog(name, url); } else if ("download".equals(target)) { ToolBox.open(url); } else { ToolBox.open(GWT.getHostPageBaseURL() + url); } } public class MyStackPanel extends StackPanel { private Element body = null; private boolean iActive = false; public MyStackPanel() { super(); body = DOM.getFirstChild(getElement()); } public String getStackText(int index) { if (index >= getWidgetCount()) { return null; } Element tdWrapper = DOM.getChild(DOM.getChild(body, index * 2), 0); return DOM.getFirstChild(tdWrapper).getInnerText(); } public void add(Command cmd, String text) { add(new DummyWidget(cmd), text); } public void showStack(int index) { if (iActive) { if (getWidget(index) instanceof DummyWidget) { ((DummyWidget)getWidget(index)).getClickCommand().execute(); } else { super.showStack(index); saveState(); } } else { super.showStack(index); } } public void setActive(boolean active) { iActive = active; } public class DummyWidget extends SimplePanel { private Command iClickCommand = null; public DummyWidget(Command cmd) { getElement().getStyle().setDisplay(Display.NONE); iClickCommand = cmd; } public Command getClickCommand() { return iClickCommand; } } } } --- NEW FILE: Refresh.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.page; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.Window; public class Refresh { public static native void createTriggers()/*-{ $wnd.refreshPage = function(message) { @org.unitime.timetable.gwt.client.page.Refresh::refreshPage()(); }; @org.unitime.timetable.gwt.client.page.Refresh::scrollDown()(); }-*/; public static void refreshPage() { String url = Window.Location.getHref(); if (url.indexOf('#') >= 0) url = url.substring(0, url.lastIndexOf('#')); url += "#" + Window.getScrollLeft() + ":" + Window.getScrollTop(); Window.Location.assign(url); new Timer() { @Override public void run() { Window.Location.reload(); } }.schedule(100); } public static void scrollDown() { String hash = Window.Location.getHash(); if (hash != null && hash.matches("#[0-9]+:[0-9]+")) { String[] scroll = hash.substring(1).split(":"); Window.scrollTo(Integer.parseInt(scroll[0]), Integer.parseInt(scroll[1])); } } } --- NEW FILE: UniTimeVersion.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.page; import org.unitime.timetable.gwt.services.MenuService; import org.unitime.timetable.gwt.services.MenuServiceAsync; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; /** * @author Tomas Muller */ public class UniTimeVersion extends Composite { private final MenuServiceAsync iService = GWT.create(MenuService.class); private Label iLabel; public UniTimeVersion() { iLabel = new Label(); //iLabel.setStyleName("unitime-Footer"); iService.getVersion(new AsyncCallback<String>() { @Override public void onSuccess(String result) { iLabel.setText(result); } @Override public void onFailure(Throwable caught) { } }); initWidget(iLabel); } public void insert(final RootPanel panel) { panel.add(this); panel.setVisible(true); } } --- NEW FILE: UniTimeBack.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client.page; import java.util.ArrayList; import java.util.List; import com.google.gwt.core.client.GWT; import com.google.gwt.event.logical.shared.ValueChangeEvent; import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.RootPanel; /** * @author Tomas Muller */ public class UniTimeBack { private String iBackUrl = null; private List<String[]> iBacks = new ArrayList<String[]>(); public UniTimeBack() { History.addValueChangeHandler(new ValueChangeHandler<String>() { @Override public void onValueChange(ValueChangeEvent<String> event) { if (event.getValue() == null || event.getValue().isEmpty() || "back".equals(event.getValue())) { open(GWT.getHostPageBaseURL() + "back.do?uri=" + iBackUrl); } else { String uri = token2uri(event.getValue().replace("%20", " ")); if (uri != null) open(GWT.getHostPageBaseURL() + "back.do?uri=" + uri); } } }); } private native void open(String url) /*-{ $wnd.location = url; }-*/; private String token2uri(String token) { for (String[] back: iBacks) { if (back[1].equals(token)) return back[0]; } return null; } public void insert(final RootPanel panel) { String backs = panel.getElement().getInnerText(); iBacks.clear(); for (String back: backs.split("\\&")) { String[] b = back.split("\\|"); iBacks.add(b); History.newItem(b[1], false); } if (iBacks.isEmpty()) return; int back = 2; String lastUrl = iBacks.get(iBacks.size() - 1)[0]; if (lastUrl.indexOf('%') >= 0) lastUrl = lastUrl.substring(0, lastUrl.indexOf('%')); String currentUrl = Window.Location.getHref(); if (currentUrl.indexOf('/') >= 0) currentUrl = currentUrl.substring(currentUrl.lastIndexOf('/') + 1); if (currentUrl.indexOf('?') >= 0) currentUrl = currentUrl.substring(0, currentUrl.lastIndexOf('?')); if (currentUrl.indexOf('#') >= 0) currentUrl = currentUrl.substring(0, currentUrl.lastIndexOf('#')); if (!lastUrl.equals(currentUrl) || iBacks.size() < 2) { back = 1; History.newItem("back", false); } iBackUrl = iBacks.get(iBacks.size() - back)[0]; } } |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/solver/curricula/students In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/solver/curricula/students Added Files: CurComparator.java CurStudentSwap.java CurValue.java CurModel.java CurVariableSelection.java CurStudentLimit.java CurValueSelection.java CurStudent.java CurVariable.java CurSimpleMove.java CurCourse.java CurTermination.java CurSimpleAssignment.java CurHillClimber.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: CurStudent.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.text.DecimalFormat; import java.util.HashSet; import java.util.Set; /** * @author Tomas Muller */ public class CurStudent { private static DecimalFormat sDF = new DecimalFormat("0.###"); private Set<CurCourse> iCourses = new HashSet<CurCourse>(); private Long iStudentId; private double iWeight; public CurStudent(Long studentId, double weight) { iStudentId = studentId; iWeight = weight; } public double getWeight() { return iWeight; } public void setWeight(double weight) { iWeight = weight; } public Long getStudentId() { return iStudentId; } public Set<CurCourse> getCourses() { return iCourses; } public String toString() { return getStudentId() + (getWeight() != 1.f ? "@" + sDF.format(getWeight()): "" ); } } --- NEW FILE: CurStudentSwap.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import net.sf.cpsolver.ifs.heuristics.NeighbourSelection; import net.sf.cpsolver.ifs.model.Neighbour; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.solver.Solver; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.ToolBox; /** * @author Tomas Muller */ public class CurStudentSwap implements NeighbourSelection<CurVariable, CurValue>{ protected CurStudentSwap(DataProperties config) { } @Override public void init(Solver<CurVariable, CurValue> solver) { } @Override public Neighbour<CurVariable, CurValue> selectNeighbour( Solution<CurVariable, CurValue> solution) { CurModel model = (CurModel)solution.getModel(); CurCourse course = ToolBox.random(model.getSwapCourses()); if (course == null) return null; CurStudent student = null; CurValue oldValue = null, newValue = null; int idx = ToolBox.random(model.getStudents().size()); for (int i = 0; i < model.getStudents().size(); i++) { student = model.getStudents().get((i + idx) % model.getStudents().size()); oldValue = course.getValue(student); if (oldValue == null && student.getCourses().size() < model.getStudentLimit().getMaxLimit()) break; if (oldValue != null && student.getCourses().size() > model.getStudentLimit().getMinLimit()) break; } if (oldValue == null && student.getCourses().size() >= model.getStudentLimit().getMaxLimit()) return null; if (oldValue != null && student.getCourses().size() <= model.getStudentLimit().getMinLimit()) return null; idx = ToolBox.random(model.getStudents().size()); for (int i = 0; i < model.getStudents().size(); i++) { CurStudent newStudent = model.getStudents().get((i + idx) % model.getStudents().size()); if (oldValue != null) { if (course.getStudents().contains(newStudent)) continue; if (newStudent.getCourses().size() >= model.getStudentLimit().getMaxLimit()) continue; if (course.getSize() + newStudent.getWeight() - student.getWeight() > course.getMaxSize()) continue; if (course.getSize() + newStudent.getWeight() - student.getWeight() < course.getMaxSize() - model.getMinStudentWidth()) continue; newValue = new CurValue(oldValue.variable(), newStudent); break; } else { if (newStudent.getCourses().size() <= model.getStudentLimit().getMinLimit()) continue; if (course.getSize() + student.getWeight() - newStudent.getWeight() > course.getMaxSize()) continue; if (course.getSize() + student.getWeight() - newStudent.getWeight() < course.getMaxSize() - model.getMinStudentWidth()) continue; oldValue = course.getValue(newStudent); if (oldValue != null) { newValue = new CurValue(oldValue.variable(), student); break; } } } return (newValue == null ? null : new CurSimpleAssignment(newValue)); } } --- NEW FILE: CurVariable.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.util.ArrayList; import java.util.List; import net.sf.cpsolver.ifs.model.Variable; /** * @author Tomas Muller */ public class CurVariable extends Variable<CurVariable, CurValue> { private CurCourse iCourse; public CurVariable(CurModel model, CurCourse course, int first, int size) { super(); iCourse = course; List<CurValue> values = new ArrayList<CurValue>(); for (int i = 0; i < size; i++) values.add(new CurValue(this, model.getStudents().get(first + i))); setValues(values); } public CurCourse getCourse() { return iCourse; } public String toString() { return getCourse().getCourseName(); } } --- NEW FILE: CurCourse.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import net.sf.cpsolver.ifs.model.Constraint; import net.sf.cpsolver.ifs.util.ToolBox; /** * @author Tomas Muller */ public class CurCourse extends Constraint<CurVariable, CurValue> { private static DecimalFormat sDF = new DecimalFormat("0.###"); private String iCourseName; private Long iCourseId; private Set<CurStudent> iStudents = new HashSet<CurStudent>(); private Hashtable<Long, Double> iTargetShare = new Hashtable<Long, Double>(); private CurModel iModel; private double iMaxSize; private double iSize = 0.0; public CurCourse(CurModel model, Long course, String courseName, int maxNrStudents, double maxSize) { iModel = model; iCourseId = course; iCourseName = courseName; iMaxSize = maxSize; for (int i = 0; i < maxNrStudents; i++) { CurVariable c = new CurVariable(model, this, 0, model.getStudents().size()); model.addVariable(c); addVariable(c); } model.addConstraint(this); } public void computeConflicts(CurValue value, Set<CurValue> conflicts) { if (getSize() + value.getStudent().getWeight() > getMaxSize()) { double excess = getSize() + value.getStudent().getWeight() - getMaxSize(); for (CurValue conf: conflicts) if (conf.variable().getCourse().equals(this)) excess -= conf.getStudent().getWeight(); /* if (value.variable().getAssignment() != null && !conflicts.contains(value.variable().getAssignment())) excess -= value.variable().getAssignment().getStudent().getWeight(); */ while (excess > 0.0) { List<CurValue> adepts = new ArrayList<CurValue>(); double best = 0; for (CurVariable assigned: assignedVariables()) { if (assigned.equals(value.variable())) continue; CurValue adept = assigned.getAssignment(); if (conflicts.contains(adept)) continue; double p = adept.toDouble(); if (adepts.isEmpty() || p < best) { best = p; adepts.clear(); adepts.add(adept); } else if (p == best) { adepts.add(adept); } } if (adepts.isEmpty()) { conflicts.add(value); break; } CurValue conf = ToolBox.random(adepts); conflicts.add(conf); excess -= conf.getStudent().getWeight(); } } if (getStudents().contains(value.getStudent())) for (CurVariable sc: assignedVariables()) { if (sc.getAssignment().getStudent().equals(value.getStudent())) { conflicts.add(sc.getAssignment()); } } } public Set<CurStudent> getStudents() { return iStudents; } public double getMaxSize() { return iMaxSize + iModel.getMinStudentWidth() / 2f; } public double getOriginalMaxSize() { return iMaxSize; } public Long getCourseId() { return iCourseId; } public String getCourseName() { return iCourseName; } public int getNrStudents() { return variables().size(); } public double getSize() { return iSize; } public CurValue getValue(CurStudent student) { for (CurVariable var: variables()) { if (var.getAssignment() != null && var.getAssignment().getStudent().equals(student)) return var.getAssignment(); } return null; } public double share(CurCourse course) { double share = 0; for (CurStudent s: getStudents()) if (course.getStudents().contains(s)) share += s.getWeight(); return share; } public double penalty(CurCourse course) { return Math.abs(share(course) - getTargetShare(course.getCourseId())); } public double penalty(CurStudent student) { return penalty(student, null); /* if (student == null) return 0.0; double penalty = 0; for (CurCourse course: iModel.getCourses()) { if (course.getCourseId().equals(getCourseId())) continue; double target = getTargetShare(course.getCourseId()); double share = share(course); boolean contains = course.getStudents().contains(student); double size = course.getSize(); if (!getStudents().contains(student)) { size += student.getWeight(); if (contains) share += student.getWeight(); } if ((share < target && !contains) || (share > target && contains)) penalty += ((double)Math.abs(share - target)) / (contains ? share : size - share); } return penalty; */ } public double penalty(CurStudent newStudent, CurStudent oldStudent) { if (oldStudent != null && oldStudent.equals(newStudent)) return penalty(newStudent, null); double penalty = 0; for (CurCourse course: iModel.getCourses()) { if (course.getCourseId().equals(getCourseId())) continue; double target = getTargetShare(course.getCourseId()); double share = share(course); double oldPenalty = Math.abs(share - target); if (newStudent != null && course.getStudents().contains(newStudent)) share += newStudent.getWeight(); if (oldStudent != null && course.getStudents().contains(oldStudent)) share -= oldStudent.getWeight(); double newPenalty = Math.abs(share - target); penalty += newPenalty - oldPenalty; } return penalty; } public void setTargetShare(Long course, double targetShare) { iTargetShare.put(course, targetShare); } public double getTargetShare(Long course) { Double targetShare = iTargetShare.get(course); return (targetShare == null ? 0 : targetShare); } @Override public void assigned(long iteration, CurValue value) { super.assigned(iteration, value); iStudents.add(value.getStudent()); value.getStudent().getCourses().add(this); iSize += value.getStudent().getWeight(); /* if (iSize > getMaxSize()) throw new RuntimeException("Maximal number of students in a course exceeded " + "(" + iSize + " > " + getMaxSize() + ")"); if (value.getStudent().getCourses().size() > ((CurModel)value.variable().getModel()).getStudentLimit().getMaxLimit()) throw new RuntimeException("Student max limit breached for " + value.getStudent() + " (" + value.getStudent().getCourses().size() + " > " + ((CurModel)value.variable().getModel()).getStudentLimit().getMaxLimit() + "."); */ } @Override public void unassigned(long iteration, CurValue value) { super.unassigned(iteration, value); iStudents.remove(value.getStudent()); iSize -= value.getStudent().getWeight(); value.getStudent().getCourses().remove(this); /* if (value.getStudent().getCourses().size() < ((CurModel)value.variable().getModel()).getStudentLimit().getMinLimit()) throw new RuntimeException("Student min limit breached for " + value.getStudent() + "."); */ } public int hashCode() { return getCourseId().hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof CurCourse)) return false; return getCourseId().equals(((CurCourse)o).getCourseId()); } public String toString() { return "Course<" + getCourseName() + ", size: " + sDF.format(getSize()) + "/" + sDF.format(getOriginalMaxSize()) + ">"; } public boolean isComplete() { return getSize() + iModel.getMinStudentWidth() > getMaxSize(); } } --- NEW FILE: CurValueSelection.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.util.ArrayList; import java.util.List; import java.util.Set; import net.sf.cpsolver.ifs.heuristics.ValueSelection; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.solver.Solver; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.ToolBox; /** * @author Tomas Muller */ public class CurValueSelection implements ValueSelection<CurVariable, CurValue> { public CurValueSelection(DataProperties cfg) {} public void init(Solver<CurVariable, CurValue> solver) { } public CurValue selectValue( Solution<CurVariable, CurValue> solution, CurVariable selectedVariable) { /* if (ToolBox.random() < 0.2) return selectValueSlow(solution, selectedVariable); return selectValueFast(solution, selectedVariable); */ return selectValueSlow(solution, selectedVariable); } public CurValue selectValueFast( Solution<CurVariable, CurValue> solution, CurVariable selectedVariable) { CurModel m = (CurModel)solution.getModel(); if (selectedVariable.getAssignment() != null && selectedVariable.getAssignment().getStudent().getCourses().size() <= m.getStudentLimit().getMinLimit()) return null; int size = selectedVariable.values().size(); int i = ToolBox.random(size); for (int j = 0; j < size; j++) { CurValue student = selectedVariable.values().get((i + j) % size); if (student.equals(selectedVariable.getAssignment())) continue; if (selectedVariable.getCourse().getStudents().contains(student.getStudent())) continue; if (student.getStudent().getCourses().size() >= m.getStudentLimit().getMaxLimit()) continue; if (selectedVariable.getCourse().getSize() + student.getStudent().getWeight() - (selectedVariable.getAssignment() == null ? 0.0 : selectedVariable.getAssignment().getStudent().getWeight()) > selectedVariable.getCourse().getMaxSize()) continue; if (selectedVariable.getAssignment() != null && selectedVariable.getCourse().getSize() + student.getStudent().getWeight() - selectedVariable.getAssignment().getStudent().getWeight() < selectedVariable.getCourse().getMaxSize() - m.getMinStudentWidth()) continue; return student; } return null; } public CurValue selectValueSlow( Solution<CurVariable, CurValue> solution, CurVariable selectedVariable) { CurModel m = (CurModel)solution.getModel(); if (selectedVariable.getAssignment() != null && selectedVariable.getAssignment().getStudent().getCourses().size() <= m.getStudentLimit().getMinLimit()) return null; List<CurValue> bestStudents = new ArrayList<CurValue>(); List<CurValue> allImprovingStudents = new ArrayList<CurValue>(); List<CurValue> allStudents = new ArrayList<CurValue>(); double bestValue = 0; for (CurValue student: selectedVariable.values()) { if (student.equals(selectedVariable.getAssignment())) continue; if (selectedVariable.getCourse().getStudents().contains(student.getStudent())) continue; if (student.getStudent().getCourses().size() >= m.getStudentLimit().getMaxLimit()) continue; /* if (selectedVariable.getCourse().getSize() + student.getStudent().getWeight() - (selectedVariable.getAssignment() == null ? 0.0 : selectedVariable.getAssignment().getStudent().getWeight()) > selectedVariable.getCourse().getMaxSize()) continue; if (selectedVariable.getAssignment() != null && selectedVariable.getCourse().getSize() + student.getStudent().getWeight() - selectedVariable.getAssignment().getStudent().getWeight() < selectedVariable.getCourse().getMaxSize() - m.getMinStudentWidth()) continue; */ double value = student.toDouble(); Set<CurValue> conflicts = m.conflictValues(student); for (CurValue conf: conflicts) { value -= conf.toDouble(); } if (bestStudents.isEmpty() || bestValue > value) { bestValue = value; bestStudents.clear(); bestStudents.add(student); } else if (bestValue == value) { bestStudents.add(student); } if (value != 0) allImprovingStudents.add(student); allStudents.add(student); } if (selectedVariable.getAssignment() != null) { double rnd = ToolBox.random(); if (rnd < 0.01) return ToolBox.random(allStudents); if (rnd < 0.10) return ToolBox.random(allImprovingStudents); } return ToolBox.random(bestStudents); } } --- NEW FILE: CurHillClimber.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.util.ArrayList; import java.util.List; import net.sf.cpsolver.ifs.heuristics.NeighbourSelection; import net.sf.cpsolver.ifs.model.Neighbour; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.solver.Solver; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.ToolBox; /** * @author Tomas Muller */ public class CurHillClimber implements NeighbourSelection<CurVariable, CurValue>{ protected CurHillClimber(DataProperties config) { } @Override public void init(Solver<CurVariable, CurValue> solver) { } @Override public Neighbour<CurVariable, CurValue> selectNeighbour( Solution<CurVariable, CurValue> solution) { CurModel model = (CurModel)solution.getModel(); List<CurValue> best = new ArrayList<CurValue>(); double bestValue = 0; int ix = ToolBox.random(model.variables().size()); for (int i = 0; i < model.variables().size(); i++) { CurVariable course = model.variables().get((ix + i) % model.variables().size()); if (!course.getCourse().isComplete() && course.getAssignment() != null) continue; int jx = ToolBox.random(course.values().size()); if (course.getAssignment() != null && course.getAssignment().getStudent().getCourses().size() <= model.getStudentLimit().getMinLimit()) continue; for (int j = 0; j < course.values().size(); j++) { CurValue student = course.values().get((j + jx) % course.values().size()); if (course.getCourse().getStudents().contains(student.getStudent())) continue; if (student.getStudent().getCourses().size() >= model.getStudentLimit().getMaxLimit()) continue; if (course.getCourse().getSize() + student.getStudent().getWeight() - (course.getAssignment() == null ? 0.0 : course.getAssignment().getStudent().getWeight()) > course.getCourse().getMaxSize()) continue; if (course.getAssignment() != null && course.getCourse().getSize() + student.getStudent().getWeight() - course.getAssignment().getStudent().getWeight() < course.getCourse().getMaxSize() - model.getMinStudentWidth()) continue; double value = student.toDouble(); if (best.isEmpty() || value < bestValue) { if (value < 0.0) return new CurSimpleAssignment(student); best.clear(); best.add(student); bestValue = value; } else if (value == bestValue) { best.add(student); } } } CurValue student = ToolBox.random(best); if (bestValue > 0.0 && !student.variable().getCourse().isComplete()) return null; return (student == null ? null : new CurSimpleAssignment(student)); } } --- NEW FILE: CurModel.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.io.FileOutputStream; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collection; import java.util.Comparator; import java.util.Hashtable; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; import net.sf.cpsolver.ifs.model.Model; import net.sf.cpsolver.ifs.model.Neighbour; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.solution.SolutionListener; import net.sf.cpsolver.ifs.solver.Solver; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.ToolBox; /** * @author Tomas Muller */ public class CurModel extends Model<CurVariable, CurValue> { private static Log sLog = LogFactory.getLog(CurModel.class); private static DecimalFormat sDF = new DecimalFormat("0.000"); private List<CurStudent> iStudents = new ArrayList<CurStudent>(); private Map<Long, CurCourse> iCourses = new Hashtable<Long, CurCourse>(); private List<CurCourse> iSwapableCourses = new ArrayList<CurCourse>(); private CurStudentLimit iStudentLimit = null; private double iMinStudentWeight = Float.MAX_VALUE, iMaxStudentWeight = 0.0; private double iAssignedWeight = 0.0, iBestAssignedWeight = 0.0, iMaxAssignedWeight = 0.0; public CurModel(Collection<CurStudent> students) { iStudents.addAll(students); iStudentLimit = new CurStudentLimit(0, Integer.MAX_VALUE); for (CurStudent student: getStudents()) { iMinStudentWeight = Math.min(iMinStudentWeight, student.getWeight()); iMaxStudentWeight = Math.max(iMaxStudentWeight, student.getWeight()); } } public double getMinStudentWidth() { return iMinStudentWeight; } public double getMaxStudentWidth() { return iMaxStudentWeight; } public void addCourse(Long courseId, String courseName, double size) { CurCourse course = new CurCourse(this, courseId, courseName, Math.min(iStudents.size(), (int)Math.round(size/getMinStudentWidth())), size); iCourses.put(courseId, course); if (course.getNrStudents() < iStudents.size()) iSwapableCourses.add(course); iMaxAssignedWeight += course.getOriginalMaxSize(); } public void setTargetShare(Long c1, Long c2, double share) { iCourses.get(c1).setTargetShare(c2, share); iCourses.get(c2).setTargetShare(c1, share); } public void setStudentLimits() { double nrStudentCourses = 0; for (CurCourse course: getCourses()) { nrStudentCourses += course.getOriginalMaxSize(); } double studentWeight = 0; for (CurStudent student: getStudents()) { studentWeight += student.getWeight(); } double avg = nrStudentCourses / studentWeight; int maxLimit = 1 + (int)Math.ceil(avg); int minLimit = (int)Math.floor(avg) - 1; sLog.debug("Student course limit <" + minLimit + "," + maxLimit + ">"); iStudentLimit = new CurStudentLimit(minLimit, maxLimit); addGlobalConstraint(iStudentLimit); } public CurStudentLimit getStudentLimit() { return iStudentLimit; } public Collection<CurCourse> getCourses() { return iCourses.values(); } public CurCourse getCourse(Long courseId) { return iCourses.get(courseId); } public List<CurStudent> getStudents() { return iStudents; } public List<CurCourse> getSwapCourses() { return iSwapableCourses; } @Override public Map<String, String> getInfo() { Map<String, String> ret = super.getInfo(); ret.put("Students", String.valueOf(getStudents().size())); ret.put("Courses", String.valueOf(getCourses().size())); double avgEnrollment = ((double)variables().size()) / getCourses().size(); double rmsEnrollment = 0.0; for (CurCourse c1: getCourses()) rmsEnrollment += (c1.getNrStudents() - avgEnrollment) * (c1.getNrStudents() - avgEnrollment); ret.put("Course size", sDF.format(avgEnrollment) + " ± " + sDF.format(Math.sqrt(rmsEnrollment / getCourses().size()))); int totalCourses = 0; for (CurStudent student: getStudents()) totalCourses += student.getCourses().size(); double avgCourses = ((double)totalCourses) / getStudents().size(); double rmsCourses = 0.0; for (CurStudent student: getStudents()) rmsCourses += (student.getCourses().size() - avgCourses) * (student.getCourses().size() - avgCourses); ret.put("Courses per student", sDF.format(avgCourses) + " ± " + sDF.format(Math.sqrt(rmsCourses / getStudents().size())) + " (limit: " + getStudentLimit().getMinLimit() + " .. " + getStudentLimit().getMaxLimit() + ")"); int totalShare = 0; double totalError = 0; double rmsError = 0.0; int pairs = 0; for (CurCourse c1: getCourses()) for (CurCourse c2: getCourses()) if (c1.getCourseId() < c2.getCourseId()) { double share = c1.share(c2); double target = c1.getTargetShare(c2.getCourseId()); totalError += Math.abs(share - target); rmsError += (share - target) * (share - target); pairs ++; totalShare += share; } ret.put("Errors", totalError + " (" + sDF.format(100.0 * totalError / totalShare) + "% of total share, avg: " + sDF.format(((double)totalError) / pairs) + ", rms: " + sDF.format(Math.sqrt(rmsError / pairs)) + ")"); ret.put("Assigned Student Weight", sDF.format(getAssignedWeight()) + "/" + sDF.format(getMaxWeight())); double totalStudentWeight = 0; for (CurStudent student: getStudents()) { totalStudentWeight += student.getWeight(); } double avgStudentWeight = totalStudentWeight / getStudents().size(); double rmsStudentWeight = 0; for (CurStudent student: getStudents()) { rmsStudentWeight += (student.getWeight() - avgStudentWeight) * (student.getWeight() - avgStudentWeight); } ret.put("Student Weight", sDF.format(getMinStudentWidth()) + " .. " + sDF.format(getMaxStudentWidth()) + " (avg: " + sDF.format(avgStudentWeight) + ", rms: " + sDF.format(Math.sqrt(rmsStudentWeight / getStudents().size())) + ")"); return ret; } public double getTotalValue() { double value = 0; for (CurCourse c1: iCourses.values()) for (CurCourse c2: iCourses.values()) if (c1.getCourseId() < c2.getCourseId()) value += c1.penalty(c2); return value; } public double getAssignedWeight() { return iAssignedWeight; } public double getMaxWeight() { return iMaxAssignedWeight; } public double getBestWeight() { return iBestAssignedWeight; } @Override public void saveBest() { super.saveBest(); iBestAssignedWeight = iAssignedWeight; } @Override public void clearBest() { super.clearBest(); iBestAssignedWeight = 0.0; } @Override public void afterAssigned(long iteration, CurValue value) { super.afterAssigned(iteration, value); iAssignedWeight += value.getStudent().getWeight(); } @Override public void afterUnassigned(long iteration, CurValue value) { super.afterUnassigned(iteration, value); iAssignedWeight -= value.getStudent().getWeight(); } public String toString() { return assignedVariables().size() + "/" + variables().size() + " V:" + sDF.format(getTotalValue()) + " A:" + sDF.format(getAssignedWeight()) + "/" + sDF.format(getMaxWeight()); } public void ifs() { net.sf.cpsolver.ifs.util.DataProperties cfg = new net.sf.cpsolver.ifs.util.DataProperties(); cfg.setProperty("Termination.Class", "org.unitime.timetable.solver.curricula.students.CurTermination"); cfg.setProperty("Termination.StopWhenComplete", "false"); cfg.setProperty("Termination.TimeOut", "60"); cfg.setProperty("Termination.MaxIdle", "1000"); cfg.setProperty("Comparator.Class", "org.unitime.timetable.solver.curricula.students.CurComparator"); cfg.setProperty("Variable.Class", "org.unitime.timetable.solver.curricula.students.CurVariableSelection"); cfg.setProperty("Value.Class", "org.unitime.timetable.solver.curricula.students.CurValueSelection"); cfg.setProperty("General.SaveBestUnassigned", "-1"); Solver<CurVariable, CurValue> solver = new Solver<CurVariable, CurValue>(cfg); solver.setInitalSolution(this); solver.currentSolution().addSolutionListener(new SolutionListener<CurVariable, CurValue>() { @Override public void solutionUpdated(Solution<CurVariable, CurValue> solution) { } @Override public void getInfo(Solution<CurVariable, CurValue> solution, Map<String, String> info, Collection<CurVariable> variables) { } @Override public void getInfo(Solution<CurVariable, CurValue> solution, Map<String, String> info) { } @Override public void bestSaved(Solution<CurVariable, CurValue> solution) { sLog.debug(solution.getModel().toString()+", i:" + solution.getIteration()); } @Override public void bestRestored(Solution<CurVariable, CurValue> solution) { } @Override public void bestCleared(Solution<CurVariable, CurValue> solution) { } }); solver.start(); try { solver.getSolverThread().join(); } catch (InterruptedException e) { } Solution<CurVariable, CurValue> solution = solver.lastSolution(); solution.restoreBest(); sLog.debug("Best solution found after " + solution.getBestTime() + " seconds (" + solution.getBestIteration() + " iterations)."); sLog.debug("Number of assigned variables is " + solution.getModel().assignedVariables().size()); sLog.debug("Total value of the solution is " + solution.getModel().getTotalValue()); } public void saveAsXml(Element root) { List<Long> courses = new ArrayList<Long>(); for (CurCourse course: getCourses()) { Element courseElement = root.addElement("course"); courseElement.addAttribute("id", course.getCourseId().toString()); courseElement.addAttribute("name", course.getCourseName()); courseElement.addAttribute("limit", String.valueOf(course.getOriginalMaxSize())); if (!courses.isEmpty()) { String share = ""; for (Long other: courses) { share += (share.isEmpty() ? "" : ",") + course.getTargetShare(other); } courseElement.addAttribute("share", share); } courses.add(course.getCourseId()); } for (CurStudent student: getStudents()) { Element studentElement = root.addElement("student"); studentElement.addAttribute("id", student.getStudentId().toString()); if (student.getWeight() != 1.0) studentElement.addAttribute("weight", String.valueOf(student.getWeight())); String courseIds = ""; for (CurCourse course: student.getCourses()) { courseIds += (courseIds.isEmpty() ? "" : ",") + course.getCourseId(); } studentElement.setText(courseIds); } } public static CurModel loadFromXml(Element root) { List<Element> studentElements = root.elements("student"); List<CurStudent> students = new ArrayList<CurStudent>(); for (Element studentElement: studentElements) { students.add(new CurStudent(Long.valueOf(studentElement.attributeValue("id")), Float.parseFloat(studentElement.attributeValue("weight", "1.0")))); } CurModel m = new CurModel(students); List<Long> courses = new ArrayList<Long>(); for (Iterator<Element> i = root.elementIterator("course"); i.hasNext();) { Element courseElement = i.next(); Long courseId = Long.valueOf(courseElement.attributeValue("id")); String courseName = courseElement.attributeValue("name"); double size = Float.parseFloat(courseElement.attributeValue("limit")); m.addCourse(courseId, courseName, size); if (!courses.isEmpty()) { String share[] = courseElement.attributeValue("share").split(","); for (int j = 0; j < courses.size(); j++) m.setTargetShare(courseId, courses.get(j), Float.parseFloat(share[j])); } courses.add(courseId); } int idx = 0; for (Element studentElement: studentElements) { CurStudent student = students.get(idx++); String courseIds = studentElement.getText(); if (courseIds != null && !courseIds.isEmpty()) { for (String courseId: courseIds.split(",")) { CurCourse course = m.getCourse(Long.valueOf(courseId)); CurVariable var = null; for (CurVariable v: course.variables()) if (v.getAssignment() == null) { var = v; break; } var.assign(0, new CurValue(var, student)); } } } return m; } public void naive(DataProperties cfg) { sLog.debug(" -- running naive"); int idle = 0, it = 0; double best = getTotalValue(); CurStudentSwap sw = new CurStudentSwap(cfg); Solution<CurVariable, CurValue> solution = new Solution<CurVariable, CurValue>(this); while (!getSwapCourses().isEmpty() && idle < 1000) { Neighbour<CurVariable, CurValue> n = sw.selectNeighbour(solution); if (n == null) break; double value = n.value(); if (value < 0.0) { idle = 0; n.assign(it); } else if (value == 0.0) { n.assign(it); } if (getTotalValue() < best) { best = getTotalValue(); sLog.debug(" -- best value: " + this); } it++; idle++; } sLog.debug(" -- final value: " + this); } public void hc(DataProperties cfg) { sLog.debug(" -- running hill climber"); int it = 0, idle = 0; double total = getTotalValue(); double best = total; CurHillClimber hc = new CurHillClimber(cfg); Solution<CurVariable, CurValue> solution = new Solution<CurVariable, CurValue>(this); while (idle < 1000) { Neighbour<CurVariable, CurValue> n = hc.selectNeighbour(solution); if (n == null) break; if (unassignedVariables().isEmpty() && n.value() >= -1e7f) break; total += n.value(); n.assign(it); if (total < best) { best = total; idle = 0; sLog.debug(" -- best value: " + this); } else { idle++; } it++; } sLog.debug(" -- final value: " + this); } public void deluge(DataProperties cfg) { sLog.debug(" -- running great deluge"); int it = 0; double total = getTotalValue(); double bound = 1.25 * total; double best = getTotalValue(); CurStudentSwap sw = new CurStudentSwap(cfg); Solution<CurVariable, CurValue> solution = new Solution<CurVariable, CurValue>(this); saveBest(); while (!getSwapCourses().isEmpty() && bound > 0.75 * total && total > 0) { Neighbour<CurVariable, CurValue> n = sw.selectNeighbour(solution); if (n != null) { double value = n.value(); if (value <= 0.0 || total + value < bound) { n.assign(it); if (total + value < best) { best = total + value; saveBest(); sLog.debug(" -- best value: " + this + ", bound: " + bound); } total += value; } } bound *= 0.999999; it++; } restoreBest(); sLog.debug(" -- final value: " + this); } public void fast(DataProperties cfg) { sLog.debug(" -- running fast"); int idle = 0, it = 0; double total = getTotalValue(); double best = total; CurSimpleMove m = new CurSimpleMove(cfg); Solution<CurVariable, CurValue> solution = new Solution<CurVariable, CurValue>(this); while (idle < 1000) { Neighbour<CurVariable, CurValue> n = m.selectNeighbour(solution); if (n != null) { double value = n.value(); if (value < 0.0) { idle = 0; n.assign(it); total += value; } else if (value == 0.0) { n.assign(it); } } if (total < best) { best = total; sLog.debug(" -- best value: " + this); } it++; idle++; } sLog.debug(" -- final value: " + this); } public void solve() { sLog.debug(" -- setting up the solver"); DataProperties cfg = new DataProperties(); CurVariableSelection var = new CurVariableSelection(cfg); CurValueSelection vs = new CurValueSelection(cfg); Solution<CurVariable, CurValue> solution = new Solution<CurVariable, CurValue>(this); sLog.debug(" -- creating initial assignment"); while (!unassignedVariables().isEmpty()) { CurVariable course = var.selectVariable(solution); if (course.getCourse().isComplete()) { sLog.debug(" -- all complete"); break; } CurValue student = vs.selectValueSlow(solution, course); if (student == null) { sLog.debug(" -- no student for " + course.getCourse().getCourseName()); break; } student.variable().assign(solution.getIteration(), student); } for (CurCourse course: getCourses()) { if (!course.isComplete()) { sLog.debug(" -- incomplete " + course.getCourseName() + ": " + getCourse(course.getCourseId()).getStudents() + " (" + course.getSize() + "/" + course.getOriginalMaxSize() + ")"); } } sLog.debug(" -- initial value: " + this); hc(cfg); // or fast(cfg); deluge(cfg); // or naive(cfg); } public boolean isSameModel(Object o) { if (o == null || !(o instanceof CurModel)) return false; CurModel m = (CurModel)o; if (getStudents().size() != m.getStudents().size()) return false; if (getStudentLimit().getMaxLimit() != m.getStudentLimit().getMaxLimit()) return false; if (getStudentLimit().getMinLimit() != m.getStudentLimit().getMinLimit()) return false; if (getMinStudentWidth() != m.getMinStudentWidth()) return false; if (getCourses().size() != m.getCourses().size()) return false; students: for (CurStudent s: getStudents()) { if (s.getStudentId() != null && s.getStudentId() >= 0) for (CurStudent z: m.getStudents()) { if (z.getStudentId().equals(s.getStudentId()) && z.getWeight() == s.getWeight()) continue students; } return false; } students: for (CurStudent s: m.getStudents()) { if (s.getStudentId() != null && s.getStudentId() >= 0) for (CurStudent z: getStudents()) { if (z.getStudentId().equals(s.getStudentId()) && z.getWeight() == s.getWeight()) continue students; } return false; } for (int idx = 0; idx < getStudents().size(); idx++) { CurStudent s = getStudents().get(idx); if (s.getStudentId() != null && s.getStudentId() >= 0) continue; if (s.getWeight() != m.getStudents().get(idx).getWeight()) return false; } for (CurCourse c1: getCourses()) { CurCourse x1 = m.getCourse(c1.getCourseId()); if (x1 == null || x1.getNrStudents() != c1.getNrStudents()) return false; for (CurCourse c2: getCourses()) if (c1.getCourseId() < c2.getCourseId() && Math.abs(c1.getTargetShare(c2.getCourseId()) - x1.getTargetShare(c2.getCourseId())) > 0.001) { return false; } } return true; } public static void main(String[] args) { try { List<CurStudent> students = new ArrayList<CurStudent>(); for (int i = 0; i < 20; i++) students.add(new CurStudent(new Long(1 + i), (i < 10 ? 0.5f: 2f))); CurModel m = new CurModel(students); for (int i = 1; i <= 10; i++) m.addCourse((long)i, "C" + i, 2 * i); for (int i = 1; i < 10; i++) for (int j = i + 1; j <= 10; j++) m.setTargetShare((long)i, (long)j, i); m.setStudentLimits(); Document d0 = DocumentHelper.createDocument(); m.saveAsXml(d0.addElement("curriculum")); sLog.info(d0.asXML()); CurModel n = CurModel.loadFromXml((new SAXReader()).read("/Users/muller/solution.xml").getRootElement()); n.setStudentLimits(); sLog.info("Same model: " + m.isSameModel(n) + ", " + n.isSameModel(m)); sLog.info("Loaded: " + ToolBox.dict2string(m.getInfo(), 2)); m.solve(); sLog.info("Solution: " + ToolBox.dict2string(m.getInfo(), 2)); Document d1 = DocumentHelper.createDocument(); m.saveAsXml(d1.addElement("curriculum")); sLog.info(d1.asXML()); TreeSet<CurCourse> courses = new TreeSet<CurCourse>(new Comparator<CurCourse>() { public int compare(CurCourse c1, CurCourse c2) { int cmp = c1.getCourseName().compareTo(c2.getCourseName()); if (cmp != 0) return cmp; return c1.getCourseId().compareTo(c2.getCourseId()); } }); courses.addAll(m.getCourses()); int penalty = 0; for (CurCourse course: courses) { sLog.info(course.getCourseName() + ": " + m.getCourse(course.getCourseId()).getStudents() + " (" + course.getSize() + "/" + course.getOriginalMaxSize() + ")"); for (CurCourse other: courses) { if (other.getCourseId() <= course.getCourseId()) continue; double share = course.share(other); double target = course.getTargetShare(other.getCourseId()); sLog.info(" " + other.getCourseName() + ": share=" + share + ", target=" + target + ", penalty=" + Math.abs(target - share)); penalty += Math.abs(target - share); } } sLog.info("Total penalty: " + penalty); Document doc = DocumentHelper.createDocument(); m.saveAsXml(doc.addElement("curriculum")); FileOutputStream fos = new FileOutputStream("/Users/muller/solution.xml"); (new XMLWriter(fos, OutputFormat.createPrettyPrint())).write(doc); fos.flush(); fos.close(); } catch (Exception e) { e.printStackTrace(); } } } --- NEW FILE: CurComparator.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.solution.SolutionComparator; import net.sf.cpsolver.ifs.util.DataProperties; /** * @author Tomas Muller */ public class CurComparator implements SolutionComparator<CurVariable, CurValue>{ public CurComparator(DataProperties config) { } @Override public boolean isBetterThanBestSolution(Solution<CurVariable, CurValue> currentSolution) { CurModel m = (CurModel)currentSolution.getModel(); if (m.getAssignedWeight() > m.getBestWeight() + m.getMinStudentWidth() / 2.0) return true; if (m.getAssignedWeight() < m.getBestWeight() - m.getMinStudentWidth() / 2.0) return false; return m.getTotalValue() < currentSolution.getBestValue(); } } --- NEW FILE: CurVariableSelection.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.util.ArrayList; import java.util.List; import net.sf.cpsolver.ifs.heuristics.RouletteWheelSelection; import net.sf.cpsolver.ifs.heuristics.VariableSelection; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.solver.Solver; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.ToolBox; /** * @author Tomas Muller */ public class CurVariableSelection implements VariableSelection<CurVariable, CurValue>{ RouletteWheelSelection<CurVariable> iWheel = null; public CurVariableSelection(DataProperties p) {} @Override public void init(Solver<CurVariable, CurValue> solver) { } @Override public CurVariable selectVariable(Solution<CurVariable, CurValue> solution) { CurModel m = (CurModel)solution.getModel(); if (!m.unassignedVariables().isEmpty()) { List<CurVariable> best = new ArrayList<CurVariable>(); double bestValue = 0.0; for (CurVariable course: m.unassignedVariables()) { if (course.getCourse().isComplete()) continue; double value = course.getCourse().getMaxSize() - course.getCourse().getSize(); if (best.isEmpty() || bestValue < value) { best.clear(); best.add(course); bestValue = value; } else if (bestValue == value) { best.add(course); } } if (!best.isEmpty()) return ToolBox.random(best); } if (iWheel == null || !iWheel.hasMoreElements()) { iWheel = new RouletteWheelSelection<CurVariable>(); for (CurVariable course: m.assignedVariables()) { double penalty = course.getAssignment().toDouble(); if (course.getCourse().getStudents().size() == m.getStudents().size()) continue; if (penalty != 0) iWheel.add(course, penalty); } } return iWheel.nextElement(); } } --- NEW FILE: CurValue.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import net.sf.cpsolver.ifs.model.Value; /** * @author Tomas Muller */ public class CurValue extends Value<CurVariable, CurValue> { private CurStudent iStudent; public CurValue(CurVariable course, CurStudent student) { super(course); iStudent = student; } public CurStudent getStudent() { return iStudent; } public double toDouble() { if (variable().getAssignment() == null) return variable().getCourse().penalty(iStudent); return variable().getCourse().penalty(iStudent, variable().getAssignment().getStudent()); } } --- NEW FILE: CurTermination.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.termination.GeneralTerminationCondition; import net.sf.cpsolver.ifs.termination.TerminationCondition; import net.sf.cpsolver.ifs.util.DataProperties; /** * @author Tomas Muller */ public class CurTermination implements TerminationCondition<CurVariable, CurValue>{ protected static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger.getLogger(GeneralTerminationCondition.class); private int iMaxIter; private double iTimeOut; private boolean iStopWhenComplete; private long iMaxIdle; public CurTermination(DataProperties properties) { iMaxIter = properties.getPropertyInt("Termination.MaxIters", -1); iTimeOut = properties.getPropertyDouble("Termination.TimeOut", -1.0); iStopWhenComplete = properties.getPropertyBoolean("Termination.StopWhenComplete", false); iMaxIdle = properties.getPropertyLong("Termination.MaxIdle", 10000); } public boolean canContinue(Solution<CurVariable, CurValue> currentSolution) { if (iMaxIter >= 0 && currentSolution.getIteration() >= iMaxIter) { sLogger.info("Maximum number of iteration reached."); return false; } if (iTimeOut >= 0 && currentSolution.getTime() > iTimeOut) { sLogger.info("Timeout reached."); return false; } if (iStopWhenComplete || (iMaxIter < 0 && iTimeOut < 0)) { boolean ret = (currentSolution.getModel().nrUnassignedVariables() != 0); if (!ret) sLogger.info("Complete solution found."); return ret; } if (currentSolution.getIteration() - currentSolution.getBestIteration() > iMaxIdle) { sLogger.info("Maximum idle iterations reached."); return false; } return true; } } --- NEW FILE: CurStudentLimit.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import java.util.ArrayList; import java.util.List; import java.util.Set; import net.sf.cpsolver.ifs.model.GlobalConstraint; import net.sf.cpsolver.ifs.util.ToolBox; /** * @author Tomas Muller */ public class CurStudentLimit extends GlobalConstraint<CurVariable, CurValue> { private int iMinLimit = 0, iMaxLimit = 0; public CurStudentLimit(int minLimit, int maxLimit) { iMinLimit = minLimit; iMaxLimit = maxLimit; } public int getMinLimit() { return iMinLimit; } public int getMaxLimit() { return iMaxLimit; } @Override public void computeConflicts(CurValue value, Set<CurValue> conflicts) { int courses = value.getStudent().getCourses().size(); if (!value.getStudent().getCourses().contains(value.variable().getCourse())) courses++; for (CurValue conflict: conflicts) { if (conflict.getStudent().equals(value.getStudent()) && value.getStudent().getCourses().contains(conflict.variable().getCourse())) courses--; } if (courses > iMaxLimit) { List<CurValue> adepts = new ArrayList<CurValue>(); for (CurCourse course: value.getStudent().getCourses()) { if (course.equals(value.variable().getCourse())) continue; CurValue adept = course.getValue(value.getStudent()); if (conflicts.contains(adept)) continue; adepts.add(adept); } conflicts.add(ToolBox.random(adepts)); } } public String toString() { return "StudentLimit<" + getMinLimit() + "," + getMaxLimit() + ">"; } } --- NEW FILE: CurSimpleMove.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import net.sf.cpsolver.ifs.heuristics.NeighbourSelection; import net.sf.cpsolver.ifs.model.Neighbour; import net.sf.cpsolver.ifs.solution.Solution; import net.sf.cpsolver.ifs.solver.Solver; import net.sf.cpsolver.ifs.util.DataProperties; /** * @author Tomas Muller */ public class CurSimpleMove implements NeighbourSelection<CurVariable, CurValue>{ private CurVariableSelection iVariableSelection; private CurValueSelection iValueSelection; protected CurSimpleMove(DataProperties config) { iVariableSelection = new CurVariableSelection(config); iValueSelection = new CurValueSelection(config); } @Override public void init(Solver<CurVariable, CurValue> solver) { } @Override public Neighbour<CurVariable, CurValue> selectNeighbour( Solution<CurVariable, CurValue> solution) { CurVariable var = iVariableSelection.selectVariable(solution); if (var == null) return null; CurValue val = iValueSelection.selectValueFast(solution, var); return (val == null ? null : new CurSimpleAssignment(val)); } } --- NEW FILE: CurSimpleAssignment.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula.students; import net.sf.cpsolver.ifs.model.Neighbour; /** * @author Tomas Muller */ public class CurSimpleAssignment extends Neighbour<CurVariable, CurValue> { private CurValue iNewValue; public CurSimpleAssignment(CurValue newValue) { iNewValue = newValue; } @Override public void assign(long iteration) { iNewValue.variable().assign(iteration, iNewValue); } @Override public double value() { return iNewValue.variable().getCourse().... [truncated message content] |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/server/custom In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/server/custom Added Files: SectionLimitProvider.java SectionUrlProvider.java CourseDetailsProvider.java CustomSectionNames.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: SectionLimitProvider.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server.custom; import java.util.ArrayList; import java.util.Hashtable; import org.unitime.timetable.gwt.server.AcademicSessionInfo; /** * @author Tomas Muller */ public interface SectionLimitProvider { public int[] getSectionLimit(AcademicSessionInfo session, Long courseId, Long classId, String customClassSuffix); public Hashtable<Long, int[]> getSectionLimits(AcademicSessionInfo session, Long courseId, ArrayList<Long> classIds, CustomSectionNames names); public Hashtable<Long, int[]> getSectionLimitsFromCache(AcademicSessionInfo session, Long courseId, ArrayList<Long> classIds, CustomSectionNames names); } --- NEW FILE: CourseDetailsProvider.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server.custom; import org.unitime.timetable.gwt.server.AcademicSessionInfo; import org.unitime.timetable.gwt.shared.SectioningException; /** * @author Tomas Muller */ public interface CourseDetailsProvider { public String getDetails(AcademicSessionInfo session, String subject, String courseNbr) throws SectioningException; } --- NEW FILE: CustomSectionNames.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server.custom; import org.unitime.timetable.gwt.server.AcademicSessionInfo; /** * @author Tomas Muller */ public interface CustomSectionNames { public void update(AcademicSessionInfo session); public String getClassSuffix(Long sessionId, Long courseId, Long classId); } --- NEW FILE: SectionUrlProvider.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server.custom; import java.net.URL; import org.unitime.timetable.gwt.server.AcademicSessionInfo; /** * @author Tomas Muller */ public interface SectionUrlProvider { public URL getSectionUrl(AcademicSessionInfo session, Long courseId, Long classId, String customClassSuffix); } |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:10:56
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/solver/curricula In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/solver/curricula Added Files: CurriculaCourseDemands.java StudentCourseRequests.java ProjectedStudentCourseDemands.java CurriculaLastLikeCourseDemands.java StudentCourseDemands.java EnrolledStudentCourseDemands.java LastLikeStudentCourseDemands.java WeightedLastLikeStudentCourseDemands.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: LastLikeStudentCourseDemands.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.Session; import org.unitime.timetable.model.SubjectArea; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.Progress; /** * @author Tomas Muller */ public class LastLikeStudentCourseDemands implements StudentCourseDemands { protected org.hibernate.Session iHibSession; protected Hashtable<String, Set<WeightedStudentId>> iDemandsForPemId = new Hashtable<String, Set<WeightedStudentId>>(); protected Hashtable<Long, Hashtable<String, Set<WeightedStudentId>>> iDemandsForSubjectCourseNbr = new Hashtable<Long, Hashtable<String,Set<WeightedStudentId>>>(); protected Hashtable<Long, Set<WeightedCourseOffering>> iStudentRequests = null; protected Long iSessionId = null; public LastLikeStudentCourseDemands(DataProperties properties) { } public boolean isMakingUpStudents() { return false; } public boolean canUseStudentClassEnrollmentsAsSolution() { return false; } public boolean isWeightStudentsToFillUpOffering() { return false; } public void init(org.hibernate.Session hibSession, Progress progress, Session session, Set<InstructionalOffering> offerings) { iHibSession = hibSession; iSessionId = session.getUniqueId(); } protected Hashtable<String, Set<WeightedStudentId>> loadSubject(SubjectArea subject) { Hashtable<String, Set<WeightedStudentId>> demandsForCourseNbr = new Hashtable<String, Set<WeightedStudentId>>(); iDemandsForSubjectCourseNbr.put(subject.getUniqueId(), demandsForCourseNbr); for (Object[] d: (List<Object[]>)iHibSession.createQuery("select d.courseNbr, d.student.uniqueId, d.coursePermId "+ "from LastLikeCourseDemand d where d.subjectArea.uniqueId=:subjectAreaId") .setLong("subjectAreaId", subject.getUniqueId()).setCacheable(true).list()) { String courseNbr = (String)d[0]; WeightedStudentId studentId = new WeightedStudentId((Long)d[1]); String coursePermId = (String)d[2]; Set<WeightedStudentId> studentIds = demandsForCourseNbr.get(courseNbr); if (studentIds == null) { studentIds = new HashSet<WeightedStudentId>(); demandsForCourseNbr.put(courseNbr, studentIds); } studentIds.add(studentId); if (coursePermId!=null) { studentIds = iDemandsForPemId.get(coursePermId); if (studentIds==null) { studentIds = new HashSet<WeightedStudentId>(); iDemandsForPemId.put(coursePermId, studentIds); } studentIds.add(studentId); } } return demandsForCourseNbr; } public Set<WeightedStudentId> getDemands(CourseOffering course) { Hashtable<String, Set<WeightedStudentId>> demandsForCourseNbr = iDemandsForSubjectCourseNbr.get(course.getSubjectArea().getUniqueId()); if (demandsForCourseNbr == null) { demandsForCourseNbr = loadSubject(course.getSubjectArea()); } Set<WeightedStudentId> studentIds = null; if (course.getPermId() != null) studentIds = iDemandsForPemId.get(course.getPermId()); if (studentIds == null) studentIds = demandsForCourseNbr.get(course.getCourseNbr()); if (course.getDemandOffering() != null && !course.getDemandOffering().equals(course)) { if (studentIds == null) studentIds = getDemands(course.getDemandOffering()); else { studentIds = new HashSet<WeightedStudentId>(studentIds); studentIds.addAll(getDemands(course.getDemandOffering())); } } if (studentIds == null) studentIds = new HashSet<WeightedStudentId>(); return studentIds; } public Set<WeightedCourseOffering> getCourses(Long studentId) { if (iStudentRequests == null) { iStudentRequests = new Hashtable<Long, Set<WeightedCourseOffering>>(); for (Object[] o : (List<Object[]>)iHibSession.createQuery( "select s.uniqueId, co " + "from LastLikeCourseDemand x inner join x.student s, CourseOffering co where " + "x.subjectArea.session.uniqueId = :sessionId and "+ "co.subjectArea.uniqueId = x.subjectArea.uniqueId and " + "((x.coursePermId is not null and co.permId=x.coursePermId) or (x.coursePermId is null and co.courseNbr=x.courseNbr))") .setLong("sessionId", iSessionId) .setCacheable(true).list()) { Long sid = (Long)o[0]; CourseOffering co = (CourseOffering)o[1]; Set<WeightedCourseOffering> courses = iStudentRequests.get(sid); if (courses == null) { courses = new HashSet<WeightedCourseOffering>(); iStudentRequests.put(sid, courses); } courses.add(new WeightedCourseOffering(co)); } } return iStudentRequests.get(studentId); } } --- NEW FILE: ProjectedStudentCourseDemands.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.Progress; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.CurriculumProjectionRule; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.Session; import org.unitime.timetable.model.SubjectArea; /** * @author Tomas Muller */ public class ProjectedStudentCourseDemands extends LastLikeStudentCourseDemands { private Hashtable<String,Hashtable<String,Hashtable<String, Float>>> iAreaClasfMajor2Proj = new Hashtable<String, Hashtable<String,Hashtable<String,Float>>>(); private Progress iProgress; public ProjectedStudentCourseDemands(DataProperties properties) { super(properties); } public void init(org.hibernate.Session hibSession, Progress progress, Session session, Set<InstructionalOffering> offerings) { super.init(hibSession, progress, session, offerings); iProgress = progress; progress.setPhase("Loading curriculum projections", 1); for (CurriculumProjectionRule rule: (List<CurriculumProjectionRule>)hibSession.createQuery( "select r from CurriculumProjectionRule r where r.academicArea.session.uniqueId=:sessionId") .setLong("sessionId", session.getUniqueId()).setCacheable(true).list()) { String areaAbbv = rule.getAcademicArea().getAcademicAreaAbbreviation(); String majorCode = (rule.getMajor() == null ? "" : rule.getMajor().getCode()); String clasfCode = rule.getAcademicClassification().getCode(); Float projection = rule.getProjection(); Hashtable<String,Hashtable<String, Float>> clasf2major2proj = iAreaClasfMajor2Proj.get(areaAbbv); if (clasf2major2proj == null) { clasf2major2proj = new Hashtable<String, Hashtable<String,Float>>(); iAreaClasfMajor2Proj.put(areaAbbv, clasf2major2proj); } Hashtable<String, Float> major2proj = clasf2major2proj.get(clasfCode); if (major2proj == null) { major2proj = new Hashtable<String, Float>(); clasf2major2proj.put(clasfCode, major2proj); } major2proj.put(majorCode, projection); } progress.incProgress(); } public float getProjection(String areaAbbv, String clasfCode, String majorCode) { if (iAreaClasfMajor2Proj.isEmpty()) return 1.0f; Hashtable<String,Hashtable<String, Float>> clasf2major2proj = (areaAbbv == null ? null : iAreaClasfMajor2Proj.get(areaAbbv)); if (clasf2major2proj == null || clasf2major2proj.isEmpty()) return 1.0f; Hashtable<String, Float> major2proj = (clasfCode == null ? null : clasf2major2proj.get(clasfCode)); if (major2proj == null) return 1.0f; Float projection = (majorCode == null ? null : major2proj.get(majorCode)); if (projection == null) projection = major2proj.get(""); return (projection == null ? 1.0f : projection); } @Override protected Hashtable<String, Set<WeightedStudentId>> loadSubject(SubjectArea subject) { Hashtable<String, Set<WeightedStudentId>> demandsForCourseNbr = new Hashtable<String, Set<WeightedStudentId>>(); iDemandsForSubjectCourseNbr.put(subject.getUniqueId(), demandsForCourseNbr); for (Object[] d: (List<Object[]>)iHibSession.createQuery("select d.courseNbr, s.uniqueId, d.coursePermId, "+ "a.academicAreaAbbreviation, f.code, m.code " + "from LastLikeCourseDemand d inner join d.student s left outer join s.academicAreaClassifications c left outer join s.posMajors m " + "left outer join c.academicArea a left outer join c.academicClassification f where " + "d.subjectArea.uniqueId=:subjectAreaId") .setLong("subjectAreaId", subject.getUniqueId()).setCacheable(true).list()) { String courseNbr = (String)d[0]; String coursePermId = (String)d[2]; String areaAbbv = (String)d[3]; String clasfCode = (String)d[4]; String majorCode = (String)d[5]; WeightedStudentId studentId = new WeightedStudentId((Long)d[1], getProjection(areaAbbv, clasfCode, majorCode)); studentId.setStats(areaAbbv, clasfCode, majorCode); studentId.setCurriculum(areaAbbv == null ? null : majorCode == null ? areaAbbv : areaAbbv + "/" + majorCode); Set<WeightedStudentId> studentIds = demandsForCourseNbr.get(courseNbr); if (studentIds == null) { studentIds = new HashSet<WeightedStudentId>(); demandsForCourseNbr.put(courseNbr, studentIds); } studentIds.add(studentId); if (coursePermId!=null) { studentIds = iDemandsForPemId.get(coursePermId); if (studentIds==null) { studentIds = new HashSet<WeightedStudentId>(); iDemandsForPemId.put(coursePermId, studentIds); } studentIds.add(studentId); } } if (demandsForCourseNbr.isEmpty()) { iProgress.warn("There are no projected demands for " + subject.getSubjectAreaAbbreviation()+ ", using last-like course demands instead."); return super.loadSubject(subject); } return demandsForCourseNbr; } public Set<WeightedCourseOffering> getCourses(Long studentId) { if (iStudentRequests == null) { iStudentRequests = new Hashtable<Long, Set<WeightedCourseOffering>>(); for (Object[] o : (List<Object[]>)iHibSession.createQuery( "select s.uniqueId, co, " + "a.academicAreaAbbreviation, f.code, m.code " + "from LastLikeCourseDemand x inner join x.student s left outer join s.academicAreaClassifications c left outer join s.posMajors m " + "left outer join c.academicArea a left outer join c.academicClassification f, CourseOffering co where " + "x.subjectArea.session.uniqueId = :sessionId and "+ "co.subjectArea.uniqueId = x.subjectArea.uniqueId and " + "((x.coursePermId is not null and co.permId=x.coursePermId) or (x.coursePermId is null and co.courseNbr=x.courseNbr))") .setLong("sessionId", iSessionId) .setCacheable(true).list()) { Long sid = (Long)o[0]; CourseOffering co = (CourseOffering)o[1]; String areaAbbv = (String)o[2]; String clasfCode = (String)o[3]; String majorCode = (String)o[4]; Set<WeightedCourseOffering> courses = iStudentRequests.get(sid); if (courses == null) { courses = new HashSet<WeightedCourseOffering>(); iStudentRequests.put(sid, courses); } courses.add(new WeightedCourseOffering(co, getProjection(areaAbbv, clasfCode, majorCode))); } } return iStudentRequests.get(studentId); } } --- NEW FILE: CurriculaLastLikeCourseDemands.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.Set; import net.sf.cpsolver.ifs.model.Constraint; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.IdGenerator; import net.sf.cpsolver.ifs.util.Progress; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.hibernate.Session; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.Curriculum; import org.unitime.timetable.model.CurriculumClassification; import org.unitime.timetable.model.CurriculumCourse; import org.unitime.timetable.model.CurriculumCourseGroup; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.PosMajor; import org.unitime.timetable.solver.curricula.students.CurCourse; import org.unitime.timetable.solver.curricula.students.CurModel; import org.unitime.timetable.solver.curricula.students.CurStudent; import org.unitime.timetable.solver.curricula.students.CurValue; import org.unitime.timetable.solver.curricula.students.CurVariable; /** * @author Tomas Muller */ public class CurriculaLastLikeCourseDemands implements StudentCourseDemands { private static Log sLog = LogFactory.getLog(CurriculaLastLikeCourseDemands.class); private ProjectedStudentCourseDemands iProjectedDemands; private IdGenerator iLastStudentId = new IdGenerator(); private Hashtable<Long, Set<WeightedStudentId>> iDemands = new Hashtable<Long, Set<WeightedStudentId>>(); private Hashtable<Long, Set<WeightedCourseOffering>> iStudentRequests = new Hashtable<Long, Set<WeightedCourseOffering>>(); private Hashtable<Long, Hashtable<String, Set<String>>> iLoadedCurricula = new Hashtable<Long,Hashtable<String, Set<String>>>(); private HashSet<Long> iCheckedCourses = new HashSet<Long>(); private boolean iIncludeOtherStudents = true; public CurriculaLastLikeCourseDemands(DataProperties config) { iProjectedDemands = new ProjectedStudentCourseDemands(config); iIncludeOtherStudents = config.getPropertyBoolean("CurriculaCourseDemands.IncludeOtherStudents", iIncludeOtherStudents); } @Override public void init(Session hibSession, Progress progress, org.unitime.timetable.model.Session session, Set<InstructionalOffering> offerings) { iProjectedDemands.init(hibSession, progress, session, offerings); List<Curriculum> curricula = null; if (offerings != null && offerings.size() <= 1000) { String courses = ""; for (InstructionalOffering offering: offerings) for (CourseOffering course: offering.getCourseOfferings()) { if (!courses.isEmpty()) courses += ","; courses += course.getUniqueId(); } curricula = hibSession.createQuery( "select distinct c from CurriculumCourse cc inner join cc.classification.curriculum c where " + "c.academicArea.session.uniqueId = :sessionId and cc.course.uniqueId in (" + courses + ")") .setLong("sessionId", session.getUniqueId()).list(); } else { curricula = hibSession.createQuery( "select c from Curriculum c where c.academicArea.session.uniqueId = :sessionId") .setLong("sessionId", session.getUniqueId()).list(); } progress.setPhase("Loading curricula", curricula.size()); for (Curriculum curriculum: curricula) { Hashtable<String, Hashtable<CourseOffering, Set<WeightedStudentId>>> lastLike = loadClasfCourseMajor2ll(hibSession, curriculum); for (CurriculumClassification clasf: curriculum.getClassifications()) { init(hibSession, clasf, lastLike.get(clasf.getAcademicClassification().getCode())); } progress.incProgress(); } } private Hashtable<String, Hashtable<CourseOffering, Set<WeightedStudentId>>> loadClasfCourseMajor2ll(org.hibernate.Session hibSession, Curriculum curriculum) { String majorCodes = ""; for (PosMajor major: curriculum.getMajors()) { if (!majorCodes.isEmpty()) majorCodes += ","; majorCodes += "'" + major.getCode() + "'"; } Hashtable<String, Hashtable<CourseOffering, Set<WeightedStudentId>>> clasf2courseLl = new Hashtable<String, Hashtable<CourseOffering, Set<WeightedStudentId>>>(); for (Object[] o : (List<Object[]>)hibSession.createQuery( "select f.code, co, m.code, s.uniqueId " + "from LastLikeCourseDemand x inner join x.student s inner join s.academicAreaClassifications a inner join a.academicClassification f " + "inner join s.posMajors m, CourseOffering co where " + "x.subjectArea.session.uniqueId = :sessionId and "+ "a.academicArea.academicAreaAbbreviation = :acadAbbv " + (majorCodes.isEmpty() ? "" : "and m.code in (" + majorCodes + ") ") + "and co.subjectArea.uniqueId = x.subjectArea.uniqueId and " + "((x.coursePermId is not null and co.permId=x.coursePermId) or (x.coursePermId is null and co.courseNbr=x.courseNbr))") .setLong("sessionId", curriculum.getDepartment().getSession().getUniqueId()) .setString("acadAbbv", curriculum.getAcademicArea().getAcademicAreaAbbreviation()) .setCacheable(true).list()) { String clasfCode = (String)o[0]; CourseOffering course = (CourseOffering)o[1]; String majorCode = (String)o[2]; Long studentId = (Long)o[3]; WeightedStudentId student = new WeightedStudentId(studentId, iProjectedDemands.getProjection(curriculum.getAcademicArea().getAcademicAreaAbbreviation(), clasfCode, majorCode)); student.setStats(curriculum.getAcademicArea().getAcademicAreaAbbreviation(), clasfCode, majorCode); student.setCurriculum(curriculum.getAbbv()); Hashtable<CourseOffering, Set<WeightedStudentId>> course2ll = clasf2courseLl.get(clasfCode); if (course2ll == null) { course2ll = new Hashtable<CourseOffering, Set<WeightedStudentId>>(); clasf2courseLl.put(clasfCode, course2ll); } Set<WeightedStudentId> students = course2ll.get(course); if (students == null) { students = new HashSet<WeightedStudentId>(); course2ll.put(course, students); } students.add(student); } return clasf2courseLl; } protected void init(org.hibernate.Session hibSession, CurriculumClassification clasf, Hashtable<CourseOffering, Set<WeightedStudentId>> lastLikeStudents) { sLog.debug("Processing " + clasf.getCurriculum().getAbbv() + " " + clasf.getName() + " ... (" + clasf.getNrStudents() + " students, " + clasf.getCourses().size() + " courses)"); Hashtable<WeightedStudentId, Set<CourseOffering>> students = new Hashtable<WeightedStudentId, Set<CourseOffering>>(); if (lastLikeStudents != null) { for (Map.Entry<CourseOffering, Set<WeightedStudentId>> entry: lastLikeStudents.entrySet()) { for (WeightedStudentId student: entry.getValue()) { Set<CourseOffering> courses = students.get(student); if (courses == null) { courses = new HashSet<CourseOffering>(); students.put(student, courses); } courses.add(entry.getKey()); } } } float totalWeight = 0; for (WeightedStudentId student: students.keySet()) totalWeight += student.getWeight(); sLog.debug(" last-like students: " + totalWeight + ", target: " + clasf.getNrStudents()); if (2 * totalWeight < clasf.getNrStudents()) { // students are less than 1/2 of the requested size -> make up some students int studentsToMakeUp = Math.round(clasf.getNrStudents() - totalWeight); sLog.debug(" making up " + studentsToMakeUp + " students"); for (int i = 0; i < studentsToMakeUp; i++) { WeightedStudentId student = new WeightedStudentId(-iLastStudentId.newId()); student.setStats(clasf.getCurriculum().getAcademicArea().getAcademicAreaAbbreviation(), clasf.getAcademicClassification().getCode(), null); students.put(student, new HashSet<CourseOffering>()); } } else { // change weights to fit the requested size float factor = clasf.getNrStudents() / totalWeight; sLog.debug(" changing student weight " + factor + " times"); for (WeightedStudentId student: students.keySet()) student.setWeight(student.getWeight() * factor); } // Setup model List<CurStudent> curStudents = new ArrayList<CurStudent>(); Hashtable<Long, WeightedStudentId> studentIds = new Hashtable<Long, WeightedStudentId>(); for (WeightedStudentId student: students.keySet()) { curStudents.add(new CurStudent(student.getStudentId(), student.getWeight())); studentIds.put(student.getStudentId(), student); } CurModel m = new CurModel(curStudents); for (CurriculumCourse course: clasf.getCourses()) { m.addCourse(course.getCourse().getUniqueId(), course.getCourse().getCourseName(), clasf.getNrStudents() * course.getPercShare()); Hashtable<String,Set<String>> curricula = iLoadedCurricula.get(course.getCourse().getUniqueId()); if (curricula == null) { curricula = new Hashtable<String, Set<String>>(); iLoadedCurricula.put(course.getCourse().getUniqueId(), curricula); } Set<String> majors = curricula.get(clasf.getCurriculum().getAcademicArea().getAcademicAreaAbbreviation()); if (majors == null) { majors = new HashSet<String>(); curricula.put(clasf.getCurriculum().getAcademicArea().getAcademicAreaAbbreviation(), majors); } if (clasf.getCurriculum().getMajors().isEmpty()) { majors.add(""); } else { for (PosMajor mj: clasf.getCurriculum().getMajors()) majors.add(mj.getCode()); } } computeTargetShare(clasf, m); // Load model from cache (if exists) CurModel cachedModel = null; Element cache = (clasf.getStudents() == null ? null : clasf.getStudents().getRootElement()); if (cache != null && cache.getName().equals(getCacheName())) { cachedModel = CurModel.loadFromXml(cache); } // Check the cached model if (cachedModel != null && cachedModel.isSameModel(m)) { // Reuse sLog.debug(" using cached model..."); m = cachedModel; } else { // initial assignment for (CurStudent student: curStudents) { for (CourseOffering course: students.get(studentIds.get(student.getStudentId()))) { CurCourse curCourse = m.getCourse(course.getUniqueId()); if (curCourse == null) continue; CurVariable var = null; for (CurVariable v: curCourse.variables()) if (v.getAssignment() == null) { var = v; break; } if (var != null) { CurValue val = new CurValue(var, student); if (!m.inConflict(val)) var.assign(0, val); else { sLog.debug("Unable to assign " + student + " to " + var); Map<Constraint<CurVariable, CurValue>, Set<CurValue>> conf = m.conflictConstraints(val); for (Map.Entry<Constraint<CurVariable, CurValue>, Set<CurValue>> entry: conf.entrySet()) { sLog.debug(entry.getKey() + ": " + entry.getValue()); } } } else { sLog.debug("No variable for " + student + " to " + curCourse); } } } // Solve model sLog.debug("Initial: " + m.getInfo()); m.solve(); sLog.debug("Final: " + m.getInfo()); // Save into the cache Document doc = DocumentHelper.createDocument(); m.saveAsXml(doc.addElement(getCacheName())); // sLog.debug("Model:\n" + doc.asXML()); clasf.setStudents(doc); hibSession.update(clasf); } // Save results for (CurriculumCourse course: clasf.getCourses()) { Set<WeightedStudentId> courseStudents = iDemands.get(course.getCourse().getUniqueId()); if (courseStudents == null) { courseStudents = new HashSet<WeightedStudentId>(); iDemands.put(course.getCourse().getUniqueId(), courseStudents); } for (CurStudent s: m.getCourse(course.getCourse().getUniqueId()).getStudents()) { WeightedStudentId student = studentIds.get(s.getStudentId()); student.setCurriculum(clasf.getCurriculum().getAbbv()); courseStudents.add(student); Set<WeightedCourseOffering> courses = iStudentRequests.get(student.getStudentId()); if (courses == null) { courses = new HashSet<WeightedCourseOffering>(); iStudentRequests.put(student.getStudentId(), courses); } courses.add(new WeightedCourseOffering(course.getCourse(), student.getWeight())); } } } protected String getCacheName() { return "curriculum-lastlike-demands"; } protected void computeTargetShare(CurriculumClassification clasf, CurModel model) { for (CurriculumCourse c1: clasf.getCourses()) { double x1 = clasf.getNrStudents() * c1.getPercShare(); for (CurriculumCourse c2: clasf.getCourses()) { double x2 = clasf.getNrStudents() * c2.getPercShare(); if (c1.getUniqueId() >= c2.getUniqueId()) continue; double share = 0; Set<WeightedStudentId> s1 = iProjectedDemands.getDemands(c1.getCourse()); Set<WeightedStudentId> s2 = iProjectedDemands.getDemands(c2.getCourse()); if (s1 != null && !s1.isEmpty() && s2 != null && !s2.isEmpty()) { double sharedStudents = 0, lastLike = 0; for (WeightedStudentId s: s1) { if (s.match(clasf)) { lastLike += s.getWeight(); if (s2.contains(s)) sharedStudents += s.getWeight(); } } double requested = c1.getPercShare() * clasf.getNrStudents(); share = (requested / lastLike) * sharedStudents; } else { share = c1.getPercShare() * c2.getPercShare() * clasf.getNrStudents(); } CurriculumCourseGroup group = null; groups: for (CurriculumCourseGroup g1: c1.getGroups()) { for (CurriculumCourseGroup g2: c2.getGroups()) { if (g1.equals(g2)) { group = g1; break groups; } } } if (group != null) { share = (group.getType() == 0 ? 0.0 : Math.min(x1, x2)); } model.setTargetShare(c1.getCourse().getUniqueId(), c2.getCourse().getUniqueId(), share); } } } @Override public Set<WeightedCourseOffering> getCourses(Long studentId) { if (studentId >= 0 || iStudentRequests.isEmpty()) return iProjectedDemands.getCourses(studentId); return iStudentRequests.get(studentId); } @Override public Set<WeightedStudentId> getDemands(CourseOffering course) { if (iDemands.isEmpty()) return iProjectedDemands.getDemands(course); Set<WeightedStudentId> demands = iDemands.get(course.getUniqueId()); if (!iIncludeOtherStudents) return demands; if (demands == null) { demands = new HashSet<WeightedStudentId>(); iDemands.put(course.getUniqueId(), demands); } if (iCheckedCourses.add(course.getUniqueId())) { int was = demands.size(); Hashtable<String,Set<String>> curricula = iLoadedCurricula.get(course.getUniqueId()); Set<WeightedStudentId> other = iProjectedDemands.getDemands(course); if (curricula == null || curricula.isEmpty()) { demands.addAll(other); } else { for (WeightedStudentId student: other) { if (student.getArea() == null) continue; // ignore students w/o academic area Set<String> majors = curricula.get(student.getArea()); if (majors != null && majors.contains("")) continue; // all majors if (majors == null || (student.getMajor() != null && !majors.contains(student.getMajor()))) demands.add(student); } } if (demands.size() > was) sLog.debug(course.getCourseName() + " has " + (demands.size() - was) + " other students (besides of the " + was + " curriculum students)."); } return demands; } @Override public boolean canUseStudentClassEnrollmentsAsSolution() { return false; } @Override public boolean isMakingUpStudents() { return false; // most students should be last-like students } @Override public boolean isWeightStudentsToFillUpOffering() { return false; } } --- NEW FILE: StudentCourseDemands.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import java.util.Set; import net.sf.cpsolver.ifs.util.Progress; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.CurriculumClassification; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.PosMajor; import org.unitime.timetable.model.Session; import org.unitime.timetable.model.dao.CourseOfferingDAO; /** * @author Tomas Muller */ public interface StudentCourseDemands { /** * Called only once * @param hibSession opened hibernate session * @param progress progress to print messages * @param session current academic session * @param offerings instructional offerings of the problem that is being loaded */ public void init(org.hibernate.Session hibSession, Progress progress, Session session, Set<InstructionalOffering> offerings); /** * Called once for each course * @param course course for which demands are requested * @return set of students (their unique ids, and weights) that request the course */ public Set<WeightedStudentId> getDemands(CourseOffering course); /** * Return true if students are made up (i.e, it does not make any sense to save them with the solution). */ public boolean isMakingUpStudents(); /** * Return true if students are real students (not last-like) for which the student class enrollments * apply (real student class enrollments can be loaded instead of solution's student class assignments). */ public boolean canUseStudentClassEnrollmentsAsSolution(); /** * Return true if students should be weghted so that the offering is filled in completely. */ public boolean isWeightStudentsToFillUpOffering(); /** * List of courses for a student */ public Set<WeightedCourseOffering> getCourses(Long studentId); public static class WeightedStudentId { private long iStudentId; private float iWeight; private String iAreaAbbv, iClasfCode, iMajorCode, iCurriculum; public WeightedStudentId(long studentId, float weight) { iStudentId = studentId; iWeight = weight; } public WeightedStudentId(long studentId) { this(studentId, 1.0f); } public long getStudentId() { return iStudentId; } public float getWeight() { return iWeight; } public void setWeight(float weight) { iWeight = weight; } public void setStats(String areaAbbv, String clasfCode, String majorCode) { iAreaAbbv = areaAbbv; iClasfCode = clasfCode; iMajorCode = majorCode; } public void setCurriculum(String curriculum) { iCurriculum = curriculum; } public String getArea() { return iAreaAbbv; } public String getClasf() { return iClasfCode; } public String getMajor() { return iMajorCode; } public String getCurriculum() { return iCurriculum; } public boolean match(String areaAbbv, String clasfCode, String majorCode) { return areaAbbv.equals(iAreaAbbv) && clasfCode.equals(iClasfCode) && majorCode.equals(iMajorCode); } public boolean match(CurriculumClassification clasf) { if (!clasf.getCurriculum().getAcademicArea().getAcademicAreaAbbreviation().equals(iAreaAbbv)) return false; if (!clasf.getAcademicClassification().getCode().equals(iClasfCode)) return false; if (clasf.getCurriculum().getMajors().isEmpty()) return true; for (PosMajor m: clasf.getCurriculum().getMajors()) { if (m.getCode().equals(iMajorCode)) return true; } return false; } public int hashCode() { return new Long(getStudentId()).hashCode(); } public boolean equals(Object o) { if (o == null || !(o instanceof WeightedStudentId)) return false; return getStudentId() == ((WeightedStudentId)o).getStudentId(); } public String toString() { return String.valueOf(getStudentId()); } } public static class WeightedCourseOffering { private transient CourseOffering iCourseOffering = null; private long iCourseOfferingId; private float iWeight = 1.0f; public WeightedCourseOffering(CourseOffering courseOffering) { iCourseOffering = courseOffering; iCourseOfferingId = courseOffering.getUniqueId(); } public WeightedCourseOffering(Long courseOfferingId) { iCourseOfferingId = courseOfferingId; } public WeightedCourseOffering(CourseOffering courseOffering, float weight) { this(courseOffering); iWeight = weight; } public WeightedCourseOffering(Long courseOfferingId, float weight) { this(courseOfferingId); iWeight = weight; } public Long getCourseOfferingId() { return iCourseOfferingId; } public CourseOffering getCourseOffering() { if (iCourseOffering == null) iCourseOffering = CourseOfferingDAO.getInstance().get(iCourseOfferingId); return iCourseOffering; } public float getWeight() { return iWeight; } } } --- NEW FILE: WeightedLastLikeStudentCourseDemands.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import net.sf.cpsolver.ifs.util.DataProperties; /** * @author Tomas Muller */ public class WeightedLastLikeStudentCourseDemands extends LastLikeStudentCourseDemands { public WeightedLastLikeStudentCourseDemands(DataProperties properties) { super(properties); } public boolean isWeightStudentsToFillUpOffering() { return true; } } --- NEW FILE: EnrolledStudentCourseDemands.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.Session; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.Progress; /** * @author Tomas Muller */ public class EnrolledStudentCourseDemands implements StudentCourseDemands { private org.hibernate.Session iHibSession = null; private Hashtable<Long, Set<WeightedStudentId>> iDemands = new Hashtable<Long, Set<WeightedStudentId>>(); private Hashtable<Long, Set<WeightedCourseOffering>> iStudentRequests = new Hashtable<Long, Set<WeightedCourseOffering>>(); private boolean iCacheAll = true; public EnrolledStudentCourseDemands(DataProperties properties) { iCacheAll = properties.getPropertyBoolean("EnrolledStudentsCourseDemands.CacheAll", iCacheAll); } public boolean isMakingUpStudents() { return false; } public boolean canUseStudentClassEnrollmentsAsSolution() { return true; } public boolean isWeightStudentsToFillUpOffering() { return false; } public void init(org.hibernate.Session hibSession, Progress progress, Session session, Set<InstructionalOffering> offerings) { iHibSession = hibSession; if (iCacheAll) for (Object[] o: (List<Object[]>)hibSession.createQuery("select e.courseOffering, e.student.uniqueId from StudentClassEnrollment e where " + "e.courseOffering.subjectArea.session.uniqueId = :sessionId").setLong("sessionId", session.getUniqueId()).list()) { CourseOffering course = (CourseOffering)o[0]; Long studentId = (Long)o[1]; Set<WeightedStudentId> students = iDemands.get(course.getUniqueId()); if (students == null) { students = new HashSet<WeightedStudentId>(); iDemands.put(course.getUniqueId(), students); } students.add(new WeightedStudentId(studentId)); Set<WeightedCourseOffering> courses = iStudentRequests.get(studentId); if (courses == null) { courses = new HashSet<WeightedCourseOffering>(); iStudentRequests.put(studentId, courses); } courses.add(new WeightedCourseOffering(course)); } } public Set<WeightedStudentId> getDemands(CourseOffering course) { if (iCacheAll) return iDemands.get(course.getUniqueId()); Set<WeightedStudentId> students = new HashSet<WeightedStudentId>(); for (Long studentId: (List<Long>)iHibSession.createQuery("select distinct e.student.uniqueId from StudentClassEnrollment e where " + "e.courseOffering.uniqueId = :courseId").setLong("courseId", course.getUniqueId()).list()) { students.add(new WeightedStudentId(studentId)); } return students; } public Set<WeightedCourseOffering> getCourses(Long studentId) { if (iCacheAll) return iStudentRequests.get(studentId); HashSet<WeightedCourseOffering> ret = new HashSet<WeightedCourseOffering>(); for (CourseOffering course: (List<CourseOffering>)iHibSession.createQuery( "select distinct e.courseOffering from StudentClassEnrollment e where " + "e.student.uniqueId = :studentId").setLong("studentId", studentId).list()) { ret.add(new WeightedCourseOffering(course)); } return ret; } } --- NEW FILE: StudentCourseRequests.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.Progress; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.Session; import org.unitime.timetable.model.SubjectArea; /** * @author Tomas Muller */ public class StudentCourseRequests implements StudentCourseDemands { protected Hashtable<Long, Hashtable<Long, Set<WeightedStudentId>>> iDemands = new Hashtable<Long, Hashtable<Long, Set<WeightedStudentId>>>(); protected org.hibernate.Session iHibSession = null; protected Hashtable<Long, Set<WeightedCourseOffering>> iStudentRequests = null; protected Long iSessionId = null; public StudentCourseRequests(DataProperties conf) { } @Override public void init(org.hibernate.Session hibSession, Progress progress, Session session, Set<InstructionalOffering> offerings) { iHibSession = hibSession; iSessionId = session.getUniqueId(); } protected Hashtable<Long, Set<WeightedStudentId>> loadDemandsForSubjectArea(SubjectArea subjectArea) { Hashtable<Long, Set<WeightedStudentId>> demands = new Hashtable<Long, Set<WeightedStudentId>>(); for (Object[] o: (List<Object[]>) iHibSession.createQuery( "select distinct e.courseOffering.uniqueId, s.uniqueId, a.academicAreaAbbreviation, f.code, m.code from StudentClassEnrollment e inner join e.student s " + "left outer join s.academicAreaClassifications c left outer join s.posMajors m left outer join c.academicArea a left outer join c.academicClassification f " + "where e.courseOffering.subjectArea.uniqueId = :subjectId") .setLong("subjectId", subjectArea.getUniqueId()).setCacheable(true).list()) { Long courseId = (Long)o[0]; Long studentId = (Long)o[1]; String areaAbbv = (String)o[2]; String clasfCode = (String)o[3]; String majorCode = (String)o[4]; Set<WeightedStudentId> students = demands.get(courseId); if (students == null) { students = new HashSet<WeightedStudentId>(); demands.put(courseId, students); } WeightedStudentId student = new WeightedStudentId(studentId); student.setStats(areaAbbv, clasfCode, majorCode); student.setCurriculum(areaAbbv == null ? null : majorCode == null ? areaAbbv : areaAbbv + "/" + majorCode); students.add(student); } return demands; } @Override public Set<WeightedCourseOffering> getCourses(Long studentId) { if (iStudentRequests == null) { iStudentRequests = new Hashtable<Long, Set<WeightedCourseOffering>>(); for (Object[] o : (List<Object[]>)iHibSession.createQuery( "select distinct e.student.uniqueId, e.courseOffering " + "from StudentClassEnrollment e where e.student.session.uniqueId = :sessionId") .setLong("sessionId", iSessionId).setCacheable(true).list()) { Long sid = (Long)o[0]; CourseOffering co = (CourseOffering)o[1]; Set<WeightedCourseOffering> courses = iStudentRequests.get(sid); if (courses == null) { courses = new HashSet<WeightedCourseOffering>(); iStudentRequests.put(sid, courses); } courses.add(new WeightedCourseOffering(co)); } } return iStudentRequests.get(studentId); } @Override public Set<WeightedStudentId> getDemands(CourseOffering course) { Hashtable<Long, Set<WeightedStudentId>> demands = iDemands.get(course.getSubjectArea().getUniqueId()); if (demands == null) { demands = loadDemandsForSubjectArea(course.getSubjectArea()); iDemands.put(course.getSubjectArea().getUniqueId(), demands); } return demands.get(course.getUniqueId()); } @Override public boolean isMakingUpStudents() { return false; } @Override public boolean isWeightStudentsToFillUpOffering() { return false; } @Override public boolean canUseStudentClassEnrollmentsAsSolution() { return true; } } --- NEW FILE: CurriculaCourseDemands.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.solver.curricula; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.DocumentHelper; import org.dom4j.Element; import org.unitime.timetable.model.CourseOffering; import org.unitime.timetable.model.Curriculum; import org.unitime.timetable.model.CurriculumClassification; import org.unitime.timetable.model.CurriculumCourse; import org.unitime.timetable.model.CurriculumCourseGroup; import org.unitime.timetable.model.InstructionalOffering; import org.unitime.timetable.model.PosMajor; import org.unitime.timetable.model.Session; import org.unitime.timetable.solver.curricula.students.CurModel; import org.unitime.timetable.solver.curricula.students.CurStudent; import net.sf.cpsolver.ifs.util.DataProperties; import net.sf.cpsolver.ifs.util.IdGenerator; import net.sf.cpsolver.ifs.util.Progress; /** * @author Tomas Muller */ public class CurriculaCourseDemands implements StudentCourseDemands { private static Log sLog = LogFactory.getLog(CurriculaCourseDemands.class); private Hashtable<Long, Set<WeightedStudentId>> iDemands = new Hashtable<Long, Set<WeightedStudentId>>(); private Hashtable<Long, Set<WeightedCourseOffering>> iStudentRequests = new Hashtable<Long, Set<WeightedCourseOffering>>(); private IdGenerator lastStudentId = new IdGenerator(); protected ProjectedStudentCourseDemands iFallback; private Hashtable<Long, Hashtable<String, Set<String>>> iLoadedCurricula = new Hashtable<Long,Hashtable<String, Set<String>>>(); private HashSet<Long> iCheckedCourses = new HashSet<Long>(); private boolean iIncludeOtherStudents = true; public CurriculaCourseDemands(DataProperties properties) { if (properties != null) iFallback = new ProjectedStudentCourseDemands(properties); iIncludeOtherStudents = properties.getPropertyBoolean("CurriculaCourseDemands.IncludeOtherStudents", iIncludeOtherStudents); } public CurriculaCourseDemands() { this(null); } public boolean isMakingUpStudents() { return true; } public boolean canUseStudentClassEnrollmentsAsSolution() { return false; } public boolean isWeightStudentsToFillUpOffering() { return false; } public void init(org.hibernate.Session hibSession, Progress progress, Session session, Set<InstructionalOffering> offerings) { iFallback.init(hibSession, progress, session, offerings); List<Curriculum> curricula = null; if (offerings != null && offerings.size() <= 1000) { String courses = ""; for (InstructionalOffering offering: offerings) for (CourseOffering course: offering.getCourseOfferings()) { if (!courses.isEmpty()) courses += ","; courses += course.getUniqueId(); } curricula = hibSession.createQuery( "select distinct c from CurriculumCourse cc inner join cc.classification.curriculum c where " + "c.academicArea.session.uniqueId = :sessionId and cc.course.uniqueId in (" + courses + ")") .setLong("sessionId", session.getUniqueId()).list(); } else { curricula = hibSession.createQuery( "select c from Curriculum c where c.academicArea.session.uniqueId = :sessionId") .setLong("sessionId", session.getUniqueId()).list(); } progress.setPhase("Loading curricula", curricula.size()); for (Curriculum curriculum: curricula) { for (CurriculumClassification clasf: curriculum.getClassifications()) { init(hibSession, clasf); } progress.incProgress(); } if (iDemands.isEmpty()) { progress.warn("There are no curricula, using projected course demands instead."); } } protected String getCacheName() { return "curriculum-demands"; } private void init(org.hibernate.Session hibSession, CurriculumClassification clasf) { if (clasf.getNrStudents() <= 0) return; sLog.debug("Processing " + clasf.getCurriculum().getAbbv() + " " + clasf.getName() + " ... (" + clasf.getNrStudents() + " students, " + clasf.getCourses().size() + " courses)"); // Create model List<CurStudent> students = new ArrayList<CurStudent>(); for (int i = 0; i < clasf.getNrStudents(); i++) students.add(new CurStudent(- lastStudentId.newId(), 1f)); CurModel m = new CurModel(students); for (CurriculumCourse course: clasf.getCourses()) { int nrStudents = Math.round(clasf.getNrStudents() * course.getPercShare()); m.addCourse(course.getUniqueId(), course.getCourse().getCourseName(), nrStudents); Hashtable<String,Set<String>> curricula = iLoadedCurricula.get(course.getCourse().getUniqueId()); if (curricula == null) { curricula = new Hashtable<String, Set<String>>(); iLoadedCurricula.put(course.getCourse().getUniqueId(), curricula); } Set<String> majors = curricula.get(clasf.getCurriculum().getAcademicArea().getAcademicAreaAbbreviation()); if (majors == null) { majors = new HashSet<String>(); curricula.put(clasf.getCurriculum().getAcademicArea().getAcademicAreaAbbreviation(), majors); } if (clasf.getCurriculum().getMajors().isEmpty()) { majors.add(""); } else { for (PosMajor mj: clasf.getCurriculum().getMajors()) majors.add(mj.getCode()); } } computeTargetShare(clasf, m); m.setStudentLimits(); // Load model from cache (if exists) CurModel cachedModel = null; Element cache = (clasf.getStudents() == null ? null : clasf.getStudents().getRootElement()); if (cache != null && cache.getName().equals(getCacheName())) { cachedModel = CurModel.loadFromXml(cache); cachedModel.setStudentLimits(); } // Check the cached model if (cachedModel != null && cachedModel.isSameModel(m)) { // Reuse sLog.debug(" using cached model..."); m = cachedModel; } else { // Solve model m.solve(); // Save into the cache Document doc = DocumentHelper.createDocument(); m.saveAsXml(doc.addElement(getCacheName())); // sLog.debug("Model:\n" + doc.asXML()); clasf.setStudents(doc); hibSession.update(clasf); } // Save results for (CurriculumCourse course: clasf.getCourses()) { Set<WeightedStudentId> courseStudents = iDemands.get(course.getCourse().getUniqueId()); if (courseStudents == null) { courseStudents = new HashSet<WeightedStudentId>(); iDemands.put(course.getCourse().getUniqueId(), courseStudents); } for (CurStudent s: m.getCourse(course.getUniqueId()).getStudents()) { WeightedStudentId student = new WeightedStudentId(s.getStudentId()); student.setStats(clasf.getCurriculum().getAcademicArea().getAcademicAreaAbbreviation(), clasf.getAcademicClassification().getCode(), null); student.setCurriculum(clasf.getCurriculum().getAbbv()); courseStudents.add(student); Set<WeightedCourseOffering> courses = iStudentRequests.get(student.getStudentId()); if (courses == null) { courses = new HashSet<WeightedCourseOffering>(); iStudentRequests.put(student.getStudentId(), courses); } courses.add(new WeightedCourseOffering(course.getCourse(), student.getWeight())); } } } protected void computeTargetShare(CurriculumClassification clasf, CurModel model) { for (CurriculumCourse c1: clasf.getCourses()) { int x1 = Math.round(clasf.getNrStudents() * c1.getPercShare()); for (CurriculumCourse c2: clasf.getCourses()) { int x2 = Math.round(clasf.getNrStudents() * c2.getPercShare()); if (c1.getUniqueId() >= c2.getUniqueId()) continue; int share = Math.round(c1.getPercShare() * c2.getPercShare() * clasf.getNrStudents()); CurriculumCourseGroup group = null; groups: for (CurriculumCourseGroup g1: c1.getGroups()) { for (CurriculumCourseGroup g2: c2.getGroups()) { if (g1.equals(g2)) { group = g1; break groups; } } } if (group != null) { share = (group.getType() == 0 ? 0 : Math.min(x1, x2)); } model.setTargetShare(c1.getUniqueId(), c2.getUniqueId(), share); } } } public Set<WeightedStudentId> getDemands(CourseOffering course) { if (iDemands.isEmpty()) return iFallback.getDemands(course); Set<WeightedStudentId> demands = iDemands.get(course.getUniqueId()); if (!iIncludeOtherStudents) return demands; if (demands == null) { demands = new HashSet<WeightedStudentId>(); iDemands.put(course.getUniqueId(), demands); } if (iCheckedCourses.add(course.getUniqueId())) { int was = demands.size(); Hashtable<String,Set<String>> curricula = iLoadedCurricula.get(course.getUniqueId()); Set<WeightedStudentId> other = iFallback.getDemands(course); if (curricula == null || curricula.isEmpty()) { demands.addAll(other); } else { for (WeightedStudentId student: other) { if (student.getArea() == null) continue; // ignore students w/o academic area Set<String> majors = curricula.get(student.getArea()); if (majors != null && majors.contains("")) continue; // all majors if (majors == null || (student.getMajor() != null && !majors.contains(student.getMajor()))) demands.add(student); } } if (demands.size() > was) sLog.info(course.getCourseName() + " has " + (demands.size() - was) + " other students (besides of the " + was + " curriculum students)."); } return demands; } public Set<WeightedCourseOffering> getCourses(Long studentId) { if (studentId >= 0 || iStudentRequests.isEmpty()) return iFallback.getCourses(studentId); return iStudentRequests.get(studentId); } } |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/client In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/client Added Files: ToolBox.java Client.java Pages.java Triggers.java Components.java Lookup.java GwtHint.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: Lookup.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client; import java.util.ArrayList; import java.util.List; import org.unitime.timetable.gwt.client.widgets.UniTimeDialogBox; import org.unitime.timetable.gwt.client.widgets.UniTimeTable; import org.unitime.timetable.gwt.client.widgets.UniTimeTableHeader; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasCellAlignment; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasColSpan; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.HasStyleName; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.MouseClickListener; import org.unitime.timetable.gwt.client.widgets.UniTimeTable.TableEvent; import org.unitime.timetable.gwt.resources.GwtResources; import org.unitime.timetable.gwt.services.LookupService; import org.unitime.timetable.gwt.services.LookupServiceAsync; import org.unitime.timetable.gwt.shared.PersonInterface; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.dom.client.Element; import com.google.gwt.dom.client.Style.Unit; import com.google.gwt.event.dom.client.KeyCodes; import com.google.gwt.event.dom.client.KeyUpEvent; import com.google.gwt.event.dom.client.KeyUpHandler; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.ScrollPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant; /** * @author Tomas Muller */ public class Lookup extends UniTimeDialogBox { public static final GwtResources RESOURCES = GWT.create(GwtResources.class); private VerticalPanel iPanel; private UniTimeTable<PersonInterface> iTable; private ScrollPanel iScroll; private TextBox iQuery; private JavaScriptObject iCallback; private String iOptions; private Timer iTimer; private String iLastQuery = null; private static Lookup sInstance = null; private final LookupServiceAsync iLookupService = GWT.create(LookupService.class); public Lookup() { super(true, true); setText("People Lookup"); setEscapeToHide(true); iPanel = new VerticalPanel(); iPanel.setSpacing(2); iQuery = new TextBox(); iQuery.setWidth("400px"); HorizontalPanel queryPanel = new HorizontalPanel(); Label filterText = new Label("Name:", false); filterText.getElement().getStyle().setMarginRight(5, Unit.PX); queryPanel.setWidth("75px"); queryPanel.add(filterText); queryPanel.setCellHorizontalAlignment(filterText, HasHorizontalAlignment.ALIGN_RIGHT); queryPanel.setCellVerticalAlignment(filterText, HasVerticalAlignment.ALIGN_MIDDLE); queryPanel.add(iQuery); HTML blank = new HTML(" "); blank.setWidth("75px"); queryPanel.add(blank); iPanel.add(queryPanel); iPanel.setCellHorizontalAlignment(queryPanel, HasHorizontalAlignment.ALIGN_CENTER); iTable = new UniTimeTable<PersonInterface>(); iScroll = new ScrollPanel(iTable); iScroll.setSize("800px", "500px"); iScroll.setStyleName("unitime-ScrollPanel"); iPanel.add(iScroll); setWidget(iPanel); List<UniTimeTableHeader> header = new ArrayList<UniTimeTableHeader>(); header.add(new UniTimeTableHeader("Name")); header.add(new UniTimeTableHeader("Email")); header.add(new UniTimeTableHeader("Phone")); header.add(new UniTimeTableHeader("Department")); header.add(new UniTimeTableHeader("Source")); iTable.addRow(null, header); iTable.setAllowSelection(true); iTable.setWidth("100%"); iTimer = new Timer() { @Override public void run() { update(); } }; iTable.addMouseClickListener(new MouseClickListener<PersonInterface>() { @Override public void onMouseClick(TableEvent<PersonInterface> event) { if (event.getData() != null) { iTimer.cancel(); Lookup.this.hide(); fireCallback(getCallback(), event.getData().getId(), event.getData().getFirstName(), event.getData().getMiddleName(), event.getData().getLastName(), event.getData().getEmail(), event.getData().getPhone()); } } }); iQuery.addKeyUpHandler(new KeyUpHandler() { public void onKeyUp(KeyUpEvent event) { iTimer.schedule(500); } }); sinkEvents(Event.ONKEYDOWN); } private void scrollToSelectedRow() { int row = iTable.getSelectedRow(); if (row < 0) return; Element scroll = iScroll.getElement(); Element item = iTable.getRowFormatter().getElement(iTable.getSelectedRow()); if (item==null) return; int realOffset = 0; while (item !=null && !item.equals(scroll)) { realOffset += item.getOffsetTop(); item = item.getOffsetParent(); } scroll.setScrollTop(realOffset - scroll.getOffsetHeight() / 2); } public void onBrowserEvent(final Event event) { switch (DOM.eventGetType(event)) { case Event.ONKEYDOWN: if (event.getKeyCode() == KeyCodes.KEY_DOWN && iTable.getRowCount() > 1 && iTable.getData(1) != null) { int row = iTable.getSelectedRow(); if (row >= 0) iTable.setSelected(row, false); if (row < 0) { row = 1; } else { row ++; } if (row >= iTable.getRowCount()) row = 1; iTable.setSelected(row, true); scrollToSelectedRow(); event.preventDefault(); event.stopPropagation(); } if (event.getKeyCode() == KeyCodes.KEY_UP && iTable.getRowCount() > 1 && iTable.getData(1) != null) { int row = iTable.getSelectedRow(); if (row >= 0) iTable.setSelected(row, false); if (row < 0) { row = iTable.getRowCount() - 1; } else { row --; } if (row <= 0) row = iTable.getRowCount() - 1;; iTable.setSelected(row, true); scrollToSelectedRow(); event.preventDefault(); event.stopPropagation(); } if (event.getKeyCode() == KeyCodes.KEY_ENTER) { int row = iTable.getSelectedRow(); if (row >= 0) { PersonInterface person = iTable.getData(row); if (person != null) { iTimer.cancel(); Lookup.this.hide(); fireCallback(getCallback(), person.getId(), person.getFirstName(), person.getMiddleName(), person.getLastName(), person.getEmail(), person.getPhone()); } } } break; } } public void setQuery(String query) { iQuery.setText(query); } public void setCallback(JavaScriptObject callback) { iCallback = callback; } public void setOptions(String options) { iOptions = options; } public void update() { final String q = iQuery.getText().trim(); if (q.equals(iLastQuery)) return; if (q.isEmpty()) { iTable.clearTable(1); return; } iTable.clearTable(1); List<Widget> line = new ArrayList<Widget>(); line.add(new LoadingImage()); iTable.addRow(null, line); iLookupService.lookupPeople(q, iOptions, new AsyncCallback<List<PersonInterface>>() { @Override public void onSuccess(List<PersonInterface> result) { iLastQuery = q; iTable.clearTable(1); boolean hasId = true; for (PersonInterface person: result) { List<Widget> line = new ArrayList<Widget>(); line.add(new Label(person.getName(), false)); line.add(new Label(person.getEmail(), false)); line.add(new Label(person.getPhone(), false)); line.add(new Label(person.getDepartment())); line.add(new Label(person.getSource())); iTable.addRow(person, line); if (person.getId() == null || person.getId().isEmpty() || "null".equals(person.getId())) { int row = iTable.getRowCount() - 1; for (int col = 0; col < iTable.getCellCount(row); col++) iTable.getCellFormatter().addStyleName(row, col, "unitime-Disabled"); if (hasId) { hasId = false; if (row > 1) for (int col = 0; col < iTable.getCellCount(row); col++) iTable.getCellFormatter().addStyleName(row, col, "unitime-TopLineDash"); } } } if (result.isEmpty()) { List<Widget> line = new ArrayList<Widget>(); line.add(new ErrorLine("No person matching the query found.", false)); iTable.addRow(null, line); } } @Override public void onFailure(Throwable caught) { iTable.clearTable(1); List<Widget> line = new ArrayList<Widget>(); line.add(new ErrorLine(caught.getMessage(), true)); iTable.addRow(null, line); } }); } public static class ErrorLine extends Label implements HasColSpan, HasStyleName { private boolean iError; public ErrorLine(String text, boolean error) { super(text); iError = error; } @Override public int getColSpan() { return 5; } @Override public String getStyleName() { return (iError ? "unitime-ErrorMessage" : "unitime-Message"); } } public static class LoadingImage extends Image implements HasColSpan, HasCellAlignment { public LoadingImage() { super(RESOURCES.loading_small()); } @Override public int getColSpan() { return 5; } @Override public HorizontalAlignmentConstant getCellAlignment() { return HasHorizontalAlignment.ALIGN_CENTER; } } public static Lookup getInstance() { if (sInstance == null) { sInstance = new Lookup(); } return sInstance; } public static native void createTriggers()/*-{ $wnd.peopleLookup = function(query, callback, options) { @org.unitime.timetable.gwt.client.Lookup::peopleLookup(Ljava/lang/String;Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;)(query,callback,options); }; }-*/; public void center() { super.center(); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { iLastQuery = null; iQuery.setFocus(true); iQuery.selectAll(); update(); } }); } public static void peopleLookup(String query, JavaScriptObject callback, String options) { if (query != null && !query.trim().isEmpty()) getInstance().setQuery(query); getInstance().setCallback(callback); getInstance().setOptions(options); getInstance().center(); } public static JavaScriptObject getCallback() { return getInstance().iCallback; } public native void fireCallback(JavaScriptObject callback, String... person)/*-{ callback(person); }-*/; } --- NEW FILE: Triggers.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client; import org.unitime.timetable.gwt.client.page.Refresh; import org.unitime.timetable.gwt.client.widgets.LoadingWidget; import org.unitime.timetable.gwt.client.widgets.UniTimeFrameDialog; import com.google.gwt.user.client.Command; /** * @author Tomas Muller */ public enum Triggers { gwtHint(new Command() { public void execute() { GwtHint.createTriggers(); }}), lookup(new Command() { public void execute() { Lookup.createTriggers(); } }), gwtDialog(new Command() { public void execute() { UniTimeFrameDialog.createTriggers(); } }), loading(new Command() { public void execute() { LoadingWidget.createTriggers(); } }), refresh(new Command() { public void execute() { Refresh.createTriggers(); } }); private Command iCommand; Triggers(Command registerCommand) { iCommand = registerCommand; } public void register() { iCommand.execute(); } } --- NEW FILE: Pages.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client; import org.unitime.timetable.gwt.client.admin.SimpleEditPage; import org.unitime.timetable.gwt.client.curricula.CurriculaPage; import org.unitime.timetable.gwt.client.curricula.CurriculumProjectionRulesPage; import org.unitime.timetable.gwt.client.events.EventResourceTimetable; import org.unitime.timetable.gwt.client.sectioning.StudentSectioningPage; import com.google.gwt.user.client.ui.Widget; /** * Register GWT pages here. * @author Tomas Muller * */ public enum Pages { curricula("Curricula", new PageFactory() { public Widget create() { return new CurriculaPage(); } }), curprojrules("Curriculum Projection Rules", new PageFactory() { public Widget create() { return new CurriculumProjectionRulesPage(); } }), sectioning("Student Scheduling Assistant", new PageFactory() { public Widget create() { return new StudentSectioningPage(StudentSectioningPage.Mode.SECTIONING); } }), requests("Student Course Requests", new PageFactory() { public Widget create() { return new StudentSectioningPage(StudentSectioningPage.Mode.REQUESTS); } }), admin("Administration", new PageFactory() { public Widget create() { return new SimpleEditPage(); } }), timetable("Event Timetable", new PageFactory() { public Widget create() { return new EventResourceTimetable(); } }); private String iTitle; private PageFactory iFactory; Pages(String title, PageFactory factory) { iTitle = title; iFactory = factory; } public String title() { return iTitle; } public Widget widget() { return iFactory.create(); } public interface PageFactory { Widget create(); } } --- NEW FILE: Components.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client; import org.unitime.timetable.gwt.client.curricula.CourseCurriculaTable; import org.unitime.timetable.gwt.client.page.UniTimePageLabel; import org.unitime.timetable.gwt.client.page.UniTimeBack; import org.unitime.timetable.gwt.client.page.UniTimePageHeader; import org.unitime.timetable.gwt.client.page.UniTimeMenuBar; import org.unitime.timetable.gwt.client.page.UniTimeSideBar; import org.unitime.timetable.gwt.client.page.UniTimeVersion; import com.google.gwt.user.client.ui.RootPanel; /** * Register GWT components here. * @author Tomas Muller * */ public enum Components { courseCurricula("UniTimeGWT:CourseCurricula", new ComponentFactory() { public void insert(RootPanel panel) { new CourseCurriculaTable(true, true).insert(panel); } }), title("UniTimeGWT:Title", new ComponentFactory() { public void insert(RootPanel panel) { UniTimePageLabel.getInstance().insert(panel); } }), sidebar_stack("UniTimeGWT:SideStackMenu", new ComponentFactory() { public void insert(RootPanel panel) { new UniTimeSideBar(true).insert(panel); } }), sidebar_tree("UniTimeGWT:SideTreeMenu", new ComponentFactory() { public void insert(RootPanel panel) { new UniTimeSideBar(false).insert(panel); } }), menubar_static("UniTimeGWT:TopMenu", new ComponentFactory() { public void insert(RootPanel panel) { new UniTimeMenuBar(false).insert(panel); } }), menubar_dynamic("UniTimeGWT:DynamicTopMenu", new ComponentFactory() { public void insert(RootPanel panel) { new UniTimeMenuBar(true).insert(panel); } }), header("UniTimeGWT:Header", new ComponentFactory() { public void insert(RootPanel panel) { new UniTimePageHeader().insert(panel); } }), version("UniTimeGWT:Version", new ComponentFactory() { public void insert(RootPanel panel) { new UniTimeVersion().insert(panel); } }), back("UniTimeGWT:Back", new ComponentFactory() { public void insert(RootPanel panel) { new UniTimeBack().insert(panel); } }); private String iId; private ComponentFactory iFactory; Components(String id, ComponentFactory factory) { iId = id; iFactory = factory; } public String id() { return iId; } public void insert(RootPanel panel) { iFactory.insert(panel); } public interface ComponentFactory { void insert(RootPanel panel); } } --- NEW FILE: GwtHint.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client; import com.google.gwt.core.client.JavaScriptObject; import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.PopupPanel; /** * @author Tomas Muller */ public class GwtHint extends PopupPanel { private HTML iContent; private static GwtHint sInstance; public GwtHint(String html) { super(); setStyleName("unitime-PopupHint"); iContent = new HTML(html, false); setWidget(iContent); } public void setContent(String html) { iContent.setHTML(html); } public static GwtHint getInstance() { if (sInstance == null) { sInstance = new GwtHint(""); } return sInstance; } public static native void createTriggers()/*-{ $wnd.showGwtHint = function(source, content) { @org.unitime.timetable.gwt.client.GwtHint::showHint(Lcom/google/gwt/core/client/JavaScriptObject;Ljava/lang/String;)(source, content); }; $wnd.hideGwtHint = function() { @org.unitime.timetable.gwt.client.GwtHint::hideHint()(); }; }-*/; public static void showHint(JavaScriptObject source, String content) { final Element relativeObject = source.cast(); getInstance().setContent(content); getInstance().setPopupPositionAndShow(new PositionCallback() { @Override public void setPosition(int offsetWidth, int offsetHeight) { int textBoxOffsetWidth = relativeObject.getOffsetWidth(); int offsetWidthDiff = offsetWidth - textBoxOffsetWidth; int left; if (LocaleInfo.getCurrentLocale().isRTL()) { int textBoxAbsoluteLeft = relativeObject.getAbsoluteLeft(); left = textBoxAbsoluteLeft - offsetWidthDiff; if (offsetWidthDiff > 0) { int windowRight = Window.getClientWidth() + Window.getScrollLeft(); int windowLeft = Window.getScrollLeft(); int textBoxLeftValForRightEdge = textBoxAbsoluteLeft + textBoxOffsetWidth; int distanceToWindowRight = windowRight - textBoxLeftValForRightEdge; int distanceFromWindowLeft = textBoxLeftValForRightEdge - windowLeft; if (distanceFromWindowLeft < offsetWidth && distanceToWindowRight >= offsetWidthDiff) { left = textBoxAbsoluteLeft; } } } else { left = relativeObject.getAbsoluteLeft(); if (offsetWidthDiff > 0) { int windowRight = Window.getClientWidth() + Window.getScrollLeft(); int windowLeft = Window.getScrollLeft(); int distanceToWindowRight = windowRight - left; int distanceFromWindowLeft = left - windowLeft; if (distanceToWindowRight < offsetWidth && distanceFromWindowLeft >= offsetWidthDiff) { left -= offsetWidthDiff; } } } int top = relativeObject.getAbsoluteTop(); int windowTop = Window.getScrollTop(); int windowBottom = Window.getScrollTop() + Window.getClientHeight(); int distanceFromWindowTop = top - windowTop; int distanceToWindowBottom = windowBottom - (top + relativeObject.getOffsetHeight()); if (distanceToWindowBottom < offsetHeight && distanceFromWindowTop >= offsetHeight) { top -= offsetHeight; } else { top += relativeObject.getOffsetHeight(); } getInstance().setPopupPosition(left, top); } }); } public static void hideHint() { getInstance().hide(); } } --- NEW FILE: Client.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client; import java.util.ArrayList; import java.util.List; import org.unitime.timetable.gwt.client.page.UniTimePageLabel; import org.unitime.timetable.gwt.client.widgets.LoadingWidget; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.RunAsyncCallback; import com.google.gwt.core.client.Scheduler; import com.google.gwt.core.client.Scheduler.ScheduledCommand; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; /** * @author Tomas Muller */ public class Client implements EntryPoint { public static List<GwtPageChangedHandler> iGwtPageChangedHandlers = new ArrayList<GwtPageChangedHandler>(); public void onModuleLoad() { // register triggers GWT.runAsync(new RunAsyncCallback() { @Override public void onSuccess() { for (Triggers t: Triggers.values()) t.register(); } @Override public void onFailure(Throwable reason) { } }); // load page if (RootPanel.get("UniTimeGWT:Body") != null) { LoadingWidget.getInstance().show("Loading page ..."); Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { initPageAsync(Window.Location.getParameter("page")); } }); } // load components for (final Components c: Components.values()) { final RootPanel p = RootPanel.get(c.id()); if (p != null) { Scheduler.get().scheduleDeferred(new ScheduledCommand() { @Override public void execute() { initComponentAsync(p, c); } }); } } } public void initPageAsync(final String page) { GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { init(page); LoadingWidget.getInstance().hide(); } public void onFailure(Throwable reason) { Label error = new Label("Failed to load the page (" + reason.getMessage() + ")"); error.setStyleName("unitime-ErrorMessage"); RootPanel loading = RootPanel.get("UniTimeGWT:Loading"); if (loading != null) loading.setVisible(false); RootPanel.get("UniTimeGWT:Body").add(error); LoadingWidget.getInstance().hide(); } }); } public void init(String page) { try { RootPanel loading = RootPanel.get("UniTimeGWT:Loading"); if (loading != null) loading.setVisible(false); for (Pages p: Pages.values()) { if (p.name().equals(page)) { LoadingWidget.getInstance().setMessage("Loading " + p.title() + " ..."); UniTimePageLabel.getInstance().setPageName(p.title()); Window.setTitle("UniTime 3.2| " + p.title()); RootPanel.get("UniTimeGWT:Body").add(p.widget()); return; } } Label error = new Label("Failed to load the page (" + (page == null ? "page not provided" : "page " + page + " not registered" ) + ")"); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("UniTimeGWT:Body").add(error); } catch (Exception e) { Label error = new Label("Failed to load the page (" + e.getMessage() + ")"); error.setStyleName("unitime-ErrorMessage"); RootPanel.get("UniTimeGWT:Body").add(error); } } public void initComponentAsync(final RootPanel panel, final Components comp) { GWT.runAsync(new RunAsyncCallback() { public void onSuccess() { comp.insert(panel); } public void onFailure(Throwable reason) { } }); } public static class GwtPageChangeEvent { } public interface GwtPageChangedHandler { public void onChange(GwtPageChangeEvent event); } public static void addGwtPageChangedHandler(GwtPageChangedHandler h) { iGwtPageChangedHandlers.add(h); } public static void fireGwtPageChanged(GwtPageChangeEvent event) { for (GwtPageChangedHandler h: iGwtPageChangedHandlers) h.onChange(event); } } --- NEW FILE: ToolBox.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.client; import java.util.Date; import com.google.gwt.core.client.GWT; import com.google.gwt.i18n.client.DateTimeFormat; import com.google.gwt.i18n.client.DateTimeFormat.PredefinedFormat; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.Widget; /** * @author Tomas Muller */ public class ToolBox { public native static void disableTextSelectInternal(Element e)/*-{ e.ondrag = function () { return false; }; e.onselectstart = function () { return false; }; e.style.MozUserSelect="none" }-*/; public native static int getScrollBarWidth() /*-{ var inner = document.createElement("p"); inner.style.width = "100%"; inner.style.height = "200px"; var outer = document.createElement("div"); outer.style.position = "absolute"; outer.style.top = "0px"; outer.style.left = "0px"; outer.style.visibility = "hidden"; outer.style.width = "200px"; outer.style.height = "150px"; outer.style.overflow = "hidden"; outer.appendChild (inner); document.body.appendChild (outer); var w1 = inner.offsetWidth; outer.style.overflow = "scroll"; var w2 = inner.offsetWidth; if (w1 == w2) w2 = outer.clientWidth; document.body.removeChild (outer); return (w1 - w2); }-*/; public static native void printw(String html) /*-{ var win = (html ? $wnd.open("about:blank", "__printingWindow") : $wnd); var doc = win.document; if (html) { doc.open(); doc.write(html); doc.write("<script type=\"text/javascript\" language=\"javascript\">" + "function invokePrint() { " + "if (document.readyState && document.readyState!='complete') " + "setTimeout(function() { invokePrint(); }, 50); " + "else if (document.body && document.body.innerHTML=='false') " + "setTimeout(function() { invokePrint(); }, 50); " + "else { focus(); print(); }}" + "setTimeout(function() { invokePrint(); }, 500);" + "</script>"); doc.close(); } win.focus(); }-*/; public static native void printf(String html) /*-{ if (navigator.userAgent.toLowerCase().indexOf('chrome') > -1) { @org.unitime.timetable.gwt.client.ToolBox::printw(Ljava/lang/String;)(html); return; } var frame = $doc.frames ? $doc.frames['__printingFrame'] : $doc.getElementById('__printingFrame'); if (!frame) { @org.unitime.timetable.gwt.client.ToolBox::printw(Ljava/lang/String;)(html); return; } var doc = null; if (frame.contentDocument) doc = frame.contentDocument; else if (frame.contentWindow) doc = frame.contentWindow.document; else if (frame.document) doc = frame.document; if (!doc) { @org.unitime.timetable.gwt.client.ToolBox::printw(Ljava/lang/String;)(html); return; } if (html) { doc.open(); doc.write(html); doc.close(); } if (doc.readyState && doc.readyState!='complete') { setTimeout(function() { @org.unitime.timetable.gwt.client.ToolBox::printf(Ljava/lang/String;)(null); }, 50); } else if (doc.body && doc.body.innerHTML=='false') { setTimeout(function() { @org.unitime.timetable.gwt.client.ToolBox::printf(Ljava/lang/String;)(null); }, 50); } else { if (frame.contentWindow) frame = frame.contentWindow; frame.focus(); frame.print(); } }-*/; public static void print(String title, String user, String session, Widget... widgets) { String content = ""; for (Widget w: widgets) content += "<div class=\"unitime-PrintedComponent\">" + DOM.toString(w.getElement()) + "</div>"; String html = "<html><header>" + "<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">" + "<link type=\"text/css\" rel=\"stylesheet\" href=\"" + GWT.getHostPageBaseURL() + "unitime/gwt/standard/standard.css\">" + "<link type=\"text/css\" rel=\"stylesheet\" href=\"" + GWT.getHostPageBaseURL() + "styles/unitime.css\">" + "<link rel=\"shortcut icon\" href=\"" + GWT.getHostPageBaseURL() + "images/timetabling.ico\">" + "<title>UniTime 3.2 | University Timetabling Application</title>" + "</header><body>" + "<table align=\"center\"><tr><td>" + "<table class=\"unitime-Page\"><tr><td>" + "<table id=\"header\" class=\"unitime-MainTable\" cellpadding=\"2\" cellspacing=\"0\" width=\"100%\">" + "<tr><td rowspan=\"2\"><img src=\"" + GWT.getHostPageBaseURL() + "images/unitime.png\" border=\"0\"/></td>" + "<td nowrap=\"nowrap\" class=\"unitime-Title\" width=\"100%\" align=\"center\" colspan=\"2\">" + title + "</td></tr>" + "<tr><td nowrap=\"nowrap\" class=\"unitime-SubTitle\" width=\"50%\" align=\"center\">" + user + "</td>"+ "<td nowrap=\"nowrap\" class=\"unitime-SubTitle\" width=\"50%\" align=\"center\">" + session + "</td></tr></table>" + content + "</td></tr></table>" + "</td></tr><tr><td>" + "<table class=\"unitime-Footer\"><tr>" + "<td width=\"33%\" align=\"left\" nowrap=\"nowrap\">Printed from UniTime 3.2 | University Timetabling Application</td>" + "<td width=\"34%\" align=\"center\">© 2008 - 2010 UniTime LLC</td>" + "<td width=\"33%\" align=\"right\">" + DateTimeFormat.getFormat(PredefinedFormat.DATE_TIME_MEDIUM).format(new Date()) + "</td>" + "</tr></table></td></tr></table>" + "</body></html>"; printf(html); } public native static void open(String url) /*-{ $wnd.location = url; }-*/; } |
|
From: Tomas M. <to...@us...> - 2010-12-01 11:10:56
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/server/custom/purdue In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/server/custom/purdue Added Files: PurdueCourseDetailsProvider.java PurdueSectionLimitProvider.java PurdueSectionNames.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: PurdueSectionNames.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server.custom.purdue; import org.unitime.timetable.gwt.server.AcademicSessionInfo; import org.unitime.timetable.gwt.server.custom.CustomSectionNames; import org.unitime.timetable.model.Class_; import org.unitime.timetable.model.dao.Class_DAO; import org.unitime.timetable.model.dao.CourseOfferingDAO; /** * @author Tomas Muller */ public class PurdueSectionNames implements CustomSectionNames { public String getClassSuffix(Long sessionId, Long courseId, Long classId) { Class_ clazz = Class_DAO.getInstance().get(classId); return clazz.getClassSuffix(CourseOfferingDAO.getInstance().get(courseId)); } public void update(AcademicSessionInfo session) { } } --- NEW FILE: PurdueSectionLimitProvider.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server.custom.purdue; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.Hashtable; import java.util.Set; import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.unitime.timetable.gwt.server.AcademicSessionInfo; import org.unitime.timetable.gwt.server.custom.CustomSectionNames; import org.unitime.timetable.gwt.server.custom.SectionLimitProvider; import org.unitime.timetable.gwt.server.custom.SectionUrlProvider; import org.unitime.timetable.gwt.shared.SectioningException; import org.unitime.timetable.gwt.shared.SectioningExceptionType; /** * @author Tomas Muller */ public class PurdueSectionLimitProvider implements SectionLimitProvider, SectionUrlProvider { private static Logger sLog = Logger.getLogger(PurdueSectionLimitProvider.class); public static String sUrl = "https://esa-oas-prod-wl.itap.purdue.edu/prod/bzwsrch.p_schedule_detail?term=:year:term&crn=:crn"; public static String sDummyUrl = "https://esa-oas-prod-wl.itap.purdue.edu/prod/bzwsrch.p_schedule_detail?term=201010&crn=10001"; public static String sContentRE = "(<table [ ]*class=\"[a-z]*\" summary=\"This layout table is used to present the seating numbers.\" .*</table>)"; public static String sTableRE = "<td class=\"dddefault\">(\\-?[0-9]*)</td>"; private Pattern iContentRE = Pattern.compile(sContentRE, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.UNIX_LINES); private Pattern iTableRE = Pattern.compile(sTableRE, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.UNIX_LINES); public static int sConcurrencyLimit = 10; private Hashtable<Long, int[]> iCache = new Hashtable<Long, int[]>(); private String getTerm(AcademicSessionInfo session) throws SectioningException { if (session.getTerm().toLowerCase().startsWith("spr")) return "20"; if (session.getTerm().toLowerCase().startsWith("sum")) return "30"; if (session.getTerm().toLowerCase().startsWith("fal")) return "10"; throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "academic term "+session.getTerm()+" not known"); } private String getYear(AcademicSessionInfo session) throws SectioningException { if (session.getTerm().toLowerCase().startsWith("fal")) return String.valueOf(Integer.parseInt(session.getYear()) + 1); return session.getYear(); } public URL getSectionUrl(AcademicSessionInfo session, Long courseId, Long classId, String customClassSuffix) { try { if (customClassSuffix == null || customClassSuffix.isEmpty()) throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "class CRN not provided"); String crn = customClassSuffix; if (customClassSuffix.indexOf('-') >= 0) crn = customClassSuffix.substring(0, customClassSuffix.indexOf('-')); URL url = new URL(sUrl .replace(":year", getYear(session)) .replace(":term", getTerm(session)) .replace(":initiative", session.getCampus()) .replace(":crn", crn)); return url; } catch (MalformedURLException e) { throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "course detail url is wrong"); } } public int[] getSectionLimit(AcademicSessionInfo session, Long courseId, Long classId, String customClassSuffix) throws SectioningException { int[] ret = getSectionLimit(getSectionUrl(session, courseId, classId, customClassSuffix)); iCache.put(classId, ret); return ret; } public int[] getSectionLimit(URL secionUrl) throws SectioningException { try { BufferedReader in = new BufferedReader(new InputStreamReader(secionUrl.openStream())); StringBuffer content = new StringBuffer(); String line; while ((line = in.readLine()) != null) content.append(line); in.close(); Matcher match = iContentRE.matcher(content); if (!match.find()) throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "unable to parse <a href='"+secionUrl+"'>class detial page</a>"); String table = match.group(1); match = iTableRE.matcher(table); if (!match.find()) throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "unable to parse <a href='"+secionUrl+"'>class detial page</a>"); int capacity = Integer.parseInt(match.group(1)); if (!match.find()) throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "unable to parse <a href='"+secionUrl+"'>class detial page</a>"); int actual = Integer.parseInt(match.group(1)); if (!match.find()) throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "unable to parse <a href='"+secionUrl+"'>class detial page</a>"); // int remaning = Integer.parseInt(match.group(1)); return new int[] {actual, capacity}; } catch (IOException e) { throw new SectioningException(SectioningExceptionType.CUSTOM_SECTION_LIMITS_FAILURE, "unable to read <a href='"+secionUrl+"'>class detial page</a>"); } } public Hashtable<Long, int[]> getSectionLimits(AcademicSessionInfo session, Long courseId, ArrayList<Long> classIds, CustomSectionNames names) { Hashtable<Long, int[]> ret = new Hashtable<Long, int[]>(); ThreadPool pool = new ThreadPool(); for (Long classId: classIds) { String customClassSuffix = names.getClassSuffix(session.getUniqueId(), courseId, classId); pool.retrieveLimit(session, courseId, classId, customClassSuffix, ret); } pool.waitForAll(); return ret; } public Hashtable<Long, int[]> getSectionLimitsFromCache(AcademicSessionInfo session, Long courseId, ArrayList<Long> classIds, CustomSectionNames names) { Hashtable<Long, int[]> ret = new Hashtable<Long, int[]>(); ThreadPool pool = new ThreadPool(); for (Long classId: classIds) { int[] limits = iCache.get(classId); if (limits != null) { ret.put(classId, limits); } else { String customClassSuffix = names.getClassSuffix(session.getUniqueId(), courseId, classId); pool.retrieveLimit(session, courseId, classId, customClassSuffix, ret); } } pool.waitForAll(); return ret; } public static void main(String[] args) { try { // int[] l = new PurdueSectionLimitProvider().getSectionLimit(new URL(sDummyUrl)); AcademicSessionInfo session = new AcademicSessionInfo(-1l, "2009", "Fall", "PWL"); ArrayList<Long> classIds = new ArrayList<Long>(); for (int i = 0; i < 100; i++) classIds.add(new Long(10001 + i)); CustomSectionNames names = new CustomSectionNames() { public void update(AcademicSessionInfo session) { } public String getClassSuffix(Long sessionId, Long courseId, Long classId) { return classId.toString() + "-dummy"; } }; long t0 = System.currentTimeMillis(); Hashtable<Long, int[]> limits = new PurdueSectionLimitProvider().getSectionLimits(session, -1l, classIds, names); long t1 = System.currentTimeMillis(); System.out.println("limits:"); for (Long classId : new TreeSet<Long>(limits.keySet())) { int[] limit = limits.get(classId); System.out.println(" " + classId + " .. " + limit[0] + "/" + limit[1]); } System.out.println(" lookup took " + (t1 - t0) + "ms"); } catch (Exception e) { e.printStackTrace(); } } class ThreadPool { Set<Worker> iWorkers = new HashSet<Worker>(); void retrieveLimit(AcademicSessionInfo session, Long courseId, Long classId, String customClassSuffix, Hashtable<Long, int[]> ret) { synchronized (iWorkers) { while (iWorkers.size() > sConcurrencyLimit) { try { iWorkers.wait(); } catch (InterruptedException e) {} } Worker w = new Worker(session, courseId, classId, customClassSuffix, ret); iWorkers.add(w); w.start(); } } void done(Worker w) { synchronized (iWorkers) { iWorkers.remove(w); iWorkers.notify(); } } public void waitForAll() { synchronized (iWorkers) { while (!iWorkers.isEmpty()) { try { iWorkers.wait(); } catch (InterruptedException e) {} } } } class Worker extends Thread { private AcademicSessionInfo iSession; private Long iCourseId, iClassId; private String iCustomClassSuffix; private Hashtable<Long, int[]> iResults; public Worker(AcademicSessionInfo session, Long courseId, Long classId, String customClassSuffix, Hashtable<Long, int[]> ret) { iSession = session; iCourseId = courseId; iClassId = classId; iCustomClassSuffix = customClassSuffix; iResults = ret; setName("PuSectLimitP-" + classId); } public void run() { try { int[] limit = getSectionLimit(iSession, iCourseId, iClassId, iCustomClassSuffix); iResults.put(iClassId, limit); } catch (SectioningException e) { sLog.warn("Failed to retrieve section limit for "+iCustomClassSuffix+" ("+iSession.getTerm()+" "+iSession.getYear()+"): "+e.getMessage()); } finally { done(this); } } } } } --- NEW FILE: PurdueCourseDetailsProvider.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.server.custom.purdue; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.MalformedURLException; import java.net.URL; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.log4j.Logger; import org.unitime.timetable.gwt.server.AcademicSessionInfo; import org.unitime.timetable.gwt.server.custom.CourseDetailsProvider; import org.unitime.timetable.gwt.shared.SectioningException; import org.unitime.timetable.gwt.shared.SectioningExceptionType; /** * @author Tomas Muller */ public class PurdueCourseDetailsProvider implements CourseDetailsProvider { private static Logger sLog = Logger.getLogger(PurdueCourseDetailsProvider.class); public static String sUrl = "https://esa-oas-prod-wl.itap.purdue.edu/prod/bzwsrch.p_catalog_detail?term=:year:term&subject=:subject&cnbr=:courseNbr"; public static String sDummyUrl = "https://esa-oas-prod-wl.itap.purdue.edu/prod/bzwsrch.p_catalog_detail?term=201020&subject=AAE&cnbr=20300"; public static String sContentRE = "(<table [ ]*class=\"[a-z]*\" summary=\"This table lists the course detail for the selected term.\" .*)<table [ ]*class=\"[a-z]*\" summary=\"This is for formatting of the bottom links.\""; public static String[][] sRemoveRE = new String[][] { {"(?i)<a href=\"[^>]*\">", "<b>"}, {"(?i)</a>", "</b>"}, {"(?i)<span class=[\"]?fieldlabeltext[\"]?>", "<b>"}, {"(?i)</span>", "</b>"}, {"(?i) class=\"nttitle\" ", " class=\"unitime-MainTableHeader\" "}, {"(?i) class=\"datadisplaytable\" ", " class=\"unitime-MainTable\" "}, }; private String getTerm(AcademicSessionInfo session) throws SectioningException { if (session.getTerm().toLowerCase().startsWith("spr")) return "20"; if (session.getTerm().toLowerCase().startsWith("sum")) return "30"; if (session.getTerm().toLowerCase().startsWith("fal")) return "10"; throw new SectioningException(SectioningExceptionType.CUSTOM_COURSE_DETAILS_FAILURE, "academic term "+session.getTerm()+" not known"); } private String getYear(AcademicSessionInfo session) throws SectioningException { if (session.getTerm().toLowerCase().startsWith("fal")) return String.valueOf(Integer.parseInt(session.getYear()) + 1); return session.getYear(); } public String getDetails(AcademicSessionInfo session, String subject, String courseNbr) throws SectioningException { try { if (courseNbr.length() > 5) courseNbr = courseNbr.substring(0, 5); URL url = new URL(sUrl .replace(":year", getYear(session)) .replace(":term", getTerm(session)) .replace(":initiative", session.getCampus()) .replace(":subject", subject) .replace(":courseNbr", courseNbr)); return getDetails(url); } catch (MalformedURLException e) { sLog.error(e.getMessage(), e); throw new SectioningException(SectioningExceptionType.CUSTOM_COURSE_DETAILS_FAILURE, "course detail url is wrong", e); } } public String getDetails(URL courseUrl) throws SectioningException { try { BufferedReader in = new BufferedReader(new InputStreamReader(courseUrl.openStream())); StringBuffer content = new StringBuffer(); String line; while ((line = in.readLine()) != null) content.append(line); in.close(); Pattern pattern = Pattern.compile(sContentRE, Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.UNIX_LINES); Matcher match = pattern.matcher(content); if (!match.find()) throw new SectioningException(SectioningExceptionType.CUSTOM_COURSE_DETAILS_FAILURE, "unable to parse <a href='"+courseUrl+"'>course detial page</a>"); String table = match.group(1); for (int i=0; i<sRemoveRE.length; i++) table = table.replaceAll(sRemoveRE[i][0], sRemoveRE[i][1]); return table; } catch (IOException e) { sLog.error(e.getMessage(), e); throw new SectioningException(SectioningExceptionType.CUSTOM_COURSE_DETAILS_FAILURE, "unable to read <a href='"+courseUrl+"'>course detail page</a>"); } } public static void main(String[] args) { try { System.out.println(new PurdueCourseDetailsProvider().getDetails(new URL(sDummyUrl))); } catch (Exception e) { e.printStackTrace(); } } } |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/services In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/services Added Files: LookupService.java MenuService.java EventServiceAsync.java LookupServiceAsync.java EventService.java MenuServiceAsync.java CurriculaServiceAsync.java SectioningService.java SectioningServiceAsync.java CurriculaService.java SimpleEditService.java SimpleEditServiceAsync.java Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: EventService.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.List; import org.unitime.timetable.gwt.shared.EventException; import org.unitime.timetable.gwt.shared.EventInterface; import org.unitime.timetable.gwt.shared.EventInterface.IdValueInterface; import org.unitime.timetable.gwt.shared.EventInterface.ResourceInterface; import org.unitime.timetable.gwt.shared.EventInterface.ResourceType; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * @author Tomas Muller */ @RemoteServiceRelativePath("event.gwt") public interface EventService extends RemoteService { public ResourceInterface findResource(String session, ResourceType type, String name) throws EventException; public List<EventInterface> findEvents(ResourceInterface resource) throws EventException; public List<IdValueInterface> findSessions(String session) throws EventException; public List<ResourceInterface> findResources(String session, ResourceType type, String query, int limit) throws EventException; public Boolean canLookupPeople() throws EventException; } --- NEW FILE: MenuServiceAsync.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.Collection; import java.util.HashMap; import java.util.List; import org.unitime.timetable.gwt.shared.MenuException; import org.unitime.timetable.gwt.shared.MenuInterface; import com.google.gwt.user.client.rpc.AsyncCallback; /** * @author Tomas Muller */ public interface MenuServiceAsync { void getMenu(AsyncCallback<List<MenuInterface>> callback) throws MenuException; public void getUserInfo(AsyncCallback<HashMap<String, String>> callback) throws MenuException; public void getSessionInfo(AsyncCallback<HashMap<String, String>> callback) throws MenuException; public void getVersion(AsyncCallback<String> callback) throws MenuException; public void getSolverInfo(AsyncCallback<HashMap<String, String>> callback) throws MenuException; public void getHelpPage(String title, AsyncCallback<String> callback) throws MenuException; public void getUserData(String property, AsyncCallback<String> callback) throws MenuException; public void setUserData(String property, String value, AsyncCallback<Boolean> callback) throws MenuException; public void getUserData(Collection<String> property, AsyncCallback<HashMap<String, String>> callback) throws MenuException; public void setUserData(List<String[]> property2value, AsyncCallback<Boolean> callback) throws MenuException; } --- NEW FILE: LookupServiceAsync.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.List; import org.unitime.timetable.gwt.shared.LookupException; import org.unitime.timetable.gwt.shared.PersonInterface; import com.google.gwt.user.client.rpc.AsyncCallback; /** * @author Tomas Muller */ public interface LookupServiceAsync { public void lookupPeople(String query, String options, AsyncCallback<List<PersonInterface>> callback) throws LookupException; } --- NEW FILE: CurriculaService.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.unitime.timetable.gwt.shared.ClassAssignmentInterface; import org.unitime.timetable.gwt.shared.CurriculaException; import org.unitime.timetable.gwt.shared.CurriculumInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.AcademicAreaInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.AcademicClassificationInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.MajorInterface; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * @author Tomas Muller */ @RemoteServiceRelativePath("curricula.gwt") public interface CurriculaService extends RemoteService { public TreeSet<CurriculumInterface> findCurricula(String filter) throws CurriculaException; public List<CurriculumInterface.CurriculumClassificationInterface> loadClassifications(List<Long> curriculumIds) throws CurriculaException; public HashMap<String, CurriculumInterface.CurriculumStudentsInterface[]> computeEnrollmentsAndLastLikes(Long acadAreaId, List<Long> majors) throws CurriculaException; public TreeSet<CurriculumInterface.AcademicAreaInterface> loadAcademicAreas() throws CurriculaException; public TreeSet<CurriculumInterface.AcademicClassificationInterface> loadAcademicClassifications() throws CurriculaException; public TreeSet<CurriculumInterface.DepartmentInterface> loadDepartments() throws CurriculaException; public TreeSet<CurriculumInterface.MajorInterface> loadMajors(Long curriculumId, Long academicAreaId) throws CurriculaException; public String lastCurriculaFilter() throws CurriculaException; public CurriculumInterface loadCurriculum(Long curriculumId) throws CurriculaException; public Long saveCurriculum(CurriculumInterface curriculum) throws CurriculaException; public Boolean deleteCurriculum(Long curriculumId) throws CurriculaException; public Boolean deleteCurricula(Set<Long> curriculumIds) throws CurriculaException; public Boolean mergeCurricula(Set<Long> curriculumIds) throws CurriculaException; public TreeSet<CurriculumInterface> findCurriculaForACourse(String courseName) throws CurriculaException; public TreeSet<CurriculumInterface> findCurriculaForAnInstructionalOffering(Long offeringId) throws CurriculaException; public Boolean saveClassifications(List<CurriculumInterface> curricula) throws CurriculaException; public Collection<ClassAssignmentInterface.CourseAssignment> listCourseOfferings(String query, Integer limit) throws CurriculaException; public String retrieveCourseDetails(String course) throws CurriculaException; public Collection<ClassAssignmentInterface.ClassAssignment> listClasses(String course) throws CurriculaException; public String[] getApplicationProperty(String[] name) throws CurriculaException; public Boolean canAddCurriculum() throws CurriculaException; public Boolean isAdmin() throws CurriculaException; public Boolean makeupCurriculaFromLastLikeDemands(boolean lastLike) throws CurriculaException; public Boolean updateCurriculaByProjections(Set<Long> curriculumIds, boolean updateCurriculumCourses) throws CurriculaException; public Boolean populateCourseProjectedDemands(boolean includeOtherStudents) throws CurriculaException; public Boolean populateCourseProjectedDemands(boolean includeOtherStudents, Long offeringId) throws CurriculaException; public HashMap<AcademicAreaInterface, HashMap<MajorInterface, HashMap<AcademicClassificationInterface, Number[]>>> loadProjectionRules() throws CurriculaException; public Boolean saveProjectionRules(HashMap<AcademicAreaInterface, HashMap<MajorInterface, HashMap<AcademicClassificationInterface, Number[]>>> rules) throws CurriculaException; public Boolean canEditProjectionRules() throws CurriculaException; } --- NEW FILE: LookupService.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.List; import org.unitime.timetable.gwt.shared.LookupException; import org.unitime.timetable.gwt.shared.PersonInterface; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * @author Tomas Muller */ @RemoteServiceRelativePath("lookup.gwt") public interface LookupService extends RemoteService { public List<PersonInterface> lookupPeople(String query, String options) throws LookupException; } --- NEW FILE: EventServiceAsync.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.List; import org.unitime.timetable.gwt.shared.EventException; import org.unitime.timetable.gwt.shared.EventInterface; import org.unitime.timetable.gwt.shared.EventInterface.IdValueInterface; import org.unitime.timetable.gwt.shared.EventInterface.ResourceInterface; import org.unitime.timetable.gwt.shared.EventInterface.ResourceType; import com.google.gwt.user.client.rpc.AsyncCallback; /** * @author Tomas Muller */ public interface EventServiceAsync { public void findResource(String session, ResourceType type, String name, AsyncCallback<ResourceInterface> callback) throws EventException; public void findEvents(ResourceInterface resource, AsyncCallback<List<EventInterface>> callback) throws EventException; public void findSessions(String session, AsyncCallback<List<IdValueInterface>> callback) throws EventException; public void findResources(String session, ResourceType type, String query, int limit, AsyncCallback<List<ResourceInterface>> callback) throws EventException; public void canLookupPeople(AsyncCallback<Boolean> callback) throws EventException; } --- NEW FILE: CurriculaServiceAsync.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Set; import java.util.TreeSet; import org.unitime.timetable.gwt.shared.ClassAssignmentInterface; import org.unitime.timetable.gwt.shared.CurriculaException; import org.unitime.timetable.gwt.shared.CurriculumInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.AcademicAreaInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.AcademicClassificationInterface; import org.unitime.timetable.gwt.shared.CurriculumInterface.MajorInterface; import com.google.gwt.user.client.rpc.AsyncCallback; /** * @author Tomas Muller */ public interface CurriculaServiceAsync { public void findCurricula(String filter, AsyncCallback<TreeSet<CurriculumInterface>> callback) throws CurriculaException; public void loadClassifications(List<Long> curriculumIds, AsyncCallback<List<CurriculumInterface.CurriculumClassificationInterface>> callback) throws CurriculaException; public void computeEnrollmentsAndLastLikes(Long acadAreaId, List<Long> majors, AsyncCallback<HashMap<String, CurriculumInterface.CurriculumStudentsInterface[]>> callback) throws CurriculaException; public void loadAcademicAreas(AsyncCallback<TreeSet<CurriculumInterface.AcademicAreaInterface>> callback) throws CurriculaException; public void loadAcademicClassifications(AsyncCallback<TreeSet<CurriculumInterface.AcademicClassificationInterface>> callback) throws CurriculaException; public void loadDepartments(AsyncCallback<TreeSet<CurriculumInterface.DepartmentInterface>> callback) throws CurriculaException; public void loadMajors(Long curriculumId, Long academicAreaId, AsyncCallback<TreeSet<CurriculumInterface.MajorInterface>> callback) throws CurriculaException; public void lastCurriculaFilter(AsyncCallback<String> callback) throws CurriculaException; public void loadCurriculum(Long curriculumId, AsyncCallback<CurriculumInterface> callback) throws CurriculaException; public void saveCurriculum(CurriculumInterface curriculum, AsyncCallback<Long> callback) throws CurriculaException; public void deleteCurriculum(Long curriculumId, AsyncCallback<Boolean> callback) throws CurriculaException; public void deleteCurricula(Set<Long> curriculumIds, AsyncCallback<Boolean> callback) throws CurriculaException; public void mergeCurricula(Set<Long> curriculumIds, AsyncCallback<Boolean> callback) throws CurriculaException; public void findCurriculaForACourse(String courseName, AsyncCallback<TreeSet<CurriculumInterface>> callback) throws CurriculaException; public void findCurriculaForAnInstructionalOffering(Long offeringId, AsyncCallback<TreeSet<CurriculumInterface>> callback) throws CurriculaException; public void saveClassifications(List<CurriculumInterface> curricula, AsyncCallback<Boolean> callback) throws CurriculaException; public void listCourseOfferings(String query, Integer limit, AsyncCallback<Collection<ClassAssignmentInterface.CourseAssignment>> callback) throws CurriculaException; public void retrieveCourseDetails(String course, AsyncCallback<String> callback) throws CurriculaException; public void listClasses(String course, AsyncCallback<Collection<ClassAssignmentInterface.ClassAssignment>> callback) throws CurriculaException; public void getApplicationProperty(String[] name, AsyncCallback<String[]> callback) throws CurriculaException; public void canAddCurriculum(AsyncCallback<Boolean> callback) throws CurriculaException; public void isAdmin(AsyncCallback<Boolean> callback) throws CurriculaException; public void makeupCurriculaFromLastLikeDemands(boolean lastLike, AsyncCallback<Boolean> callback) throws CurriculaException; public void updateCurriculaByProjections(Set<Long> curriculumIds, boolean updateCurriculumCourses, AsyncCallback<Boolean> callback) throws CurriculaException; public void populateCourseProjectedDemands(boolean includeOtherStudents, AsyncCallback<Boolean> callback) throws CurriculaException; public void populateCourseProjectedDemands(boolean includeOtherStudents, Long offeringId, AsyncCallback<Boolean> callback) throws CurriculaException; public void loadProjectionRules(AsyncCallback<HashMap<AcademicAreaInterface, HashMap<MajorInterface, HashMap<AcademicClassificationInterface, Number[]>>>> callback) throws CurriculaException; public void saveProjectionRules(HashMap<AcademicAreaInterface, HashMap<MajorInterface, HashMap<AcademicClassificationInterface, Number[]>>> rules, AsyncCallback<Boolean> callback) throws CurriculaException; public void canEditProjectionRules(AsyncCallback<Boolean> callback) throws CurriculaException; } --- NEW FILE: SectioningService.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.ArrayList; import java.util.Collection; import org.unitime.timetable.gwt.shared.ClassAssignmentInterface; import org.unitime.timetable.gwt.shared.CourseRequestInterface; import org.unitime.timetable.gwt.shared.SectioningException; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * @author Tomas Muller */ @RemoteServiceRelativePath("sectioning.gwt") public interface SectioningService extends RemoteService { Collection<ClassAssignmentInterface.CourseAssignment> listCourseOfferings(Long sessionId, String query, Integer limit) throws SectioningException; Collection<String[]> listAcademicSessions(boolean sectioning) throws SectioningException; String retrieveCourseDetails(Long sessionId, String course) throws SectioningException; Collection<ClassAssignmentInterface.ClassAssignment> listClasses(Long sessionId, String course) throws IllegalArgumentException; Long retrieveCourseOfferingId(Long sessionId, String course) throws SectioningException; Collection<String> checkCourses(CourseRequestInterface request) throws SectioningException; ClassAssignmentInterface section(CourseRequestInterface request, ArrayList<ClassAssignmentInterface.ClassAssignment> currentAssignment) throws SectioningException; Collection<ClassAssignmentInterface> computeSuggestions(CourseRequestInterface request, Collection<ClassAssignmentInterface.ClassAssignment> currentAssignment, int selectedAssignment) throws SectioningException; String logIn(String userName, String password) throws SectioningException; Boolean logOut() throws SectioningException; String whoAmI() throws SectioningException; String[] lastAcademicSession(boolean sectioning) throws SectioningException; CourseRequestInterface lastRequest(Long sessionId) throws SectioningException; ArrayList<ClassAssignmentInterface.ClassAssignment> lastResult(Long sessionId) throws SectioningException; Boolean saveRequest(CourseRequestInterface request) throws SectioningException; ArrayList<Long> enroll(CourseRequestInterface request, ArrayList<ClassAssignmentInterface.ClassAssignment> currentAssignment) throws SectioningException; public Boolean isAdmin() throws SectioningException; } --- NEW FILE: SectioningServiceAsync.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.ArrayList; import java.util.Collection; import org.unitime.timetable.gwt.shared.ClassAssignmentInterface; import org.unitime.timetable.gwt.shared.CourseRequestInterface; import org.unitime.timetable.gwt.shared.SectioningException; import com.google.gwt.user.client.rpc.AsyncCallback; /** * @author Tomas Muller */ public interface SectioningServiceAsync { void listCourseOfferings(Long sessionId, String query, Integer limit, AsyncCallback<Collection<ClassAssignmentInterface.CourseAssignment>> callback) throws SectioningException; void listAcademicSessions(boolean sectioning, AsyncCallback<Collection<String[]>> callback) throws SectioningException; void retrieveCourseDetails(Long sessionId, String course, AsyncCallback<String> callback) throws SectioningException; void listClasses(Long sessionId, String course, AsyncCallback<Collection<ClassAssignmentInterface.ClassAssignment>> callback) throws IllegalArgumentException; void retrieveCourseOfferingId(Long sessionId, String course, AsyncCallback<Long> callback) throws SectioningException; void section(CourseRequestInterface request, ArrayList<ClassAssignmentInterface.ClassAssignment> currentAssignment, AsyncCallback<ClassAssignmentInterface> callback) throws SectioningException; void checkCourses(CourseRequestInterface request, AsyncCallback<Collection<String>> callback) throws SectioningException; void computeSuggestions(CourseRequestInterface request, Collection<ClassAssignmentInterface.ClassAssignment> currentAssignment, int selectedAssignment, AsyncCallback<Collection<ClassAssignmentInterface>> callback) throws SectioningException; void logIn(String userName, String password, AsyncCallback<String> callback) throws SectioningException; void logOut(AsyncCallback<Boolean> callback) throws SectioningException; void whoAmI(AsyncCallback<String> callback) throws SectioningException; void lastAcademicSession(boolean sectioning, AsyncCallback<String[]> callback) throws SectioningException; void lastRequest(Long sessionId, AsyncCallback<CourseRequestInterface> callback) throws SectioningException; void lastResult(Long sessionId, AsyncCallback<ArrayList<ClassAssignmentInterface.ClassAssignment>> callback) throws SectioningException; void saveRequest(CourseRequestInterface request, AsyncCallback<Boolean> callback) throws SectioningException; void enroll(CourseRequestInterface request, ArrayList<ClassAssignmentInterface.ClassAssignment> currentAssignment, AsyncCallback<ArrayList<Long>> callback) throws SectioningException; void isAdmin(AsyncCallback<Boolean> isAdmin) throws SectioningException; } --- NEW FILE: SimpleEditServiceAsync.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import org.unitime.timetable.gwt.shared.SimpleEditException; import org.unitime.timetable.gwt.shared.SimpleEditInterface; import com.google.gwt.user.client.rpc.AsyncCallback; /** * @author Tomas Muller */ public interface SimpleEditServiceAsync { public void load(SimpleEditInterface.Type type, AsyncCallback<SimpleEditInterface> callback) throws SimpleEditException; public void save(SimpleEditInterface data, AsyncCallback<SimpleEditInterface> callback) throws SimpleEditException; } --- NEW FILE: MenuService.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import java.util.Collection; import java.util.HashMap; import java.util.List; import org.unitime.timetable.gwt.shared.MenuException; import org.unitime.timetable.gwt.shared.MenuInterface; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * @author Tomas Muller */ @RemoteServiceRelativePath("menu.gwt") public interface MenuService extends RemoteService { public List<MenuInterface> getMenu() throws MenuException; public HashMap<String, String> getUserInfo() throws MenuException; public HashMap<String, String> getSessionInfo() throws MenuException; public String getVersion() throws MenuException; public HashMap<String, String> getSolverInfo() throws MenuException; public String getHelpPage(String title) throws MenuException; public String getUserData(String property) throws MenuException; public Boolean setUserData(String property, String value) throws MenuException; public HashMap<String, String> getUserData(Collection<String> property) throws MenuException; public Boolean setUserData(List<String[]> property2value) throws MenuException; } --- NEW FILE: SimpleEditService.java --- /* * UniTime 3.2 (University Timetabling Application) * Copyright (C) 2010, 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.gwt.services; import org.unitime.timetable.gwt.shared.SimpleEditException; import org.unitime.timetable.gwt.shared.SimpleEditInterface; import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; /** * @author Tomas Muller */ @RemoteServiceRelativePath("simpleEdit.gwt") public interface SimpleEditService extends RemoteService { public SimpleEditInterface load(SimpleEditInterface.Type type) throws SimpleEditException; public SimpleEditInterface save(SimpleEditInterface data) throws SimpleEditException; } |
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/gwt/resources/icons In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/JavaSource/org/unitime/timetable/gwt/resources/icons Added Files: minimize_RO.gif down_Over.png action_add.png blank_Over_big.png lock_unlock.png help_icon.gif openMenu_RO.gif collapse_node_btn.gif loading.gif search_picker_Down.png action_delete.png application.png loading_small.gif search_picker_Disabled.png lock_disabled.png roadrunner16.png search_picker_Over.png down_Down.png openMenu.gif up_Down.png search_picker_Normal.png lock.png down.png blank.png up.png save.png blank_Down_big.png letter.png comments.png roadrunner32.png expand_node_btn.gif printer.png blank_big.png search_picker.png group.png up_Over.png minimize.gif end_node_btn.gif Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: minimize.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: down_Over.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: roadrunner32.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: lock_disabled.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: up_Over.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: blank_big.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: search_picker.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: search_picker_Disabled.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: expand_node_btn.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: up_Down.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: end_node_btn.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: letter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: printer.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: comments.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: loading.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: blank_Down_big.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: help_icon.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: blank.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: loading_small.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: action_delete.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: lock_unlock.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: openMenu.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: down_Down.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: openMenu_RO.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: up.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: application.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: search_picker_Down.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: down.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: collapse_node_btn.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: lock.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: action_add.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: blank_Over_big.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: search_picker_Normal.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: group.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: save.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: minimize_RO.gif --- (This appears to be a binary file; contents omitted.) --- NEW FILE: roadrunner16.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: search_picker_Over.png --- (This appears to be a binary file; contents omitted.) |
Update of /cvsroot/unitime/UniTime/Documentation/Images In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv13954/Documentation/Images Added Files: AddEventInfo.png AddSubjectArea.png EditRoomGroup.png EventRoomAvailability_filter.png MultipleClassSetup.png AssignInstructors.png MenuCourses.png EditExaminationDistributionPreferences.png StudentSchedulingAssistant_alternatives.png AddExaminationPeriod.png AddRoom.png Examinations.png CourseReservations.png Chameleon.png DesignatorList.png EditSponsoringOrganization.png EditSolverConfiguration.png TimetableManagers.png MenuHelp.png NotAssignedClasses.png EditDistributionPreference.png EditRoomType.png AddSponsoringOrganization.png Users.png EditAcademicSession.png InstructionalTypes.png DatePatterns.png MidtermExaminationPeriods.png Suggestions_suggestions.png ExaminationAssignmentChanges.png InstructionalOfferingDetail.png ClassDetail.png CourseFinder.png EventDetail.png SolverStatus.png Departments.png Meetings_filter.png AddAcademicSession.png AcademicAreas.png EditInstructionalType.png AddSolverParameter.png EditBuilding.png EditSchedulingSubpart.png PersonalSchedule.png EditCurriculum.png EditSolverParameterGroup.png AddBuilding.png InstructorDetail.png EditUser.png SelectAcademicSession.png MenuPreferences.png ExaminationDetail.png AddDatePattern.png DefaultManagerSettings.png SubjectAreas.png CourseReservations_class.png EditDistributionType.png SolverParameters.png ClassAssignments.png AddRoomGroup.png EditExaminationPeriod.png ExaminationDistributionPreferences.png StudentSchedulinhAssistant_timetable.png SolverParameterGroups.png AddDesignator.png Buildings.png EditRoomFeatures.png AssignedExaminations.png EditStandardEventNote.png ManagerSettings.png Suggestions_filter.png EditTimetableManager.png AddDistributionPreference.png StatusTypes.png DistributionPreferences.png ExaminationPDFReports.png Majors.png Solver.png RoomFeatures.png CurriculumRequestedEnrollments.png SolverConfigurations.png ExaminationSolver.png StudentSchedulingAssistant_finder.png SelectUserRole.png TimePatterns.png AddSpecialUseRoom.png Classes.png EditDefaultManagerSetting.png Suggestions_assignment.png AddDefaultManagerSetting.png RoomGroups.png InstructionalOfferings_filter.png Instructors.png Events_filter.png AddSolverParameterGroup.png Timetables.png RollForwardSession.png EditInstructor_lookup.png ClassSchedule.png InstructorPreferences.png EditStatusType.png Timetable.png CurrentUser.png TestHQL.png EditRoomAvailability.png AddStandardEventNote.png Meetings.png AddNonUniversityLocation.png ExaminationSolverLog.png HibernateStatistics.png EditRoom.png MenuAdmin.png StudentSchedulingAssistant_classes.png Reservations.png Events.png ApplicationConfiguration.png ConflictStatistics.png EditSolverGroup.png SchedulingSubpartDetail.png UpdateMeetings.png ManageInstructorList.png AcademicSessions.png EditSolverParameter.png AddRoomType.png CurriculumProjectionRules.png ContactUs.png StudentSchedulingAssistant_ftime.png PeopleLookup.png ClassAssignment.png SponsoringOrganizations.png Suggestions.png EditRoomGroups.png EditRoomDepartments.png SolverGroups.png AddUser.png AssignedClasses.png MenuStudents.png AddTimePattern.png InstructionalOfferingCrossLists.png CurriculumDetail.png RoomDetail.png AddExamination.png ExaminationPeriods.png ExaminationAssignment.png AddExaminationDistributionPreference.png History.png AddEventMeetings.png Edit Department.png EditExamination.png ExactTimePattern.png AddSolverConfiguration.png AddRoomFeature.png RoomTypes.png Menu.png AddInstructionalType.png EditDesignator.png EditInstructor.png EnrollmentAuditPDFReports.png EditSubjectArea.png ExaminationTimetable.png EditApplicationSetting.png EditCourseOffering.png AddInstructor.png StudentSectioningSolverLog.png DataExchange.png EditRoomPreference.png ExaminationConflictBasedStatistics.png ExaminationSchedule.png LastChanges.png AddTimetableManager.png DistributionTypes.png InstructionalOfferingConfiguration.png EditEvent.png Changes.png RoomAvailability.png StudentSchedulingAssistant.png Classes_filter.png Curricula.png AcademicAreaReservations.png EventRoomAvailability.png StandardEventNotes.png SolverLog.png EditManagerSetting.png AddSolverGroup.png EditRoomFeature.png StudentSectioningSolver.png EditClass.png EditTimePattern.png AddCurriculum.png ExaminationReports.png AddStatusType.png EditDatePattern.png Minors.png ExaminationTimetable_filter.png ManageSolvers.png MenuEvents.png AddApplicationSetting.png InstructionalOfferings.png EventRoomSelection.png MenuExams.png AcademicClassifications.png SolutionReports.png NotAssignedExaminations.png Add Department.png Rooms.png Removed Files: banner.png loading.png logo-external.png check-all.png crown.png bkrnd-header.png bkrnd-page.png help.png login.png tick.png Log Message: UniTime 3.1 moved to branch maint_UniTime31 UniTime 3.2 merged from dev_curricula back to main branch (HEAD) --- NEW FILE: AddDefaultManagerSetting.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Majors.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SolverGroups.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ClassAssignment.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditSchedulingSubpart.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: DistributionTypes.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddSpecialUseRoom.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: RollForwardSession.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Classes.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Curricula.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: CourseReservations_class.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: CurrentUser.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SolverStatus.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomGroups.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StudentSchedulingAssistant_ftime.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Meetings_filter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddEventInfo.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: InstructorDetail.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationReports.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditBuilding.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditInstructionalType.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: DefaultManagerSettings.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditTimetableManager.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ManagerSettings.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddRoomFeature.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddDatePattern.png --- (This appears to be a binary file; contents omitted.) --- logo-external.png DELETED --- --- NEW FILE: AddTimePattern.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Chameleon.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: InstructionalOfferingDetail.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Events_filter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StandardEventNotes.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditSolverGroup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: RoomDetail.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ClassAssignments.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: History.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddCurriculum.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditTimePattern.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddSolverGroup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Departments.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditStatusType.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: RoomTypes.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: HibernateStatistics.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditDistributionPreference.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Add Department.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Meetings.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditSponsoringOrganization.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ClassDetail.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EnrollmentAuditPDFReports.png --- (This appears to be a binary file; contents omitted.) --- check-all.png DELETED --- --- NEW FILE: SubjectAreas.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditUser.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StudentSectioningSolver.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditSubjectArea.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AcademicSessions.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddRoom.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditSolverParameter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditDesignator.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MenuAdmin.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddAcademicSession.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditSolverConfiguration.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MidtermExaminationPeriods.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditInstructor.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomGroup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: PersonalSchedule.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EventDetail.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationTimetable_filter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SolverParameterGroups.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: LastChanges.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationDistributionPreferences.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditStandardEventNote.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SolutionReports.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddStatusType.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditDatePattern.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: DistributionPreferences.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ManageSolvers.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EventRoomAvailability_filter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: DesignatorList.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SelectUserRole.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: InstructionalOfferingCrossLists.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditDefaultManagerSetting.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Buildings.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AssignedExaminations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EventRoomAvailability.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Changes.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddSubjectArea.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: TestHQL.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StudentSectioningSolverLog.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AcademicAreas.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddDistributionPreference.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditExamination.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StatusTypes.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MenuStudents.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExactTimePattern.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Suggestions_suggestions.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditClass.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditCurriculum.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: TimePatterns.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Menu.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: InstructionalTypes.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddNonUniversityLocation.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Suggestions_filter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ApplicationConfiguration.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddUser.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MenuEvents.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: CurriculumDetail.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: CurriculumProjectionRules.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Timetables.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ConflictStatistics.png --- (This appears to be a binary file; contents omitted.) --- bkrnd-page.png DELETED --- --- NEW FILE: SolverParameters.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Users.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoom.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: RoomGroups.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ClassSchedule.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomFeature.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SolverConfigurations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Examinations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StudentSchedulingAssistant_alternatives.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddSolverParameterGroup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditEvent.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SelectAcademicSession.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomDepartments.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomFeatures.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: CourseFinder.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditInstructor_lookup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: InstructionalOfferings_filter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddRoomType.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SponsoringOrganizations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddApplicationSetting.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Instructors.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Suggestions_assignment.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Events.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditSolverParameterGroup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomType.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddDesignator.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationConflictBasedStatistics.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: NotAssignedClasses.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ManageInstructorList.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MenuHelp.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: PeopleLookup.png --- (This appears to be a binary file; contents omitted.) --- help.png DELETED --- --- NEW FILE: EditApplicationSetting.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddInstructionalType.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationAssignment.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomAvailability.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MenuPreferences.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationPeriods.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AssignInstructors.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: DataExchange.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditDistributionType.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationSolver.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StudentSchedulingAssistant_finder.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditExaminationDistributionPreferences.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Minors.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddSponsoringOrganization.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationDetail.png --- (This appears to be a binary file; contents omitted.) --- banner.png DELETED --- --- NEW FILE: StudentSchedulingAssistant.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddEventMeetings.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationTimetable.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: UpdateMeetings.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditCourseOffering.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StudentSchedulingAssistant_classes.png --- (This appears to be a binary file; contents omitted.) --- crown.png DELETED --- --- loading.png DELETED --- --- NEW FILE: InstructorPreferences.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Solver.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MenuExams.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: StudentSchedulinhAssistant_timetable.png --- (This appears to be a binary file; contents omitted.) --- tick.png DELETED --- --- NEW FILE: DatePatterns.png --- (This appears to be a binary file; contents omitted.) --- bkrnd-header.png DELETED --- --- NEW FILE: SchedulingSubpartDetail.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditExaminationPeriod.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddExaminationPeriod.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationSolverLog.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ContactUs.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditRoomPreference.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: CourseReservations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: InstructionalOfferingConfiguration.png --- (This appears to be a binary file; contents omitted.) --- login.png DELETED --- --- NEW FILE: MultipleClassSetup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: CurriculumRequestedEnrollments.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditAcademicSession.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Timetable.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddRoomGroup.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Rooms.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: RoomAvailability.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddExaminationDistributionPreference.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: InstructionalOfferings.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Edit Department.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Classes_filter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Suggestions.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: Reservations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationAssignmentChanges.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationPDFReports.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddInstructor.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AcademicClassifications.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddTimetableManager.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: ExaminationSchedule.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: NotAssignedExaminations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: RoomFeatures.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddSolverConfiguration.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AcademicAreaReservations.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: MenuCourses.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EditManagerSetting.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: SolverLog.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddSolverParameter.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddStandardEventNote.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: TimetableManagers.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddBuilding.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AddExamination.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: AssignedClasses.png --- (This appears to be a binary file; contents omitted.) --- NEW FILE: EventRoomSelection.png --- (This appears to be a binary file; contents omitted.) |
|
From: Tomas M. <to...@us...> - 2010-12-01 08:53:25
|
Update of /cvsroot/unitime/UniTime In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv19275 Modified Files: build.number Log Message: The last build of UniTime 3.1 (number 291) released. Index: build.number =================================================================== RCS file: /cvsroot/unitime/UniTime/build.number,v retrieving revision 1.26 retrieving revision 1.27 diff -C2 -d -r1.26 -r1.27 *** build.number 19 Oct 2010 14:32:48 -0000 1.26 --- build.number 1 Dec 2010 08:53:17 -0000 1.27 *************** *** 1,3 **** #Build Number for ANT. Do not edit! ! #Tue Oct 19 01:00:34 CEST 2010 ! build.number=285 --- 1,3 ---- #Build Number for ANT. Do not edit! ! #Thu Nov 25 01:01:05 CET 2010 ! build.number=292 |
|
From: Tomas M. <to...@us...> - 2010-12-01 08:49:20
|
Update of /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/dataexchange In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv18242/JavaSource/org/unitime/timetable/dataexchange Modified Files: Tag: dev_curriculum EventRelatedImports.java StudentEnrollmentImport.java BaseCourseOfferingImport.java EventImport.java BuildingRoomImport.java Log Message: Various imports - use getManager() from the BaseImport rather than using findDefaultManager() - this way, the manager that initiated the import will be emailed Index: StudentEnrollmentImport.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/dataexchange/StudentEnrollmentImport.java,v retrieving revision 1.14.2.6 retrieving revision 1.14.2.7 diff -C2 -d -r1.14.2.6 -r1.14.2.7 *** StudentEnrollmentImport.java 9 Nov 2010 12:25:46 -0000 1.14.2.6 --- StudentEnrollmentImport.java 1 Dec 2010 08:49:12 -0000 1.14.2.7 *************** *** 36,40 **** import org.unitime.timetable.model.StudentClassEnrollment; import org.unitime.timetable.model.StudentSectioningQueue; - import org.unitime.timetable.model.TimetableManager; import org.unitime.timetable.model.dao.StudentDAO; import org.unitime.timetable.test.UpdateExamConflicts; --- 36,39 ---- *************** *** 84,93 **** debug("classes loaded"); - TimetableManager manger = getManager(); - if (manger == null) - manger = findDefaultManager(); - if (created != null) ! ChangeLog.addChange(getHibSession(), manger, session, session, created, ChangeLog.Source.DATA_IMPORT_STUDENT_ENROLLMENTS, ChangeLog.Operation.UPDATE, null, null); Hashtable<String, Student> students = new Hashtable<String, Student>(); --- 83,88 ---- debug("classes loaded"); if (created != null) ! ChangeLog.addChange(getHibSession(), getManager(), session, session, created, ChangeLog.Source.DATA_IMPORT_STUDENT_ENROLLMENTS, ChangeLog.Operation.UPDATE, null, null); Hashtable<String, Student> students = new Hashtable<String, Student>(); Index: BaseCourseOfferingImport.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/dataexchange/BaseCourseOfferingImport.java,v retrieving revision 1.10.2.6 retrieving revision 1.10.2.7 diff -C2 -d -r1.10.2.6 -r1.10.2.7 *** BaseCourseOfferingImport.java 30 Nov 2010 21:18:43 -0000 1.10.2.6 --- BaseCourseOfferingImport.java 1 Dec 2010 08:49:12 -0000 1.10.2.7 *************** *** 368,372 **** initializeMeetsWith(rootElement); initializeCanShareRoom(rootElement); - initializeManager(); initializeAssignmentHelper(); loadSetupData(); --- 368,371 ---- *************** *** 378,382 **** if (created != null) { addNote("Loading offerings XML file created on: " + created); ! ChangeLog.addChange(getHibSession(), manager, session, session, created, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, null, null); updateChangeList(true); } --- 377,381 ---- if (created != null) { addNote("Loading offerings XML file created on: " + created); ! ChangeLog.addChange(getHibSession(), getManager(), session, session, created, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, null, null); updateChangeList(true); } *************** *** 387,396 **** } - protected void initializeManager() { - if (manager == null){ - manager = findDefaultManager(); - } - } - protected void initializeMeetsWith(Element rootElement) { Boolean useMeetsWith = getOptionalBooleanAttribute(rootElement, "useMeetsWith"); --- 386,389 ---- *************** *** 596,600 **** if (changed){ this.getHibSession().saveOrUpdate(io); ! ChangeLog.addChange(getHibSession(), manager, session, io, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (action.equalsIgnoreCase("insert")?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), io.getControllingCourseOffering().getSubjectArea(), io.getDepartment()); } --- 589,593 ---- if (changed){ this.getHibSession().saveOrUpdate(io); ! ChangeLog.addChange(getHibSession(), getManager(), session, io, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (action.equalsIgnoreCase("insert")?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), io.getControllingCourseOffering().getSubjectArea(), io.getDepartment()); } *************** *** 683,687 **** this.getHibSession().flush(); this.getHibSession().refresh(dp); ! ChangeLog.addChange(getHibSession(), manager, session, dp, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } if (dp.isDefault()){ --- 676,680 ---- this.getHibSession().flush(); this.getHibSession().refresh(dp); ! ChangeLog.addChange(getHibSession(), getManager(), session, dp, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } if (dp.isDefault()){ *************** *** 1039,1043 **** getHibSession().flush(); getHibSession().refresh(di); ! ChangeLog.addChange(getHibSession(), manager, session, di, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } ci = new ClassInstructor(); --- 1032,1036 ---- getHibSession().flush(); getHibSession().refresh(di); ! ChangeLog.addChange(getHibSession(), getManager(), session, di, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } ci = new ClassInstructor(); *************** *** 1068,1072 **** getHibSession().flush(); getHibSession().refresh(c); ! ChangeLog.addChange(getHibSession(), manager, session, ci, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (addNew?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } } --- 1061,1065 ---- getHibSession().flush(); getHibSession().refresh(c); ! ChangeLog.addChange(getHibSession(), getManager(), session, ci, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (addNew?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } } *************** *** 1128,1132 **** getHibSession().flush(); getHibSession().refresh(io); ! ChangeLog.addChange(getHibSession(), manager, session, io.getCredit(), ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, io.getControllingCourseOffering().getSubjectArea(), io.getControllingCourseOffering().getDepartment()); } } --- 1121,1125 ---- getHibSession().flush(); getHibSession().refresh(io); ! ChangeLog.addChange(getHibSession(), getManager(), session, io.getCredit(), ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, io.getControllingCourseOffering().getSubjectArea(), io.getControllingCourseOffering().getDepartment()); } } *************** *** 1172,1176 **** getHibSession().flush(); getHibSession().refresh(ss); ! ChangeLog.addChange(getHibSession(), manager, session, ss.getCredit(), ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, ss.getControllingCourseOffering().getSubjectArea(), ss.getControllingCourseOffering().getDepartment()); } } --- 1165,1169 ---- getHibSession().flush(); getHibSession().refresh(ss); ! ChangeLog.addChange(getHibSession(), getManager(), session, ss.getCredit(), ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, ss.getControllingCourseOffering().getSubjectArea(), ss.getControllingCourseOffering().getDepartment()); } } *************** *** 1303,1307 **** getHibSession().flush(); getHibSession().refresh(io); ! ChangeLog.addChange(getHibSession(), manager, session, co, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, co.getSubjectArea(), co.getDepartment()); handleCustomCourseChildElements(co, ico.getElement()); } --- 1296,1300 ---- getHibSession().flush(); getHibSession().refresh(io); ! ChangeLog.addChange(getHibSession(), getManager(), session, co, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, co.getSubjectArea(), co.getDepartment()); handleCustomCourseChildElements(co, ico.getElement()); } *************** *** 1369,1373 **** } if(changed){ ! ChangeLog.addChange(getHibSession(), manager, session, oco, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, oco.getSubjectArea(), oco.getDepartment()); } } --- 1362,1366 ---- } if(changed){ ! ChangeLog.addChange(getHibSession(), getManager(), session, oco, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, oco.getSubjectArea(), oco.getDepartment()); } } *************** *** 1390,1394 **** getHibSession().refresh(io); handleCustomCourseChildElements(nco, ico.getElement()); ! ChangeLog.addChange(getHibSession(), manager, session, nco, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, nco.getSubjectArea(), nco.getDepartment()); } } --- 1383,1387 ---- getHibSession().refresh(io); handleCustomCourseChildElements(nco, ico.getElement()); ! ChangeLog.addChange(getHibSession(), getManager(), session, nco, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, nco.getSubjectArea(), nco.getDepartment()); } } *************** *** 1508,1512 **** if (changed){ addNote("\tconfig element changed: " + name); ! ChangeLog.addChange(getHibSession(), manager, session, ioc, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (addNew?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), ioc.getControllingCourseOffering().getSubjectArea(), ioc.getControllingCourseOffering().getDepartment()); this.getHibSession().saveOrUpdate(ioc); } --- 1501,1505 ---- if (changed){ addNote("\tconfig element changed: " + name); ! ChangeLog.addChange(getHibSession(), getManager(), session, ioc, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (addNew?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), ioc.getControllingCourseOffering().getSubjectArea(), ioc.getControllingCourseOffering().getDepartment()); this.getHibSession().saveOrUpdate(ioc); } *************** *** 1834,1838 **** } if (changed){ ! ChangeLog.addChange(getHibSession(), manager, session, clazz, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (isAdd?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), ioc.getControllingCourseOffering().getSubjectArea(), ioc.getDepartment()); } } --- 1827,1831 ---- } if (changed){ ! ChangeLog.addChange(getHibSession(), getManager(), session, clazz, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (isAdd?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), ioc.getControllingCourseOffering().getSubjectArea(), ioc.getDepartment()); } } *************** *** 1989,1993 **** getHibSession().flush(); getHibSession().refresh(dp); ! ChangeLog.addChange(getHibSession(), manager, session, dp, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, null, clazz.getSchedulingSubpart().getControllingDept()); } --- 1982,1986 ---- getHibSession().flush(); getHibSession().refresh(dp); ! ChangeLog.addChange(getHibSession(), getManager(), session, dp, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, null, clazz.getSchedulingSubpart().getControllingDept()); } *************** *** 2018,2022 **** changed = true; addNote("\tdid not find matching event, added new event: " + c.getSchedulingSubpart().getInstrOfferingConfig().getCourseName() + " " + c.getSchedulingSubpart().getItype().getAbbv().trim() + " " + c.getClassSuffix()); ! ChangeLog.addChange(getHibSession(), manager, session, newEvent, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } else if (origEvent!=null) { if (!origEvent.getEventName().equals(c.getSchedulingSubpart().getInstrOfferingConfig().getCourseName() + " " + c.getSchedulingSubpart().getItype().getAbbv().trim() + " " + c.getClassSuffix())){ --- 2011,2015 ---- changed = true; addNote("\tdid not find matching event, added new event: " + c.getSchedulingSubpart().getInstrOfferingConfig().getCourseName() + " " + c.getSchedulingSubpart().getItype().getAbbv().trim() + " " + c.getClassSuffix()); ! ChangeLog.addChange(getHibSession(), getManager(), session, newEvent, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.CREATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); } else if (origEvent!=null) { if (!origEvent.getEventName().equals(c.getSchedulingSubpart().getInstrOfferingConfig().getCourseName() + " " + c.getSchedulingSubpart().getItype().getAbbv().trim() + " " + c.getClassSuffix())){ *************** *** 2068,2072 **** origEvent.getMeetings().remove(m); m.setEvent(null); ! ChangeLog.addChange(getHibSession(), manager, session, m, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); getHibSession().delete(m); changed = true; --- 2061,2065 ---- origEvent.getMeetings().remove(m); m.setEvent(null); ! ChangeLog.addChange(getHibSession(), getManager(), session, m, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); getHibSession().delete(m); changed = true; *************** *** 2075,2079 **** if (changed){ assignmentHelper.createAssignment(origEvent); ! ChangeLog.addChange(getHibSession(), manager, session, origEvent, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); getHibSession().update(origEvent); } --- 2068,2072 ---- if (changed){ assignmentHelper.createAssignment(origEvent); ! ChangeLog.addChange(getHibSession(), getManager(), session, origEvent, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, c.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), c.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); getHibSession().update(origEvent); } *************** *** 2201,2205 **** } if (changed){ ! ChangeLog.addChange(getHibSession(), manager, session, ss, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (isAdd?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), ioc.getControllingCourseOffering().getSubjectArea(), ioc.getDepartment()); } } --- 2194,2198 ---- } if (changed){ ! ChangeLog.addChange(getHibSession(), getManager(), session, ss, ChangeLog.Source.DATA_IMPORT_OFFERINGS, (isAdd?ChangeLog.Operation.CREATE:ChangeLog.Operation.UPDATE), ioc.getControllingCourseOffering().getSubjectArea(), ioc.getDepartment()); } } *************** *** 2214,2218 **** if(parentSubpart != null) { this.getHibSession().saveOrUpdate(parentSubpart); ! ChangeLog.addChange(getHibSession(), manager, session, parentSubpart, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, ioc.getControllingCourseOffering().getSubjectArea(), ioc.getDepartment()); } changed = true; --- 2207,2211 ---- if(parentSubpart != null) { this.getHibSession().saveOrUpdate(parentSubpart); ! ChangeLog.addChange(getHibSession(), getManager(), session, parentSubpart, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.UPDATE, ioc.getControllingCourseOffering().getSubjectArea(), ioc.getDepartment()); } changed = true; *************** *** 2258,2262 **** getHibSession().saveOrUpdate(pg); } ! ChangeLog.addChange(getHibSession(), manager, session, dp, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, null, dept); getHibSession().delete(dp); getHibSession().saveOrUpdate(dept); --- 2251,2255 ---- getHibSession().saveOrUpdate(pg); } ! ChangeLog.addChange(getHibSession(), getManager(), session, dp, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, null, dept); getHibSession().delete(dp); getHibSession().saveOrUpdate(dept); *************** *** 2264,2268 **** // for (Iterator i=relatedInstructionalOfferings.iterator();i.hasNext();) { // InstructionalOffering io = (InstructionalOffering)i.next(); ! // ChangeLog.addChange(getHibSession(), manager, session, io, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, io.getControllingCourseOffering().getSubjectArea(), null); // } } --- 2257,2261 ---- // for (Iterator i=relatedInstructionalOfferings.iterator();i.hasNext();) { // InstructionalOffering io = (InstructionalOffering)i.next(); ! // ChangeLog.addChange(getHibSession(), getManager(), session, io, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, io.getControllingCourseOffering().getSubjectArea(), null); // } } *************** *** 2343,2347 **** } ! ChangeLog.addChange(getHibSession(), manager, session, io, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, (io.getControllingCourseOffering() == null?null:io.getControllingCourseOffering().getSubjectArea()), (io.getControllingCourseOffering() == null?null:io.getControllingCourseOffering().getDepartment())); this.getHibSession().delete(io); flush(true); --- 2336,2340 ---- } ! ChangeLog.addChange(getHibSession(), getManager(), session, io, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, (io.getControllingCourseOffering() == null?null:io.getControllingCourseOffering().getSubjectArea()), (io.getControllingCourseOffering() == null?null:io.getControllingCourseOffering().getDepartment())); this.getHibSession().delete(io); flush(true); *************** *** 2365,2369 **** } ioc.getInstructionalOffering().getInstrOfferingConfigs().remove(ioc); ! ChangeLog.addChange(getHibSession(), manager, session, ioc, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, ioc.getControllingCourseOffering().getSubjectArea(), ioc.getControllingCourseOffering().getDepartment()); this.getHibSession().delete(ioc); } --- 2358,2362 ---- } ioc.getInstructionalOffering().getInstrOfferingConfigs().remove(ioc); ! ChangeLog.addChange(getHibSession(), getManager(), session, ioc, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, ioc.getControllingCourseOffering().getSubjectArea(), ioc.getControllingCourseOffering().getDepartment()); this.getHibSession().delete(ioc); } *************** *** 2397,2401 **** ioc.getSchedulingSubparts().remove(ss); this.getHibSession().update(ioc); ! ChangeLog.addChange(getHibSession(), manager, session, ss, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, ioc.getControllingCourseOffering().getSubjectArea(), ioc.getControllingCourseOffering().getDepartment()); // this.getHibSession().delete(ss); } --- 2390,2394 ---- ioc.getSchedulingSubparts().remove(ss); this.getHibSession().update(ioc); ! ChangeLog.addChange(getHibSession(), getManager(), session, ss, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, ioc.getControllingCourseOffering().getSubjectArea(), ioc.getControllingCourseOffering().getDepartment()); // this.getHibSession().delete(ss); } *************** *** 2407,2411 **** ci.setClassInstructing(null); ci.setInstructor(null); ! ChangeLog.addChange(getHibSession(), manager, session, ci, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, clazz.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), clazz.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); this.getHibSession().delete(ci); } --- 2400,2404 ---- ci.setClassInstructing(null); ci.setInstructor(null); ! ChangeLog.addChange(getHibSession(), getManager(), session, ci, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, clazz.getSchedulingSubpart().getControllingCourseOffering().getSubjectArea(), clazz.getSchedulingSubpart().getControllingCourseOffering().getDepartment()); this.getHibSession().delete(ci); } *************** *** 2416,2420 **** SchedulingSubpart ss = c.getSchedulingSubpart(); ss.getClasses().remove(c); ! ChangeLog.addChange(getHibSession(), manager, session, c, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, ss.getControllingCourseOffering().getSubjectArea(), ss.getControllingCourseOffering().getDepartment()); existingClasses.remove(c.getUniqueId()); this.getHibSession().delete(c); --- 2409,2413 ---- SchedulingSubpart ss = c.getSchedulingSubpart(); ss.getClasses().remove(c); ! ChangeLog.addChange(getHibSession(), getManager(), session, c, ChangeLog.Source.DATA_IMPORT_OFFERINGS, ChangeLog.Operation.DELETE, ss.getControllingCourseOffering().getSubjectArea(), ss.getControllingCourseOffering().getDepartment()); existingClasses.remove(c.getUniqueId()); this.getHibSession().delete(c); Index: EventImport.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/dataexchange/EventImport.java,v retrieving revision 1.1.2.1 retrieving revision 1.1.2.2 diff -C2 -d -r1.1.2.1 -r1.1.2.2 *** EventImport.java 9 Nov 2010 12:25:46 -0000 1.1.2.1 --- EventImport.java 1 Dec 2010 08:49:12 -0000 1.1.2.2 *************** *** 97,103 **** beginTransaction(); - if (manager == null){ - manager = findDefaultManager(); - } if (session == null){ // Use the session for the academicInitiative that is effective for events now as the session to use for logging changes --- 97,100 ---- *************** *** 106,110 **** if (created != null) { addNote("Loading Events XML file created on: " + created); ! ChangeLog.addChange(getHibSession(), manager, session, session, created, ChangeLog.Source.DATA_IMPORT_EVENTS, ChangeLog.Operation.CREATE, null, null); updateChangeList(true); } --- 103,107 ---- if (created != null) { addNote("Loading Events XML file created on: " + created); ! ChangeLog.addChange(getHibSession(), getManager(), session, session, created, ChangeLog.Source.DATA_IMPORT_EVENTS, ChangeLog.Operation.CREATE, null, null); updateChangeList(true); } Index: BuildingRoomImport.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/dataexchange/BuildingRoomImport.java,v retrieving revision 1.8.2.6 retrieving revision 1.8.2.7 diff -C2 -d -r1.8.2.6 -r1.8.2.7 *** BuildingRoomImport.java 9 Nov 2010 12:25:46 -0000 1.8.2.6 --- BuildingRoomImport.java 1 Dec 2010 08:49:12 -0000 1.8.2.7 *************** *** 30,34 **** import org.unitime.timetable.model.RoomType; import org.unitime.timetable.model.Session; - import org.unitime.timetable.model.TimetableManager; --- 30,33 ---- *************** *** 39,45 **** */ public class BuildingRoomImport extends BaseImport { ! ! TimetableManager manager = null; ! private static int BATCH_SIZE = 100; public BuildingRoomImport() { --- 38,42 ---- */ public class BuildingRoomImport extends BaseImport { ! private static int BATCH_SIZE = 100; public BuildingRoomImport() { *************** *** 58,66 **** throw new Exception("No session found for the given campus, year, and term."); } - if (manager == null){ - manager = findDefaultManager(); - } if (created != null) { ! ChangeLog.addChange(getHibSession(), manager, session, session, created, ChangeLog.Source.DATA_IMPORT_EXT_BUILDING_ROOM, ChangeLog.Operation.UPDATE, null, null); } /* --- 55,60 ---- throw new Exception("No session found for the given campus, year, and term."); } if (created != null) { ! ChangeLog.addChange(getHibSession(), getManager(), session, session, created, ChangeLog.Source.DATA_IMPORT_EXT_BUILDING_ROOM, ChangeLog.Operation.UPDATE, null, null); } /* Index: EventRelatedImports.java =================================================================== RCS file: /cvsroot/unitime/UniTime/JavaSource/org/unitime/timetable/dataexchange/EventRelatedImports.java,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -C2 -d -r1.1.2.3 -r1.1.2.4 *** EventRelatedImports.java 9 Nov 2010 12:25:46 -0000 1.1.2.3 --- EventRelatedImports.java 1 Dec 2010 08:49:12 -0000 1.1.2.4 *************** *** 34,38 **** import org.unitime.timetable.model.Meeting; import org.unitime.timetable.model.Session; - import org.unitime.timetable.model.TimetableManager; import org.unitime.timetable.util.CalendarUtils; import org.unitime.timetable.util.Constants; --- 34,37 ---- *************** *** 48,52 **** protected TreeSet<String> missingLocations = new TreeSet<String>(); protected Vector<String> notes = new Vector<String>(); - protected TimetableManager manager = null; protected String dateFormat = null; protected boolean trimLeadingZerosFromExternalId = false; --- 47,50 ---- *************** *** 109,114 **** email.setText(mail); ! if (manager != null) ! email.addRecipient(manager.getEmailAddress(), manager.getName()); if ("true".equals(ApplicationProperties.getProperty("unitime.email.notif.data", "false"))) --- 107,111 ---- email.setText(mail); ! email.addRecipient(getManager().getEmailAddress(), getManager().getName()); if ("true".equals(ApplicationProperties.getProperty("unitime.email.notif.data", "false"))) |