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