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