BackgroundMonitor.java :  » Game » iTunes-Duplicate-Song-Manager-0.9.6 » core » background » Java Open Source

Java Open Source » Game » iTunes Duplicate Song Manager 0.9.6 
iTunes Duplicate Song Manager 0.9.6 » core » background » BackgroundMonitor.java
/**
 * BackgroundMonitor.java
 *
 * Copyright (c) 2009 Brian Gibowski <brian@brgib.com>. All rights reserved.
 *
 * This file is part of iTunesDSM.
 *
 * iTunesDSM 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.
 *
 * iTunesDSM 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 iTunesDSM.  If not, see <http://www.gnu.org/licenses/>.
 */

package core.background;

import data.OutputStringArrayList;
import display.Display;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.SwingWorker.StateValue;
import task.AddTracksTask;
import ui.SysTrayMain;
import ui.Status;

/**
 *
 * The BackgroundMonitor class is used to start and stop a FolderWatcher instance.
 * The class also sets listeners on the AllFiles object, and FolderWatcher instances
 * through a Status interface to monitor progress and report it to the user.
 *
 *
 * @author Brian Gibowski brian@brgib.com
 */
public class BackgroundMonitor extends Thread{

    /**
     * The default time to check the directory is 1 hour.
     * This value is 1 hour represented in milliseconds.
     */
    public static final long DEFAULT_SLEEP_TIME_MILLISECS = 3600000L;

    /**
     * The default time to check the directory is 1 hours.
     */
    public static final int DEFAULT_SLEEP_TIME_HOURS =
            (int)DEFAULT_SLEEP_TIME_MILLISECS / 60 / 60 / 1000;

    

    
    private Logger log = Logger.getLogger("global");
    private Status status;

    private long timeDelay;

    private Date nextRunTime;


    private boolean runATT = false;

    private AddTracksTask a;

    private ArrayList<BackgroundMonitorStatusListener> listeners =
            new ArrayList<BackgroundMonitorStatusListener>();

    /**
     * Creates a new BackgroundMonitor object with the default time delay.
     * The background monitor thread is automatically started.
     *
     */
    public BackgroundMonitor(){
        this(DEFAULT_SLEEP_TIME_MILLISECS);

    }

    /**
     * Creates a new BackgroundMonitor object.  The status object must be initialized
     * here with the setStatus method before starting or stopping a background
     * monitor object.  Otherwise NullPointerExceptions will be thrown.
     *
     * @param timeHoursDelay The time in hours to delay execution of searching for new tracks.
     */
    public BackgroundMonitor(int timeHoursDelay){
        this((long)(60 * 60 * 1000 * timeHoursDelay));
    }

    /**
     * Creates a new BackgroundMonitor object with the given time delay in milliseconds.
     * The background monitor thread is automatically started within this constructor.
     *
     * @param timeDelay The amount of time between new track searches in milliseconds.
     */
    public BackgroundMonitor(long timeDelay){
        this.timeDelay = timeDelay;
        this.start();
        this.setPriority(Thread.MIN_PRIORITY);
    }

    /**
     * Sets the time delay to the given long value.
     *
     * @param delay The amount of time between searches for new tracks in
     * milliseconds.
     */
    public void setTimeDelay(long delay) {
        this.timeDelay = delay;
    }

    /**
     * Sets the time delay to the given time in hours.
     *
     * @param hours The amount of time between searches for new tracks in
     * hours.
     */
    public void setTimeDelayHours(int hours){
        this.timeDelay = (long)(hours * 60 * 60 * 1000);
    }



    /**
     * Sets the status object the background monitor object should
     * report status information to.
     *
     * @param status The status object that the Background Monitor object
     * will report status updates too.  If the status object has not
     * been initialized NullPointerExceptions will be thrown.
     */
    public void setStatus(Status status){
        this.status = status;
    }

