001    package net.sf.cpsolver.studentsct.model;
002    
003    import java.util.Enumeration;
004    import java.util.HashSet;
005    import java.util.Vector;
006    
007    /**
008     * Representation of a scheduling subpart. Each scheduling subpart contains id, instructional type, name, 
009     * instructional offering configuration, and a list of sections. Optionally, parent-child relation between
010     * subparts can be defined.
011     * <br><br>
012     * 
013     * @version
014     * StudentSct 1.1 (Student Sectioning)<br>
015     * Copyright (C) 2007 Tomáš Müller<br>
016     * <a href="mailto:muller@unitime.org">muller@unitime.org</a><br>
017     * Lazenska 391, 76314 Zlin, Czech Republic<br>
018     * <br>
019     * This library is free software; you can redistribute it and/or
020     * modify it under the terms of the GNU Lesser General Public
021     * License as published by the Free Software Foundation; either
022     * version 2.1 of the License, or (at your option) any later version.
023     * <br><br>
024     * This library is distributed in the hope that it will be useful,
025     * but WITHOUT ANY WARRANTY; without even the implied warranty of
026     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
027     * Lesser General Public License for more details.
028     * <br><br>
029     * You should have received a copy of the GNU Lesser General Public
030     * License along with this library; if not, write to the Free Software
031     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
032     */
033    public class Subpart implements Comparable {
034        private long iId = -1;
035        private String iInstructionalType = null;
036        private String iName = null;
037        private Vector iSections = new Vector();
038        private Config iConfig = null;
039        private Subpart iParent = null;
040    
041        /** Constructor
042         * @param id scheduling subpart unique id
043         * @param itype instructional type
044         * @param name subpart name
045         * @param config instructional offering configuration to which this subpart belongs
046         * @param parent parent subpart, if parent-child relation is defined between subparts
047         */
048        public Subpart(long id, String itype, String name, Config config, Subpart parent) {
049            iId = id;
050            iInstructionalType = itype;
051            iName = name;
052            iConfig = config;
053            iParent = parent;
054            iConfig.getSubparts().addElement(this);
055        }
056        
057        /** Subpart id  */
058        public long getId() {
059            return iId;
060        }
061        
062        /** Instructional type, e.g., Lecture, Recitation or Laboratory */
063        public String getInstructionalType() {
064            return iInstructionalType;
065        }
066        
067        /** Subpart name */
068        public String getName() {
069            return iName;
070        }
071        
072        /** Instructional offering configuration to which this subpart belongs */
073        public Config getConfig() {
074            return iConfig;
075        }
076    
077        /** List of sections */
078        public Vector getSections() {
079            return iSections;
080        }
081        
082        /** Parent subpart, if parent-child relation is defined between subparts */
083        public Subpart getParent() {
084            return iParent;
085        }
086        
087        public String toString() {
088            return getName();
089        }
090        
091        /** True, if this subpart is parent (or parent of a parent etc.) of the given subpart */
092        public boolean isParentOf(Subpart subpart) {
093            if (subpart.getParent()==null) return false;
094            if (subpart.getParent().equals(this)) return true;
095            return isParentOf(subpart.getParent());
096        }
097        
098        /** Compare two subparts: put parents first, use ids if there is no parent-child relation*/
099        public int compareTo(Object o) {
100            if (o==null || !(o instanceof Subpart)) {
101                return -1;
102            }
103            Subpart s = (Subpart)o;
104            if (isParentOf(s)) return -1;
105            if (s.isParentOf(this)) return 1;
106            int cmp = getInstructionalType().compareTo(s.getInstructionalType());
107            if (cmp!=0) return cmp;
108            return Double.compare(getId(),s.getId());
109        }
110        
111        /** List of available choices of the sections of this subpart. */
112        public HashSet getChoices() {
113            HashSet choices = new HashSet();
114            for (Enumeration e=getSections().elements();e.hasMoreElements();) {
115                choices.add(((Section)e.nextElement()).getChoice());
116            }
117            return choices;
118        }
119        
120        /** Minimal penalty from {@link Section#getPenalty()} */
121        public double getMinPenalty() {
122            double min = Double.MAX_VALUE;
123            for (Enumeration e=getSections().elements();e.hasMoreElements();) {
124                Section section = (Section)e.nextElement();
125                min = Math.min(min, section.getPenalty());
126            }
127            return (min==Double.MAX_VALUE?0.0:min);
128        }
129        
130        /** Maximal penalty from {@link Section#getPenalty()} */
131        public double getMaxPenalty() {
132            double max = Double.MIN_VALUE;
133            for (Enumeration e=getSections().elements();e.hasMoreElements();) {
134                Section section = (Section)e.nextElement();
135                max = Math.max(max, section.getPenalty());
136            }
137            return (max==Double.MIN_VALUE?0.0:max);
138        }
139        
140        /** Return children subparts*/
141        public Vector getChildren() {
142            Vector ret = new Vector(getConfig().getSubparts().size());
143            for (Enumeration e=getConfig().getSubparts().elements();e.hasMoreElements();) {
144                Subpart s = (Subpart)e.nextElement();
145                if (this.equals(s.getParent())) ret.add(s);
146            }
147            return ret;
148        }
149    }