    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}