    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}