001package org.cpsolver.studentsct.reservation; 002 003import java.util.HashMap; 004import java.util.HashSet; 005import java.util.Map; 006import java.util.Set; 007 008import org.cpsolver.studentsct.model.Config; 009import org.cpsolver.studentsct.model.Enrollment; 010import org.cpsolver.studentsct.model.Offering; 011import org.cpsolver.studentsct.model.Section; 012import org.cpsolver.studentsct.model.Student; 013import org.cpsolver.studentsct.model.Subpart; 014 015 016 017/** 018 * Abstract restriction. Restrictions are like reservations, that must be used 019 * and that do not reserve any space. Except, there can be more than one restriction 020 * on an offering and the student must meet at least one that applies to her/him. 021 * 022 * <br> 023 * <br> 024 * 025 * @version StudentSct 1.3 (Student Sectioning)<br> 026 * Copyright (C) 2007 - 2020 Tomáš Müller<br> 027 * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br> 028 * <a href="http://muller.unitime.org">http://muller.unitime.org</a><br> 029 * <br> 030 * This library is free software; you can redistribute it and/or modify 031 * it under the terms of the GNU Lesser General Public License as 032 * published by the Free Software Foundation; either version 3 of the 033 * License, or (at your option) any later version. <br> 034 * <br> 035 * This library is distributed in the hope that it will be useful, but 036 * WITHOUT ANY WARRANTY; without even the implied warranty of 037 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 038 * Lesser General Public License for more details. <br> 039 * <br> 040 * You should have received a copy of the GNU Lesser General Public 041 * License along with this library; if not see 042 * <a href='http://www.gnu.org/licenses/'>http://www.gnu.org/licenses/</a>. 043 */ 044public abstract class Restriction { 045 /** Restriction unique id */ 046 private long iId = 0; 047 048 /** Instructional offering on which the restriction is set, required */ 049 private Offering iOffering; 050 051 /** One or more configurations, if applicable */ 052 private Set<Config> iConfigs = new HashSet<Config>(); 053 054 /** One or more sections, if applicable */ 055 private Map<Subpart, Set<Section>> iSections = new HashMap<Subpart, Set<Section>>(); 056 057 /** 058 * Constructor 059 * @param id restriction unique id 060 * @param offering instructional offering on which the restriction is set 061 */ 062 public Restriction(long id, Offering offering) { 063 iId = id; 064 iOffering = offering; 065 iOffering.getRestrictions().add(this); 066 iOffering.clearRestrictionCache(); 067 } 068 069 /** 070 * Restriction id 071 * @return restriction unique id 072 */ 073 public long getId() { return iId; } 074 075 /** 076 * Returns true if the student is applicable for the restriction 077 * @param student a student 078 * @return true if student can use the restriction to get into the course / configuration / section 079 */ 080 public abstract boolean isApplicable(Student student); 081 082 /** 083 * Instructional offering on which the restriction is set. 084 * @return instructional offering 085 */ 086 public Offering getOffering() { return iOffering; } 087 088 /** 089 * One or more configurations on which the restriction is set. 090 * @return instructional offering configurations 091 */ 092 public Set<Config> getConfigs() { return iConfigs; } 093 094 /** 095 * Add a configuration (of the offering {@link Restriction#getOffering()}) to this restriction 096 * @param config instructional offering configuration 097 */ 098 public void addConfig(Config config) { 099 iConfigs.add(config); 100 } 101 102 /** 103 * One or more sections on which the restriction is set. 104 * @return class class restrictions 105 */ 106 public Map<Subpart, Set<Section>> getSections() { return iSections; } 107 108 /** 109 * One or more sections on which the restriction is set (optional). 110 * @param subpart scheduling subpart 111 * @return class restrictions for the given scheduling subpart 112 */ 113 public Set<Section> getSections(Subpart subpart) { 114 return iSections.get(subpart); 115 } 116 117 /** 118 * Add a section (of the offering {@link Restriction#getOffering()}) to this restriction. 119 * This will also add all parent sections and the appropriate configuration to the offering. 120 * @param section a class restriction 121 */ 122 public void addSection(Section section) { 123 addConfig(section.getSubpart().getConfig()); 124 while (section != null) { 125 Set<Section> sections = iSections.get(section.getSubpart()); 126 if (sections == null) { 127 sections = new HashSet<Section>(); 128 iSections.put(section.getSubpart(), sections); 129 } 130 sections.add(section); 131 section = section.getParent(); 132 } 133 } 134 135 /** 136 * Return true if the given enrollment meets the restriction. 137 * @param enrollment given enrollment 138 * @return true if the given enrollment meets the restriction 139 */ 140 public boolean isIncluded(Enrollment enrollment) { 141 // Free time request are never included 142 if (enrollment.getConfig() == null) return false; 143 144 // Check the offering 145 if (!iOffering.equals(enrollment.getConfig().getOffering())) return false; 146 147 // no restrictions -> not included 148 if (iConfigs.isEmpty() && iSections.isEmpty()) return false; 149 150 // If there are configurations, check the configuration 151 if (!iConfigs.isEmpty() && !iConfigs.contains(enrollment.getConfig())) return false; 152 153 // Check all the sections of the enrollment 154 for (Section section: enrollment.getSections()) { 155 Set<Section> sections = iSections.get(section.getSubpart()); 156 if (sections != null && !sections.contains(section)) 157 return false; 158 } 159 return true; 160 } 161 162 public boolean isIncluded(Config config) { 163 // Check the offering 164 if (!iOffering.equals(config.getOffering())) return false; 165 166 // no restrictions -> not included 167 if (iConfigs.isEmpty() && iSections.isEmpty()) return false; 168 169 // if there are configurations, check the configuration 170 if (!iConfigs.isEmpty() && !iConfigs.contains(config)) return false; 171 return true; 172 } 173 174 public boolean isIncluded(Section section) { 175 // Check the offering 176 if (!iOffering.equals(section.getSubpart().getConfig().getOffering())) return false; 177 178 // no restrictions -> not included 179 if (iConfigs.isEmpty() && iSections.isEmpty()) return false; 180 181 // if there are configurations, check the configuration 182 if (!iConfigs.isEmpty() && !iConfigs.contains(section.getSubpart().getConfig())) return false; 183 184 // check the given section 185 Set<Section> sections = iSections.get(section.getSubpart()); 186 if (sections != null && !sections.contains(section)) 187 return false; 188 189 return true; 190 } 191}