/********************************************************
* 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: ParseThread.java
*
* Contains class:
*
* ParseThread:
*
* Purpose: To managae downloading and parsing from
* Banner and Rate-My-Professor to allow progress
* monitoring
*
* @author Mike Reinhold
*********************************************************/
package Scheduler; //declare as member of scheduler package
/********************************************************
* Import the Swing Worker class to implement
********************************************************/
import java.awt.Component; //import Component superclass
import java.util.Scanner; //import scanner utility
import javax.swing.JOptionPane; //import JOptionPane
import javax.swing.ProgressMonitor; //import progress monitor
import javax.swing.SwingWorker; //import swing worker
/********************************************************
* Class ParseThread
*
* @purpose Manage the parsing thread so the gui
* doesn't freeze when executing the parse routine
*
* @see SwingWorker
********************************************************/
public class ParseThread extends SwingWorker<Database, Void> {
/********************************************************
* UPDATE SERIAL VERSION IN VERSION WHEN THIS FILE CHANGES
********************************************************/
protected final static long versionID = 2013010900068L; //class version
/********************************************************
* The following are the protected fields of the Thread
********************************************************/
private Parser engine; //the parsing engine to use
private String term; //the term to query for
private String url; //the url to query
private ThreadSynch sync; //thread synch helper
/********************************************************
* @purpose Does the background task when the task is run
*
* @see Override, SwingWorker
*
* @throws Exception
*
* @return Database: the completed database
********************************************************/
@Override
protected Database doInBackground() throws Exception {
sync = new ThreadSynch(); //create the thread synchronization object
sync.finished = 0; //set finished to none
ProgressMonitor watch = new ProgressMonitor(Main.master, "Downloading: " + Term.getTermString(term)
, "", 0, 500); //create progress monitor
watch.setMillisToDecideToPopup(0); //set to decide to popup right away
watch.setMillisToPopup(0); //set to popup right away
sync.setWatch(watch); //set the progress monitor
sync.updateWatch("Connecting to www.ratemyprofessors.com", 0);//set initial text
return Parser.parseCourses(engine, new String(term), url, sync);//return the database
}
/********************************************************
* @purpose To restore everything when the task is done
*
* @see Override, SwingWorker
********************************************************/
@Override
protected void done(){
Database local = null; //clear database
if(sync.isCanceled()){ //check if user cancelled
JOptionPane.showMessageDialog(Main.master, //show cancelled message
"Download cancelled by user!", "Cancelled", JOptionPane.ERROR_MESSAGE);
}
try{ //required by get()
local = get(); //get the result of the thread
if (local != null){ //check if null result
Main.terms.put(term, local); //get the result of the task
local.save(); //save the database
Main.master.setEnabled(true); //reenable the master gui
if(Main.master != null){ //update any make schedule tabs that need it
for(int pos = 0; pos < Main.master.tabControl.getTabCount(); pos++){//for each tab
Component item = Main.master.tabControl.getComponentAt(pos);//get the component there
if(item instanceof MakeSchedule){//check the class
String title = Main.master.tabControl.getTitleAt(pos);
if(title.contains("-")){ //check if needs to be parsed
Scanner parse = new Scanner(title);//make a parser
parse.useDelimiter(" - ");//set delimiter
title = parse.next().trim();//get term title
parse.close();
}
String term = Term.getTermString(local.getTerm());//get term string
if(title.compareTo(term) == Compare.equal.value()){
((MakeSchedule)item).setDatabase(local, true, true);//set database and update schedueles
}
}
}
Main.master.mainMenu.newScheduleMenu.setEnabled(true);//enable the new schedule menu item
}
}
}
catch (Exception ex){ //catch exception
if(Main.terms.get(Main.prefs.getCurrentTerm()) == null){
Main.master.mainMenu.newScheduleMenu.setEnabled(false);//disable the new schedule menu item
}
} //do nothing
finally{
Main.displayDate(); //display the download date
Main.master.setEnabled(true); //reenable
Main.master.requestFocus(); //request focus
if(Main.termChanged){ //check if the term changed
String newTerm = Main.prefs.getCurrentTerm();//get new term
String term = Term.getTermString(newTerm); //convert term to title
boolean newMake = true; //for deciding if we need a new make schedule tab
for(int pos = 0; pos < Main.master.tabControl.getTabCount(); pos++){//for each tab
Component com = Main.master.tabControl.getComponentAt(pos);//get the component there
if(com instanceof MakeSchedule){//check the class
String title = Main.master.tabControl.getTitleAt(pos);//get tab title
if(title.contains("-")){ //check if needs to be parsed
Scanner parse = new Scanner(title);//make a parser
parse.useDelimiter(" - ");//set delimiter
title = parse.next().trim();//get term title
parse.close();
}
if(title.compareTo(term) == Compare.equal.value()){//check if equal
newMake = false; //do not need new make
}
}
}
if(newMake && local != null){ //check if should prompt for new schedule
int result = JOptionPane.showOptionDialog(Main.master, "Create a new schedule for " +
Term.getTermString(newTerm), "Create new Schedule?",//ask if we want a new make schedule tab
JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
null, null, null);
if(result == JOptionPane.YES_OPTION){ //if result is yes
Main.master.mainMenu.newScheduleMenu.doClick();//make tab
}
}
Main.termChanged = false; //reset the changed flag
}
Main.reRateAll();
sync.closeWatch(); //close the progress monitor
}
}
/********************************************************
* @purpose returns the engine used by this task
*
* @return Parser: the parsing engine used
********************************************************/
public Parser getEngine() {
return engine; //return the parsing engine
}
/********************************************************
* @purpose Sets the parser engine
*
* @param Parser engine: the engine to assign to thie task
********************************************************/
public void setEngine(Parser engine) {
this.engine = engine; //set the engine
}
/********************************************************
* @purpose returnt the term specified for this thread
*
* @return String: the term associated with this thread
********************************************************/
public String getTerm() {
return term; //return this term
}
/********************************************************
* @purpose Set the term associated with this thread
*
* @param String term: the string to set this thread's term to
********************************************************/
public void setTerm(String term) {
this.term = term; //set the term
}
/********************************************************
* @purpose return the url associated with the thread
*
* @return String: the url associated with this thread
********************************************************/
public String getUrl() {
return url; //return the url
}
/********************************************************
* @purpose Sets the url for the thread
*
* @param String url: the url to associate with this thread
********************************************************/
public void setUrl(String url) {
this.url = url; //set the url
}
}