    /**
     * Stops the folder watcher instance if it is running.  The status
     * instance and the system tray icon report the stopped folder watcher
     * as well.
     *
     */
    public void stopBackgroundMonitor(){        
        if(a != null && !a.isDone()){
            a.cancel(true);
        }
        runATT = false;
        setNextRun(null);
        dispatchBackgroundMonitorStatusEvents(BackgroundMonitorStatusEvent.STOPPED,
                BackgroundMonitorStatusEvent.NON_PROGRESS_EVENT);
    }

  

    /**
     * Starts a new Folder Watcher instance given the constructor variables.  The
     * requisite listeners are also applied to the folder watcher instance.
     *
     * @param filesToMonitor The directories to monitor.
     *
     * @param timeHoursDelay The amount of time between checks for changed folders
     * in hours.
     */
    public void startBackgroundMonitor(final ArrayList<File> filesToMonitor, final int timeHoursDelay){
        setTimeDelayHours(timeHoursDelay);
        if(filesToMonitor == null){
            NullPointerException e =
                    new NullPointerException("Fie to monitor is null");
            log.log(Level.SEVERE, this.getClass().getName(), e);
            throw e;
        }
        
        if(isRunning()){
            return;
        }
        
        final CheckDirsExist checkDirs = new CheckDirsExist(filesToMonitor);
        checkDirs.addPropertyChangeListener(new PropertyChangeListener(){
            @Override
            public void propertyChange(PropertyChangeEvent e){
                if(checkDirs.getState() == StateValue.DONE && !runATT){
                    try{
                        ArrayList<File> notDirs = checkDirs.get();
                        if(notDirs.size() > 0){ //if one or more dirs does not exist
                            Display.newWarningMessage("Directory to monitor",
                                    "Sorry, iTunesDSM is unable to locate" +
                                    " directories:\n" + getNotDirsPaths(notDirs) +
                                    ".\nBackground monitoring will cancel.");
                            runATT = false;
                            dispatchBackgroundMonitorStatusEvents(
                                    BackgroundMonitorStatusEvent.STOPPED,
                                    BackgroundMonitorStatusEvent.NON_PROGRESS_EVENT);

                        }
                        else{
                            setTimeDelay(SysTrayMain.OPTIONS.getBackgroundDelay());
                            setNextRun();
                            dispatchBackgroundMonitorStatusEvents(
                                BackgroundMonitorStatusEvent.STARTED,
                                BackgroundMonitorStatusEvent.NON_PROGRESS_EVENT);
                            runATT = true;
                        }
                    }
                    catch(InterruptedException ie){
                        log.log(Level.SEVERE, this.getClass().getName(), ie);

                    }
                    catch(ExecutionException ee){
                        log.log(Level.SEVERE, this.getClass().getName(), ee);
                    }
                }
            }
        });
        checkDirs.execute();
        
    }

    /**
     * Returns whether or not a new add tracks task will execute after the
     * background monitor thread has finished sleeping.  In other words, the
     * background thread is always running, but whether or not a new task
     * to check for new files is created is determined by this boolean value.
     *
     * @return runATT If true, a new AddTracksTask object will be run when the
     * BackgroundMonitor thread is finished sleeping.
     */
    public boolean isRunning(){
        return runATT;
    }



    /**
     * Returns the amount of time in hours between checks for changed folders.
     *
     * @return Returns the amount of time in hours between checks for changed
     * folders.
     */
    public int getTimeHoursDelay() {
        return (int)timeDelay / 60 / 60 / 1000;
    }

    @Override
    public void run(){
        while(true){
            try{
                if(runATT && a == null ||
                        runATT && a != null && a.isDone()){
                    runAddTracksTask();
                }               
                Thread.sleep(timeDelay);
                //Thread.sleep(40000L); //FIXME turn off
                //Thread.sleep(5000L); //FIXME turn off
            }
            catch(InterruptedException e){
                log.log(Level.SEVERE, this.getClass().getName(), e);
            }
        }

    }


