/******************************************************** * Copyright (C) 2008 Course Scheduler Team * * This program is free software; you can redistribute it and/or modify it under the terms of * the GNU General Public License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, write to: * Free Software Foundation, Inc. * 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA ********************************************************/ /********************************************************* * Course Scheduler * File: BuildScheduleThread.java * * Contains class: * * BuildScheduleThread: * * Purpose: To manage building of schedules and * properly displayingprogress bars * * @author Mike Reinhold *********************************************************/ package Scheduler; //declare as member of scheduler package /******************************************************** * Import the Swing Worker class to implement ********************************************************/ import java.util.ArrayList; import java.util.Arrays; import java.util.NoSuchElementException; import java.util.TreeMap; import javax.swing.DefaultListModel; //import list model import javax.swing.ProgressMonitor; import javax.swing.SwingWorker; //import swing worker import javax.swing.JOptionPane; //import the option pane /******************************************************** * Class BuildScheduleThread * * @purpose Manage the parsing thread so the gui * doesn't freeze when executing the parse routine * * @see SwingWorker ********************************************************/ public class BuildScheduleThread extends SwingWorker<Schedule[], Void>{ /******************************************************** * UPDATE SERIAL VERSION IN VERSION WHEN THIS FILE CHANGES ********************************************************/ protected final static long versionID = 2008101300068L; /******************************************************** * The following are the fileds of the worker thread ********************************************************/ private boolean allowClosed; //if closed courses are allowed private String[] classes; //the course keys to use private ArrayList<String> primary; //the course keys for primary courses private int useMin; //the minimum number of courses to allow private MakeSchedule owner; //the owning frame private boolean allowPopup; //if the popup for no courses found is allowed private ThreadSynch sync; //the thread synch object private CourseType type; //the course types allowed private TreeMap<String, boolean[]> allowedSections;//the sections that are allowed private TreeMap<String, Integer> numberSelections;//the number of each section private boolean reportingEnabled; //if conflict reporting is enabled /******************************************************** * @purpose Does the background task when the task is run * * @see Override, SwingWorker * * @throws Exception * * @return Database: the completed database ********************************************************/ @Override protected Schedule[] doInBackground() throws Exception { sync = new ThreadSynch(); sync.finished = 0; sync.allowUpdate = true; sync.setOwner(owner); sync.setPrimary(primary); sync.setType(type); ProgressMonitor progress = new ProgressMonitor(Main.master, "Building Schedules: ", "Calculating Combinations and Assigning Schedule Tests to Threads",0, 2); //set up progress monitor sync.setWatch(progress); boolean[][] allowSection = new boolean[classes.length][]; int[] numberSections = new int[classes.length]; for(int temp = 0; temp < classes.length; temp++){ allowSection[temp] = allowedSections.get(classes[temp]); numberSections[temp] = numberSelections.get(classes[temp]).intValue(); } return owner.local.makeSchedulesOpt(classes, primary, allowClosed, useMin, sync, allowSection, numberSections, reportingEnabled);//return the schedules } /******************************************************** * @purpose To restore everything when the task is done * * @see Override, SwingWorker ********************************************************/ @Override protected void done(){ try{ //required by get() if(sync.isCanceled()){ JOptionPane.showMessageDialog(Main.master, "Schedule build cancelled by user", "Build Cancelled", JOptionPane.ERROR_MESSAGE); } else{ Schedule[] possible = get(); //get the result of the tast if (sync.failed){ throw new NoSuchElementException(); } owner.schedulesModel = new DefaultListModel();//make new list model for(Schedule item: possible){ //for each schedule found owner.schedulesModel.addElement(item);//add it to the model } Conflict[] confs = sync.getConflicts().toArray(new Conflict[0]); Arrays.sort(confs); for(Conflict conf: confs){ owner.schedulesModel.addElement(conf); } owner.schedules.setListData(owner.schedulesModel.toArray()); //set the list data if(owner.schedulesModel.getSize() != 0){ Object item = owner.schedulesModel.getElementAt(0); owner.showSchedule(item); owner.schedules.setSelectedIndex(0);//set selected index } else{ owner.showSchedule(null); if(allowPopup){ JOptionPane.showMessageDialog(Main.master, "No available schedules for the requested courses.", "No Schedules Found", JOptionPane.INFORMATION_MESSAGE); } } } } catch (NoSuchElementException ex1){ owner.updateSchedules(true); } catch (Exception ex){ //catch exception JOptionPane.showMessageDialog(owner, "Unable to create schedules for the selected classes.", "Unable to Build Schedules", JOptionPane.ERROR_MESSAGE); int[] vals = new int[owner.scheduleClassModel.size()]; for(int col = 0; col < vals.length; col++){ vals[col] = col; } owner.scheduleClassList.setSelectedIndices(vals); owner.removeCourse.doClick(); } //do nothing owner.updateScheduleCount(); owner.setEnabled(true); //reenable the owning gui owner.conditionalDisable(); sync.closeWatch(); Main.master.requestFocus(); //request focus owner.schedules.requestFocusInWindow(); } /******************************************************** * @purpose Returns if closed courses are allowed * * @return boolean: if closed courses are allowed in the schedule ********************************************************/ public boolean isAllowClosed() { return allowClosed; //return if closed courses are allowed } /******************************************************** * ********************************************************/ public void setAllowClosed(boolean allowClosed) { this.allowClosed = allowClosed; } /******************************************************** * ********************************************************/ public String[] getClasses() { return classes; } /******************************************************** * ********************************************************/ public void setClasses(String[] classes) { this.classes = classes; } /******************************************************** * ********************************************************/ public int getUseMin() { return useMin; } /******************************************************** * ********************************************************/ public void setUseMin(int useMin) { this.useMin = useMin; } /******************************************************** * ********************************************************/ public MakeSchedule getOwner() { return owner; } /******************************************************** * ********************************************************/ public void setOwner(MakeSchedule owner) { this.owner = owner; } /******************************************************** * ********************************************************/ public boolean isAllowPopup() { return allowPopup; } /******************************************************** * ********************************************************/ public void setAllowPopup(boolean allowPopup) { this.allowPopup = allowPopup; } public ArrayList<String> getPrimary() { return primary; } public void setPrimary(ArrayList<String> primary) { this.primary = primary; } public CourseType getType() { return type; } public void setType(CourseType type) { this.type = type; } public TreeMap<String, boolean[]> getAllowedSections() { return allowedSections; } public void setAllowedSections(TreeMap<String, boolean[]> allowedSections) { this.allowedSections = allowedSections; } public TreeMap<String, Integer> getNumberSelections() { return numberSelections; } public void setNumberSelections(TreeMap<String, Integer> numberSelections) { this.numberSelections = numberSelections; } public boolean isReportingEnabled() { return reportingEnabled; } public void setReportingEnabled(boolean reportingEnabled) { this.reportingEnabled = reportingEnabled; } }