001    package net.sf.cpsolver.exam.model;
002    
003    import java.util.HashMap;
004    import java.util.HashSet;
005    import java.util.Map;
006    import java.util.Set;
007    
008    import org.dom4j.Element;
009    
010    import net.sf.cpsolver.coursett.IdConvertor;
011    import net.sf.cpsolver.ifs.model.Model;
012    import net.sf.cpsolver.ifs.util.DataProperties;
013    
014    /**
015     * Room sharing model based on a pre-defined list of examination pairs. The relation needs to be populated
016     * using {@link PredefinedExamRoomSharing#addPair(Exam, Exam)} and it is persisted with the solution XML (see
017     * {@link ExamModel#save()}, canShareRoom element for each exam containing a comma separated list of exam ids).
018     * <br>
019     * 
020     * @version ExamTT 1.2 (Examination Timetabling)<br>
021     *          Copyright (C) 2008 - 2012 Tomas Muller<br>
022     *          <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
023     *          <a href="http://muller.unitime.org">http://muller.unitime.org</a><br>
024     * <br>
025     *          This library is free software; you can redistribute it and/or modify
026     *          it under the terms of the GNU Lesser General Public License as
027     *          published by the Free Software Foundation; either version 3 of the
028     *          License, or (at your option) any later version. <br>
029     * <br>
030     *          This library is distributed in the hope that it will be useful, but
031     *          WITHOUT ANY WARRANTY; without even the implied warranty of
032     *          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
033     *          Lesser General Public License for more details. <br>
034     * <br>
035     *          You should have received a copy of the GNU Lesser General Public
036     *          License along with this library; if not see
037     *          <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>.
038     */
039    public class PredefinedExamRoomSharing extends ExamRoomSharing {
040        private Map<Long, Set<Long>> iSharingMatrix = new HashMap<Long, Set<Long>>();
041        
042        public PredefinedExamRoomSharing(Model<Exam, ExamPlacement> model, DataProperties config) {
043            super(model, config);
044        }
045    
046        @Override
047        public boolean canShareRoom(Exam x1, Exam x2) {
048            if (x1.getId() < x2.getId()) {
049                Set<Long> exams = iSharingMatrix.get(x1.getId());
050                return exams != null && exams.contains(x2.getId());
051            } else {
052                Set<Long> exams = iSharingMatrix.get(x2.getId());
053                return exams != null && exams.contains(x1.getId());
054            }
055        }
056        
057        /** Add a pair of exams that are allowed to share a room */
058        public void addPair(Exam x1, Exam x2) {
059            addPair(x1.getId(), x2.getId());
060        }
061        
062        /** Add a pair of exams that are allowed to share a room */
063        public void addPair(Long examId1, Long examId2) {
064            if (examId1 < examId2) {
065                Set<Long> exams = iSharingMatrix.get(examId1);
066                if (exams == null) { exams = new HashSet<Long>(); iSharingMatrix.put(examId1, exams); }
067                exams.add(examId2);
068            } else {
069                Set<Long> exams = iSharingMatrix.get(examId2);
070                if (exams == null) { exams = new HashSet<Long>(); iSharingMatrix.put(examId2, exams); }
071                exams.add(examId1);
072            }        
073        }
074        
075        /** Clear examination pairs */
076        public void clear() {
077            iSharingMatrix.clear();
078        }
079        
080        @Override
081        public void save(Exam exam, Element element, IdConvertor idConvertor) {
082            Set<Long> exams = iSharingMatrix.get(exam.getId());
083            if (exams != null) {
084                String ids = "";
085                for (Long id: exams) {
086                    if (!ids.isEmpty()) ids += ",";
087                    ids += (idConvertor == null ? id.toString() : idConvertor.convert("exam", id.toString()));
088                }
089                element.addElement("canShareRoom").setText(ids);
090            }
091        }
092        
093        @Override
094        public void load(Exam exam, Element element) {
095            Element canShareRoom = element.element("canShareRoom");
096            if (canShareRoom == null) return;
097            for (String id: canShareRoom.getTextTrim().split(","))
098                addPair(exam.getId(), Long.valueOf(id.trim()));
099        }
100    }