    private void runAddTracksTask(){
        if(!SysTrayMain.OPTIONS.isReady()){
            return;
        }
        a = new AddTracksTask(false); //dont monitor progress
        a.addPropertyChangeListener(new PropertyChangeListener(){
            @Override
            public void propertyChange(PropertyChangeEvent event){
                if(status != null && a.getState() == StateValue.DONE){
                    try{
                        if(!a.isCancelled() && a.isDone()){
                            int numAdded = a.get();
                            if(numAdded > 0){
                                status.setBackgroundText(numAdded +
                                        " new track(s) have been added to" +
                                        " iTunes.  Check the\n" +
                                        OutputStringArrayList.ADDED_TRACKS_FILENAME +
                                        "\nfile for new track(s).");
                            }
                            if(runATT){
                                setNextRun();
                                dispatchBackgroundMonitorStatusEvents(BackgroundMonitorStatusEvent.RUNNING,
                                        BackgroundMonitorStatusEvent.NON_PROGRESS_EVENT);
                            }
                            else{
                                setNextRun(null);
                                dispatchBackgroundMonitorStatusEvents(BackgroundMonitorStatusEvent.STOPPED,
                                        BackgroundMonitorStatusEvent.NON_PROGRESS_EVENT);
                            }
                        }
                    }
                    catch(ExecutionException e){
                        log.log(Level.SEVERE, this.getClass().getName(), e);
                    }
                    catch(InterruptedException e){
                        log.log(Level.SEVERE, this.getClass().getName(), e);
                    }
                }
                else if("progress".equals(event.getPropertyName())){
                    dispatchBackgroundMonitorStatusEvents(BackgroundMonitorStatusEvent.CHECKING_NEW_TRACKS,
                            (Integer)event.getNewValue());
                }
            }
        });
        a.execute();
    }

    /**
     * Returns a Data object that details the next check for new tracks.
     * 
     * @return The date when the next background monitor add tracks task will
     * be run.  This is a rough estimate as the Thread simply sleeps until the
     * next run time.
     */
    public Date getNextRunTime(){
        return nextRunTime;

    }

    private void setNextRun(){
        Calendar cal = Calendar.getInstance();
        long nextRunMilli = cal.getTimeInMillis() + timeDelay;
        Date nextRunDate = new Date(nextRunMilli);
        setNextRun(nextRunDate);
    }

    private void setNextRun(Date nextRunDate){
        this.nextRunTime = nextRunDate;
    }

    private String getNotDirsPaths(ArrayList<File> notDirs){
        String dirs = "";
        for(int i=0; i<notDirs.size(); i++){
            dirs += notDirs.get(i).getAbsolutePath();
            if(i != notDirs.size() - 1){
                dirs += "\n";
            }
        }
        return dirs;

    }


    /**
     * Adds a new BackgroundMonitorStatusListener object to the background monitor
     * object.
     *
     * @param listener The listener to add to the background monitor object.
     */
    public void addBackgroundMonitorStatusListener(BackgroundMonitorStatusListener listener){
        listeners.add(listener);
    }

    /**
     * Removes the listener from the BackgroundMonitor object.
     *
     * @param listener The listener to remove from the BackgroundMonitor object.
     */
    public void removeBackgroundMonitorStatusListener(BackgroundMonitorStatusListener listener){
        listeners.remove(listener);
    }

    /**
     * Alerts all listeners to a change in the BackgroundMonitor object.
     *
     * @param eventType The type of event triggered.
     * @see BackgroundMonitorStatusEvent
     */
    private void dispatchBackgroundMonitorStatusEvents(int eventType, int progress){
        BackgroundMonitorStatusEvent e = new BackgroundMonitorStatusEvent(this, eventType, progress, nextRunTime);
        for(int i=0; i<listeners.size(); i++){
            listeners.get(i).statusChange(e);
        }
    }

    

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.