/* * Get Organized - Organize your schedule, course assignments, and grades * Copyright © 2012 Alex Laird * getorganized@alexlaird.com * alexlaird.com * * 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, either version 3 of the License, or * (at your option) any later version. * * 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, see <http://www.gnu.org/licenses/>. */ package adl.go.resource; import adl.go.gui.Domain; import adl.go.gui.ViewPanel; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.text.ParseException; import java.util.Date; /** * The thread which continually checks if changes have been made and need to be * saved. * * @author Alex Laird */ public class WorkerThread extends Thread { /** * The main frame of the application. */ private ViewPanel viewPanel; /** * The domain for the main frame. */ private Domain domain; /** * If the thread is already in a save operation, a second save operation may * not be called on it until the first finishes. */ public boolean saving = false; /** * Save, if save is needed, every thirty seconds. */ private final long delay = 500; /** * The next time (system clock in ms) that a save will be attempted. */ private long nextSave = 0; /** * Check if the thread should quit. */ private boolean wantToQuit = false; /** * True if a save is allowed, false otherwise. */ private boolean allowSave = false; /** * Constructs the load/save thread with a reference to the main frame and a * reference to the local utility object. * * @param viewPanel A reference to the main frame of the application. * @param domain The domain for the main frame. */ public WorkerThread(ViewPanel viewPanel, Domain domain) { this.viewPanel = viewPanel; this.domain = domain; } /** * Sets the quit state of the thread to true, so it will not execute its * actions after each delay. It can be set back to running by calling run() * at any time. */ public void stopRunning() { wantToQuit = true; } /** * Sets the quit state of the thread to false, so it will start execution * again. * * @param allowSave Set the state of the allow save flag. */ public void setAllowSave(boolean allowSave) { this.allowSave = allowSave; } /** * Starts the save thread and checks every delay interval to see if changes * have been made and settings should be saved to the file. */ @Override public void run() { while (!wantToQuit) { try { sleep (delay); } catch (InterruptedException ex) { Domain.LOGGER.add (ex); } // Grab the time to see if this thread needs to execute an action long currTime = System.currentTimeMillis (); if (allowSave && nextSave <= currTime) { save (); nextSave = currTime + 500; } } } /** * Calls the respective save methods if changes have been made. */ protected synchronized void save() { if (!viewPanel.initLoading) { String prevDate = Domain.DATE_FORMAT.format (domain.today); if (domain.needsPreferencesSave) { domain.savePreferences (); try { domain.today = Domain.DATE_AND_TIME_FORMAT.parse (Domain.DATE_AND_TIME_FORMAT.format (new Date ())); } catch (ParseException ex) { Domain.LOGGER.add (ex); } domain.needsPreferencesSave = false; } if (domain.needsUserDetailsSave) { domain.saveUserDetails (); try { domain.today = Domain.DATE_AND_TIME_FORMAT.parse (Domain.DATE_AND_TIME_FORMAT.format (new Date ())); } catch (ParseException ex) { Domain.LOGGER.add (ex); } domain.needsUserDetailsSave = false; } if (domain.needsCoursesAndTermsSave) { domain.saveSettings (); try { domain.today = Domain.DATE_FORMAT.parse (Domain.DATE_FORMAT.format (new Date ())); } catch (ParseException ex) { Domain.LOGGER.add (ex); } domain.needsCoursesAndTermsSave = false; } for (int i = 0; i < domain.utility.courses.size (); ++i) { if (domain.utility.courses.get (i).isChanged ()) { domain.saveAssignments (domain.utility.courses.get (i)); try { domain.today = Domain.DATE_FORMAT.parse (Domain.DATE_FORMAT.format (new Date ())); } catch (ParseException ex) { Domain.LOGGER.add (ex); } } } for (int i = 0; i < domain.utility.eventYears.size (); ++i) { if (domain.utility.eventYears.get (i).isChanged ()) { domain.saveEvents (domain.utility.eventYears.get (i)); try { domain.today = Domain.DATE_FORMAT.parse (Domain.DATE_FORMAT.format (new Date ())); } catch (ParseException ex) { Domain.LOGGER.add (ex); } } } if (!prevDate.equals (Domain.DATE_FORMAT.format (domain.today))) { viewPanel.refindToday (); } // save anything that is stored in the logger, then clear it if (Domain.LOGGER.size () > 0) { try { BufferedWriter out = new BufferedWriter (new FileWriter (domain.logFile, true)); Date date = new Date (); out.write ("------------------------------------\n"); out.write ("Date: " + Domain.DATE_AND_FULL_TIME_FORMAT.format (date) + "\n"); for (int i = 0; i < Domain.LOGGER.size (); ++i) { Exception ex = (Exception) Domain.LOGGER.get (i); out.write ("Error: " + ex.getClass () + "\n"); out.write ("Message: " + ex.getMessage () + "\n--\nTrace:\n"); Object[] trace = ex.getStackTrace (); for (int j = 0; j < trace.length; ++j) { out.write (" " + trace[j].toString () + "\n"); } out.write ("--\n\n"); out.write ("----\n"); } out.write ("------------------------------------\n\n\n"); out.flush (); Domain.LOGGER.clear (); } catch (IOException ex) { } } } } }