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 (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 (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 }