001 package net.sf.cpsolver.studentsct; 002 003 import java.io.File; 004 import java.util.ArrayList; 005 import java.util.BitSet; 006 import java.util.HashSet; 007 import java.util.HashMap; 008 import java.util.Iterator; 009 import java.util.List; 010 import java.util.Map; 011 import java.util.Set; 012 013 import net.sf.cpsolver.coursett.model.Placement; 014 import net.sf.cpsolver.coursett.model.RoomLocation; 015 import net.sf.cpsolver.coursett.model.TimeLocation; 016 import net.sf.cpsolver.ifs.model.Constraint; 017 import net.sf.cpsolver.ifs.util.Progress; 018 import net.sf.cpsolver.studentsct.filter.StudentFilter; 019 import net.sf.cpsolver.studentsct.model.AcademicAreaCode; 020 import net.sf.cpsolver.studentsct.model.Choice; 021 import net.sf.cpsolver.studentsct.model.Config; 022 import net.sf.cpsolver.studentsct.model.Course; 023 import net.sf.cpsolver.studentsct.model.CourseRequest; 024 import net.sf.cpsolver.studentsct.model.Enrollment; 025 import net.sf.cpsolver.studentsct.model.FreeTimeRequest; 026 import net.sf.cpsolver.studentsct.model.Offering; 027 import net.sf.cpsolver.studentsct.model.Request; 028 import net.sf.cpsolver.studentsct.model.Section; 029 import net.sf.cpsolver.studentsct.model.Student; 030 import net.sf.cpsolver.studentsct.model.Subpart; 031 import net.sf.cpsolver.studentsct.reservation.CourseReservation; 032 import net.sf.cpsolver.studentsct.reservation.CurriculumReservation; 033 import net.sf.cpsolver.studentsct.reservation.DummyReservation; 034 import net.sf.cpsolver.studentsct.reservation.GroupReservation; 035 import net.sf.cpsolver.studentsct.reservation.IndividualReservation; 036 import net.sf.cpsolver.studentsct.reservation.Reservation; 037 038 import org.dom4j.Document; 039 import org.dom4j.Element; 040 import org.dom4j.io.SAXReader; 041 042 /** 043 * Load student sectioning model from an XML file. 044 * 045 * <br> 046 * <br> 047 * Parameters: 048 * <table border='1'> 049 * <tr> 050 * <th>Parameter</th> 051 * <th>Type</th> 052 * <th>Comment</th> 053 * </tr> 054 * <tr> 055 * <td>General.Input</td> 056 * <td>{@link String}</td> 057 * <td>Path of an XML file to be loaded</td> 058 * </tr> 059 * <tr> 060 * <td>Xml.LoadBest</td> 061 * <td>{@link Boolean}</td> 062 * <td>If true, load best assignments</td> 063 * </tr> 064 * <tr> 065 * <td>Xml.LoadInitial</td> 066 * <td>{@link Boolean}</td> 067 * <td>If false, load initial assignments</td> 068 * </tr> 069 * <tr> 070 * <td>Xml.LoadCurrent</td> 071 * <td>{@link Boolean}</td> 072 * <td>If true, load current assignments</td> 073 * </tr> 074 * <tr> 075 * <td>Xml.LoadOfferings</td> 076 * <td>{@link Boolean}</td> 077 * <td>If true, load offerings (and their stucture, i.e., courses, 078 * configurations, subparts and sections)</td> 079 * </tr> 080 * <tr> 081 * <td>Xml.LoadStudents</td> 082 * <td>{@link Boolean}</td> 083 * <td>If true, load students (and their requests)</td> 084 * </tr> 085 * <tr> 086 * <td>Xml.StudentFilter</td> 087 * <td>{@link StudentFilter}</td> 088 * <td>If provided, students are filtered by the given student filter</td> 089 * </tr> 090 * </table> 091 * 092 * <br> 093 * <br> 094 * Usage:<br> 095 * <code> 096 * StudentSectioningModel model = new StudentSectioningModel(cfg);<br> 097 * new StudentSectioningXMLLoader(model).load();<br> 098 * </code> 099 * 100 * @version StudentSct 1.2 (Student Sectioning)<br> 101 * Copyright (C) 2007 - 2010 Tomas Muller<br> 102 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 103 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 104 * <br> 105 * This library is free software; you can redistribute it and/or modify 106 * it under the terms of the GNU Lesser General Public License as 107 * published by the Free Software Foundation; either version 3 of the 108 * License, or (at your option) any later version. <br> 109 * <br> 110 * This library is distributed in the hope that it will be useful, but 111 * WITHOUT ANY WARRANTY; without even the implied warranty of 112 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 113 * Lesser General Public License for more details. <br> 114 * <br> 115 * You should have received a copy of the GNU Lesser General Public 116 * License along with this library; if not see 117 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 118 */ 119 120 public class StudentSectioningXMLLoader extends StudentSectioningLoader { 121 private static org.apache.log4j.Logger sLogger = org.apache.log4j.Logger 122 .getLogger(StudentSectioningXMLLoader.class); 123 124 private File iInputFile; 125 private File iTimetableFile = null; 126 private boolean iLoadBest = false; 127 private boolean iLoadInitial = false; 128 private boolean iLoadCurrent = false; 129 private boolean iLoadOfferings = true; 130 private boolean iLoadStudents = true; 131 private StudentFilter iStudentFilter = null; 132 133 /** 134 * Constructor 135 * 136 * @param model 137 * student sectioning model 138 */ 139 public StudentSectioningXMLLoader(StudentSectioningModel model) { 140 super(model); 141 iInputFile = new File(getModel().getProperties().getProperty("General.Input", 142 "." + File.separator + "solution.xml")); 143 if (getModel().getProperties().getProperty("General.InputTimetable") != null) 144 iTimetableFile = new File(getModel().getProperties().getProperty("General.InputTimetable")); 145 iLoadBest = getModel().getProperties().getPropertyBoolean("Xml.LoadBest", true); 146 iLoadInitial = getModel().getProperties().getPropertyBoolean("Xml.LoadInitial", true); 147 iLoadCurrent = getModel().getProperties().getPropertyBoolean("Xml.LoadCurrent", true); 148 iLoadOfferings = getModel().getProperties().getPropertyBoolean("Xml.LoadOfferings", true); 149 iLoadStudents = getModel().getProperties().getPropertyBoolean("Xml.LoadStudents", true); 150 if (getModel().getProperties().getProperty("Xml.StudentFilter") != null) { 151 try { 152 iStudentFilter = (StudentFilter) Class.forName( 153 getModel().getProperties().getProperty("Xml.StudentFilter")).getConstructor(new Class[] {}) 154 .newInstance(new Object[] {}); 155 } catch (Exception e) { 156 sLogger.error("Unable to create student filter, reason: " + e.getMessage(), e); 157 } 158 } 159 } 160 161 /** Set input file (e.g., if it is not set by General.Input property) */ 162 public void setInputFile(File inputFile) { 163 iInputFile = inputFile; 164 } 165 166 /** Set student filter */ 167 public void setStudentFilter(StudentFilter filter) { 168 iStudentFilter = filter; 169 } 170 171 /** Set whether to load students */ 172 public void setLoadStudents(boolean loadStudents) { 173 iLoadStudents = loadStudents; 174 } 175 176 /** Set whether to load offerings */ 177 public void setLoadOfferings(boolean loadOfferings) { 178 iLoadOfferings = loadOfferings; 179 } 180 181 /** Create BitSet from a bit string */ 182 private static BitSet createBitSet(String bitString) { 183 BitSet ret = new BitSet(bitString.length()); 184 for (int i = 0; i < bitString.length(); i++) 185 if (bitString.charAt(i) == '1') 186 ret.set(i); 187 return ret; 188 } 189 190 /** Load the file */ 191 @Override 192 public void load() throws Exception { 193 sLogger.debug("Reading XML data from " + iInputFile); 194 195 Document document = (new SAXReader()).read(iInputFile); 196 Element root = document.getRootElement(); 197 sLogger.debug("Root element: " + root.getName()); 198 if (!"sectioning".equals(root.getName())) { 199 sLogger.error("Given XML file is not student sectioning problem."); 200 return; 201 } 202 203 if (iLoadOfferings && getModel().getDistanceConflict() != null && root.element("travel-times") != null) { 204 for (Iterator<?> i = root.element("travel-times").elementIterator("travel-time"); i.hasNext();) { 205 Element travelTimeEl = (Element)i.next(); 206 getModel().getDistanceConflict().getDistanceMetric().addTravelTime( 207 Long.valueOf(travelTimeEl.attributeValue("id1")), 208 Long.valueOf(travelTimeEl.attributeValue("id2")), 209 Integer.valueOf(travelTimeEl.attributeValue("minutes"))); 210 } 211 } 212 213 HashMap<Long, Placement> timetable = null; 214 if (iTimetableFile != null) { 215 sLogger.info("Reading timetable from " + iTimetableFile + " ..."); 216 Document timetableDocument = (new SAXReader()).read(iTimetableFile); 217 Element timetableRoot = timetableDocument.getRootElement(); 218 if (!"timetable".equals(timetableRoot.getName())) { 219 sLogger.error("Given XML file is not course timetabling problem."); 220 return; 221 } 222 timetable = new HashMap<Long, Placement>(); 223 HashMap<Long, RoomLocation> rooms = new HashMap<Long, RoomLocation>(); 224 for (Iterator<?> i = timetableRoot.element("rooms").elementIterator("room"); i.hasNext();) { 225 Element roomEl = (Element)i.next(); 226 Long roomId = Long.valueOf(roomEl.attributeValue("id")); 227 Double posX = null, posY = null; 228 if (roomEl.attributeValue("location") != null) { 229 String loc = roomEl.attributeValue("location"); 230 posX = Double.valueOf(loc.substring(0, loc.indexOf(','))); 231 posY = Double.valueOf(loc.substring(loc.indexOf(',') + 1)); 232 } 233 RoomLocation room = new RoomLocation(Long.valueOf(roomEl.attributeValue("id")), roomEl 234 .attributeValue("name", "R" + roomEl.attributeValue("id")), roomEl 235 .attributeValue("building") == null ? null : Long.valueOf(roomEl 236 .attributeValue("building")), 0, Integer.parseInt(roomEl 237 .attributeValue("capacity")), posX, posY, "true".equals(roomEl 238 .attributeValue("ignoreTooFar")), null); 239 rooms.put(roomId, room); 240 } 241 for (Iterator<?> i = timetableRoot.element("classes").elementIterator("class"); i.hasNext();) { 242 Element classEl = (Element)i.next(); 243 Long classId = Long.valueOf(classEl.attributeValue("id")); 244 TimeLocation time = null; 245 Element timeEl = null; 246 for (Iterator<?> j = classEl.elementIterator("time"); j.hasNext(); ) { 247 Element e = (Element)j.next(); 248 if ("true".equals(e.attributeValue("solution", "false"))) { timeEl = e; break; } 249 } 250 if (timeEl != null) { 251 time = new TimeLocation(Integer.parseInt(timeEl.attributeValue("days"), 2), Integer 252 .parseInt(timeEl.attributeValue("start")), Integer.parseInt(timeEl 253 .attributeValue("length")), 0, 0, 254 classEl.attributeValue("datePattern") == null ? null : Long.valueOf(classEl 255 .attributeValue("datePattern")), classEl.attributeValue( 256 "datePatternName", ""), createBitSet(classEl.attributeValue("dates")), 257 Integer.parseInt(timeEl.attributeValue("breakTime", "0"))); 258 if (timeEl.attributeValue("pattern") != null) 259 time.setTimePatternId(Long.valueOf(timeEl.attributeValue("pattern"))); 260 } 261 List<RoomLocation> room = new ArrayList<RoomLocation>(); 262 for (Iterator<?> j = classEl.elementIterator("room"); j.hasNext();) { 263 Element roomEl = (Element) j.next(); 264 if (!"true".equals(roomEl.attributeValue("solution", "false"))) continue; 265 room.add(rooms.get(Long.valueOf(roomEl.attributeValue("id")))); 266 } 267 Placement placement = (time == null ? null : new Placement(null, time, room)); 268 if (placement != null) 269 timetable.put(classId, placement); 270 } 271 } 272 273 Progress.getInstance(getModel()).load(root, true); 274 Progress.getInstance(getModel()).message(Progress.MSGLEVEL_STAGE, "Restoring from backup ..."); 275 276 if (root.attributeValue("term") != null) 277 getModel().getProperties().setProperty("Data.Term", root.attributeValue("term")); 278 if (root.attributeValue("year") != null) 279 getModel().getProperties().setProperty("Data.Year", root.attributeValue("year")); 280 if (root.attributeValue("initiative") != null) 281 getModel().getProperties().setProperty("Data.Initiative", root.attributeValue("initiative")); 282 283 HashMap<Long, Offering> offeringTable = new HashMap<Long, Offering>(); 284 HashMap<Long, Course> courseTable = new HashMap<Long, Course>(); 285 286 if (iLoadOfferings && root.element("offerings") != null) { 287 HashMap<Long, Config> configTable = new HashMap<Long, Config>(); 288 HashMap<Long, Subpart> subpartTable = new HashMap<Long, Subpart>(); 289 HashMap<Long, Section> sectionTable = new HashMap<Long, Section>(); 290 for (Iterator<?> i = root.element("offerings").elementIterator("offering"); i.hasNext();) { 291 Element offeringEl = (Element) i.next(); 292 Offering offering = new Offering(Long.parseLong(offeringEl.attributeValue("id")), offeringEl 293 .attributeValue("name", "O" + offeringEl.attributeValue("id"))); 294 offeringTable.put(new Long(offering.getId()), offering); 295 getModel().addOffering(offering); 296 for (Iterator<?> j = offeringEl.elementIterator("course"); j.hasNext();) { 297 Element courseEl = (Element) j.next(); 298 Course course = new Course(Long.parseLong(courseEl.attributeValue("id")), courseEl.attributeValue( 299 "subjectArea", ""), courseEl.attributeValue("courseNbr", "C" 300 + courseEl.attributeValue("id")), offering, Integer.parseInt(courseEl.attributeValue( 301 "limit", "-1")), Integer.parseInt(courseEl.attributeValue("projected", "0"))); 302 courseTable.put(new Long(course.getId()), course); 303 } 304 for (Iterator<?> j = offeringEl.elementIterator("config"); j.hasNext();) { 305 Element configEl = (Element) j.next(); 306 Config config = new Config(Long.parseLong(configEl.attributeValue("id")), 307 Integer.parseInt(configEl.attributeValue("limit", "-1")), 308 configEl.attributeValue("name", "G" + configEl.attributeValue("id")), 309 offering); 310 configTable.put(config.getId(), config); 311 for (Iterator<?> k = configEl.elementIterator("subpart"); k.hasNext();) { 312 Element subpartEl = (Element) k.next(); 313 Subpart parentSubpart = null; 314 if (subpartEl.attributeValue("parent") != null) 315 parentSubpart = subpartTable.get(Long.valueOf(subpartEl.attributeValue("parent"))); 316 Subpart subpart = new Subpart(Long.parseLong(subpartEl.attributeValue("id")), subpartEl 317 .attributeValue("itype"), subpartEl.attributeValue("name", "P" 318 + subpartEl.attributeValue("id")), config, parentSubpart); 319 subpart.setAllowOverlap("true".equals(subpartEl.attributeValue("allowOverlap", "false"))); 320 subpartTable.put(new Long(subpart.getId()), subpart); 321 for (Iterator<?> l = subpartEl.elementIterator("section"); l.hasNext();) { 322 Element sectionEl = (Element) l.next(); 323 Section parentSection = null; 324 if (sectionEl.attributeValue("parent") != null) 325 parentSection = sectionTable.get(Long.valueOf(sectionEl.attributeValue("parent"))); 326 Placement placement = null; 327 if (timetable != null) { 328 placement = timetable.get(Long.parseLong(sectionEl.attributeValue("id"))); 329 } else { 330 TimeLocation time = null; 331 Element timeEl = sectionEl.element("time"); 332 if (timeEl != null) { 333 time = new TimeLocation(Integer.parseInt(timeEl.attributeValue("days"), 2), Integer 334 .parseInt(timeEl.attributeValue("start")), Integer.parseInt(timeEl 335 .attributeValue("length")), 0, 0, 336 timeEl.attributeValue("datePattern") == null ? null : Long.valueOf(timeEl 337 .attributeValue("datePattern")), timeEl.attributeValue( 338 "datePatternName", ""), createBitSet(timeEl.attributeValue("dates")), 339 Integer.parseInt(timeEl.attributeValue("breakTime", "0"))); 340 if (timeEl.attributeValue("pattern") != null) 341 time.setTimePatternId(Long.valueOf(timeEl.attributeValue("pattern"))); 342 } 343 List<RoomLocation> rooms = new ArrayList<RoomLocation>(); 344 for (Iterator<?> m = sectionEl.elementIterator("room"); m.hasNext();) { 345 Element roomEl = (Element) m.next(); 346 Double posX = null, posY = null; 347 if (roomEl.attributeValue("location") != null) { 348 String loc = roomEl.attributeValue("location"); 349 posX = Double.valueOf(loc.substring(0, loc.indexOf(','))); 350 posY = Double.valueOf(loc.substring(loc.indexOf(',') + 1)); 351 } 352 RoomLocation room = new RoomLocation(Long.valueOf(roomEl.attributeValue("id")), roomEl 353 .attributeValue("name", "R" + roomEl.attributeValue("id")), roomEl 354 .attributeValue("building") == null ? null : Long.valueOf(roomEl 355 .attributeValue("building")), 0, Integer.parseInt(roomEl 356 .attributeValue("capacity")), posX, posY, "true".equals(roomEl 357 .attributeValue("ignoreTooFar")), null); 358 rooms.add(room); 359 } 360 placement = (time == null ? null : new Placement(null, time, rooms)); 361 } 362 Section section = new Section(Long.parseLong(sectionEl.attributeValue("id")), Integer 363 .parseInt(sectionEl.attributeValue("limit")), sectionEl.attributeValue("name", "S" 364 + sectionEl.attributeValue("id")), subpart, placement, sectionEl 365 .attributeValue("instructorIds"), sectionEl.attributeValue("instructorNames"), 366 parentSection); 367 sectionTable.put(new Long(section.getId()), section); 368 section.setSpaceHeld(Double.parseDouble(sectionEl.attributeValue("hold", "0.0"))); 369 section.setSpaceExpected(Double.parseDouble(sectionEl.attributeValue("expect", "0.0"))); 370 for (Iterator<?> m = sectionEl.elementIterator("cname"); m.hasNext(); ) { 371 Element cNameEl = (Element)m.next(); 372 section.setName(Long.parseLong(cNameEl.attributeValue("id")), cNameEl.getText()); 373 } 374 Element ignoreEl = sectionEl.element("no-conflicts"); 375 if (ignoreEl != null) { 376 for (Iterator<?> m = ignoreEl.elementIterator("section"); m.hasNext(); ) 377 section.addIgnoreConflictWith(Long.parseLong(((Element)m.next()).attributeValue("id"))); 378 } 379 } 380 } 381 } 382 for (Iterator<?> j = offeringEl.elementIterator("reservation"); j.hasNext(); ) { 383 Element reservationEl = (Element)j.next(); 384 Reservation r = null; 385 if ("individual".equals(reservationEl.attributeValue("type"))) { 386 Set<Long> studentIds = new HashSet<Long>(); 387 for (Iterator<?> k = reservationEl.elementIterator("student"); k.hasNext(); ) { 388 Element studentEl = (Element)k.next(); 389 studentIds.add(Long.parseLong(studentEl.attributeValue("id"))); 390 } 391 r = new IndividualReservation(Long.valueOf(reservationEl.attributeValue("id")), offering, studentIds); 392 } else if ("group".equals(reservationEl.attributeValue("type"))) { 393 Set<Long> studentIds = new HashSet<Long>(); 394 for (Iterator<?> k = reservationEl.elementIterator("student"); k.hasNext(); ) { 395 Element studentEl = (Element)k.next(); 396 studentIds.add(Long.parseLong(studentEl.attributeValue("id"))); 397 } 398 r = new GroupReservation(Long.valueOf(reservationEl.attributeValue("id")), 399 Double.parseDouble(reservationEl.attributeValue("limit", "-1")), 400 offering, studentIds); 401 } else if ("curriculum".equals(reservationEl.attributeValue("type"))) { 402 List<String> classifications = new ArrayList<String>(); 403 for (Iterator<?> k = reservationEl.elementIterator("classification"); k.hasNext(); ) { 404 Element clasfEl = (Element)k.next(); 405 classifications.add(clasfEl.attributeValue("code")); 406 } 407 List<String> majors = new ArrayList<String>(); 408 for (Iterator<?> k = reservationEl.elementIterator("major"); k.hasNext(); ) { 409 Element majorEl = (Element)k.next(); 410 majors.add(majorEl.attributeValue("code")); 411 } 412 r = new CurriculumReservation(Long.valueOf(reservationEl.attributeValue("id")), 413 Double.parseDouble(reservationEl.attributeValue("limit", "-1")), 414 offering, 415 reservationEl.attributeValue("area"), 416 classifications, majors); 417 } else if ("course".equals(reservationEl.attributeValue("type"))) { 418 long courseId = Long.parseLong(reservationEl.attributeValue("course")); 419 for (Course course: offering.getCourses()) { 420 if (course.getId() == courseId) 421 r = new CourseReservation(Long.valueOf(reservationEl.attributeValue("id")), course); 422 } 423 } else if ("dummy".equals(reservationEl.attributeValue("type"))) { 424 r = new DummyReservation(offering); 425 } 426 if (r == null) { 427 sLogger.error("Unknown reservation type "+ reservationEl.attributeValue("type")); 428 continue; 429 } 430 r.setExpired("true".equals(reservationEl.attributeValue("expired", "false"))); 431 for (Iterator<?> k = reservationEl.elementIterator("config"); k.hasNext(); ) { 432 Element configEl = (Element)k.next(); 433 r.addConfig(configTable.get(Long.parseLong(configEl.attributeValue("id")))); 434 } 435 for (Iterator<?> k = reservationEl.elementIterator("section"); k.hasNext(); ) { 436 Element sectionEl = (Element)k.next(); 437 r.addSection(sectionTable.get(Long.parseLong(sectionEl.attributeValue("id")))); 438 } 439 } 440 } 441 } else { 442 for (Offering offering : getModel().getOfferings()) { 443 offeringTable.put(new Long(offering.getId()), offering); 444 for (Course course : offering.getCourses()) { 445 courseTable.put(new Long(course.getId()), course); 446 } 447 } 448 } 449 450 if (iLoadStudents && root.element("students") != null) { 451 List<Enrollment> bestEnrollments = new ArrayList<Enrollment>(); 452 List<Enrollment> currentEnrollments = new ArrayList<Enrollment>(); 453 for (Iterator<?> i = root.element("students").elementIterator("student"); i.hasNext();) { 454 Element studentEl = (Element) i.next(); 455 Student student = new Student(Long.parseLong(studentEl.attributeValue("id")), "true".equals(studentEl.attributeValue("dummy"))); 456 student.setExternalId(studentEl.attributeValue("externalId")); 457 student.setName(studentEl.attributeValue("name")); 458 student.setStatus(studentEl.attributeValue("status")); 459 for (Iterator<?> j = studentEl.elementIterator(); j.hasNext();) { 460 Element requestEl = (Element) j.next(); 461 if ("classification".equals(requestEl.getName())) { 462 student.getAcademicAreaClasiffications() 463 .add( 464 new AcademicAreaCode(requestEl.attributeValue("area"), requestEl 465 .attributeValue("code"))); 466 } else if ("major".equals(requestEl.getName())) { 467 student.getMajors() 468 .add( 469 new AcademicAreaCode(requestEl.attributeValue("area"), requestEl 470 .attributeValue("code"))); 471 } else if ("minor".equals(requestEl.getName())) { 472 student.getMinors() 473 .add( 474 new AcademicAreaCode(requestEl.attributeValue("area"), requestEl 475 .attributeValue("code"))); 476 } 477 } 478 if (iStudentFilter != null && !iStudentFilter.accept(student)) 479 continue; 480 for (Iterator<?> j = studentEl.elementIterator(); j.hasNext();) { 481 Element requestEl = (Element) j.next(); 482 if ("freeTime".equals(requestEl.getName())) { 483 TimeLocation time = new TimeLocation(Integer.parseInt(requestEl.attributeValue("days"), 2), 484 Integer.parseInt(requestEl.attributeValue("start")), Integer.parseInt(requestEl 485 .attributeValue("length")), 0, 0, 486 requestEl.attributeValue("datePattern") == null ? null : Long.valueOf(requestEl 487 .attributeValue("datePattern")), "", createBitSet(requestEl 488 .attributeValue("dates")), 0); 489 FreeTimeRequest request = new FreeTimeRequest(Long.parseLong(requestEl.attributeValue("id")), 490 Integer.parseInt(requestEl.attributeValue("priority")), "true".equals(requestEl 491 .attributeValue("alternative")), student, time); 492 if (requestEl.attributeValue("weight") != null) 493 request.setWeight(Double.parseDouble(requestEl.attributeValue("weight"))); 494 if (iLoadBest && requestEl.element("best") != null) 495 bestEnrollments.add(request.createEnrollment()); 496 if (iLoadInitial && requestEl.element("initial") != null) 497 request.setInitialAssignment(request.createEnrollment()); 498 if (iLoadCurrent && requestEl.element("current") != null) 499 currentEnrollments.add(request.createEnrollment()); 500 } else if ("course".equals(requestEl.getName())) { 501 List<Course> courses = new ArrayList<Course>(); 502 courses.add(courseTable.get(Long.valueOf(requestEl.attributeValue("course")))); 503 for (Iterator<?> k = requestEl.elementIterator("alternative"); k.hasNext();) 504 courses.add(courseTable.get(Long.valueOf(((Element) k.next()).attributeValue("course")))); 505 Long timeStamp = null; 506 if (requestEl.attributeValue("timeStamp") != null) 507 timeStamp = Long.valueOf(requestEl.attributeValue("timeStamp")); 508 CourseRequest courseRequest = new CourseRequest( 509 Long.parseLong(requestEl.attributeValue("id")), 510 Integer.parseInt(requestEl.attributeValue("priority")), 511 "true".equals(requestEl.attributeValue("alternative")), 512 student, courses, 513 "true".equals(requestEl.attributeValue("waitlist", "false")), timeStamp); 514 if (requestEl.attributeValue("weight") != null) 515 courseRequest.setWeight(Double.parseDouble(requestEl.attributeValue("weight"))); 516 for (Iterator<?> k = requestEl.elementIterator("waitlisted"); k.hasNext();) { 517 Element choiceEl = (Element) k.next(); 518 courseRequest.getWaitlistedChoices().add( 519 new Choice(offeringTable.get(Long.valueOf(choiceEl.attributeValue("offering"))), 520 choiceEl.getText())); 521 } 522 for (Iterator<?> k = requestEl.elementIterator("selected"); k.hasNext();) { 523 Element choiceEl = (Element) k.next(); 524 courseRequest.getSelectedChoices().add( 525 new Choice(offeringTable.get(Long.valueOf(choiceEl.attributeValue("offering"))), 526 choiceEl.getText())); 527 } 528 Element initialEl = requestEl.element("initial"); 529 if (iLoadInitial && initialEl != null) { 530 HashSet<Section> sections = new HashSet<Section>(); 531 for (Iterator<?> k = initialEl.elementIterator("section"); k.hasNext();) { 532 Element sectionEl = (Element) k.next(); 533 Section section = courseRequest.getSection(Long.parseLong(sectionEl 534 .attributeValue("id"))); 535 sections.add(section); 536 } 537 Reservation reservation = null; 538 if (initialEl.attributeValue("reservation", null) != null) { 539 long reservationId = Long.valueOf(initialEl.attributeValue("reservation")); 540 for (Course course: courseRequest.getCourses()) 541 for (Reservation r: course.getOffering().getReservations()) 542 if (r.getId() == reservationId) { reservation = r; break; } 543 } 544 if (!sections.isEmpty()) 545 courseRequest.setInitialAssignment(courseRequest.createEnrollment(sections, reservation)); 546 } 547 Element currentEl = requestEl.element("current"); 548 if (iLoadCurrent && currentEl != null) { 549 HashSet<Section> sections = new HashSet<Section>(); 550 for (Iterator<?> k = currentEl.elementIterator("section"); k.hasNext();) { 551 Element sectionEl = (Element) k.next(); 552 Section section = courseRequest.getSection(Long.parseLong(sectionEl 553 .attributeValue("id"))); 554 sections.add(section); 555 } 556 Reservation reservation = null; 557 if (currentEl.attributeValue("reservation", null) != null) { 558 long reservationId = Long.valueOf(currentEl.attributeValue("reservation")); 559 for (Course course: courseRequest.getCourses()) 560 for (Reservation r: course.getOffering().getReservations()) 561 if (r.getId() == reservationId) { reservation = r; break; } 562 } 563 if (!sections.isEmpty()) 564 currentEnrollments.add(courseRequest.createEnrollment(sections, reservation)); 565 } 566 Element bestEl = requestEl.element("best"); 567 if (iLoadBest && bestEl != null) { 568 HashSet<Section> sections = new HashSet<Section>(); 569 for (Iterator<?> k = bestEl.elementIterator("section"); k.hasNext();) { 570 Element sectionEl = (Element) k.next(); 571 Section section = courseRequest.getSection(Long.parseLong(sectionEl 572 .attributeValue("id"))); 573 sections.add(section); 574 } 575 Reservation reservation = null; 576 if (bestEl.attributeValue("reservation", null) != null) { 577 long reservationId = Long.valueOf(bestEl.attributeValue("reservation")); 578 for (Course course: courseRequest.getCourses()) 579 for (Reservation r: course.getOffering().getReservations()) 580 if (r.getId() == reservationId) { reservation = r; break; } 581 } 582 if (!sections.isEmpty()) 583 bestEnrollments.add(courseRequest.createEnrollment(sections, reservation)); 584 } 585 } 586 } 587 getModel().addStudent(student); 588 } 589 590 if (!bestEnrollments.isEmpty()) { 591 // Enrollments with a reservation must go first 592 for (Enrollment enrollment : bestEnrollments) { 593 if (enrollment.getReservation() == null) continue; 594 Map<Constraint<Request, Enrollment>, Set<Enrollment>> conflicts = getModel().conflictConstraints(enrollment); 595 if (conflicts.isEmpty()) 596 enrollment.variable().assign(0, enrollment); 597 else 598 sLogger.warn("Enrollment " + enrollment + " conflicts with " + conflicts); 599 } 600 for (Enrollment enrollment : bestEnrollments) { 601 if (enrollment.getReservation() != null) continue; 602 Map<Constraint<Request, Enrollment>, Set<Enrollment>> conflicts = getModel().conflictConstraints(enrollment); 603 if (conflicts.isEmpty()) 604 enrollment.variable().assign(0, enrollment); 605 else 606 sLogger.warn("Enrollment " + enrollment + " conflicts with " + conflicts); 607 } 608 getModel().saveBest(); 609 } 610 611 if (!currentEnrollments.isEmpty()) { 612 for (Request request : getModel().variables()) { 613 if (request.getAssignment() != null) 614 request.unassign(0); 615 } 616 for (Enrollment enrollment : currentEnrollments) { 617 enrollment.variable().assign(0, enrollment); 618 } 619 } 620 } 621 622 if (iLoadOfferings && root.element("constraints") != null) { 623 for (Iterator<?> i = root.element("constraints").elementIterator("linked-sections"); i.hasNext();) { 624 Element linkedEl = (Element) i.next(); 625 List<Section> sections = new ArrayList<Section>(); 626 for (Iterator<?> j = linkedEl.elementIterator("section"); j.hasNext();) { 627 Element sectionEl = (Element) j.next(); 628 Offering offering = offeringTable.get(Long.valueOf(sectionEl.attributeValue("offering"))); 629 sections.add(offering.getSection(Long.valueOf(sectionEl.attributeValue("id")))); 630 } 631 getModel().addLinkedSections(sections); 632 } 633 } 634 635 sLogger.debug("Model successfully loaded."); 636 } 637 638 }