Clover coverage report - gsbase - 2.0.1
Coverage timestamp: Sat Jan 1 2005 12:30:02 EST
file stats: LOC: 288   Methods: 14
NCLOC: 91   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
AbstractUIController.java 100% 89.7% 71.4% 85.7%
coverage coverage
 1    /*
 2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
 3    *
 4    * Redistribution and use in source and binary forms, with or without
 5    * modification, are permitted provided that the following conditions are met:
 6    *
 7    * 1. Redistributions of source code must retain the above copyright notice,
 8    * this list of conditions and the following disclaimer.
 9    * 2. Redistributions in binary form must reproduce the above copyright notice,
 10    * this list of conditions and the following disclaimer in the documentation
 11    * and/or other materials provided with the distribution.
 12    * 3. The end-user documentation included with the redistribution, if any, must
 13    * include the following acknowledgment:
 14    *
 15    * "This product includes software developed by Gargoyle Software Inc.
 16    * (http://www.GargoyleSoftware.com/)."
 17    *
 18    * Alternately, this acknowledgment may appear in the software itself, if
 19    * and wherever such third-party acknowledgments normally appear.
 20    * 4. The name "Gargoyle Software" must not be used to endorse or promote
 21    * products derived from this software without prior written permission.
 22    * For written permission, please contact info@GargoyleSoftware.com.
 23    * 5. Products derived from this software may not be called "GSBase", nor may
 24    * "GSBase" appear in their name, without prior written permission of
 25    * Gargoyle Software Inc.
 26    *
 27    * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
 28    * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 29    * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
 30    * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 31    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 32    * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 33    * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 34    * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 35    * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 36    * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 37    */
 38    package com.gargoylesoftware.base.gui;
 39   
 40    import com.gargoylesoftware.base.util.DetailedNullPointerException;
 41    import java.util.Locale;
 42    import javax.swing.SwingUtilities;
 43   
 44    /**
 45    * An abstract superclass for GUI controller classes.<p>
 46    *
 47    * Swing uses an architecture similar to Model-View-Controller (MVC) in which the model, view
 48    * and controller components are kept seperate from each other. This class provides
 49    * some common behaviour that is useful for controller objects. This includes support for:
 50    * <ul>
 51    *
 52    * <li>Starting and managing worker threads. See {@link #startTask(WorkerTask)},
 53    * {@link #taskComplete(WorkerTask)}, {@link #taskSuccessful(WorkerTask)},
 54    * {@link #taskExceptionThrown(WorkerTask,Exception)},
 55    * {@link #taskErrorThrown(WorkerTask,Throwable)}
 56    * <br />&nbsp;</li>
 57    *
 58    * <li>Simple support for localization. See {@link #setLocale(Locale)},
 59    * {@link #getLocale()}, {@link #localeChanged(Locale)}</li>
 60    *
 61    * </ul>
 62    *
 63    * @version $Revision: 1.7 $
 64    * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
 65    */
 66    public abstract class AbstractUIController {
 67    private Locale locale_ = Locale.getDefault();
 68   
 69   
 70    private class TaskRunnable implements Runnable {
 71    private Throwable throwable_;
 72    private final WorkerTask task_;
 73   
 74    /**
 75    * Create an instance
 76    * @param task The task that will be run
 77    */
 78  6 public TaskRunnable( final WorkerTask task ) {
 79  6 task_ = task;
 80    }
 81   
 82    /** Run the task */
 83  6 public void run() {
 84   
 85  6 try {
 86  6 task_.runOnWorkerThread();
 87    }
 88    catch( final Throwable t ) {
 89  2 throwable_ = t;
 90    }
 91  6 SwingUtilities.invokeLater(
 92    new Runnable() {
 93  6 public void run() {
 94  6 try {
 95  6 run2();
 96    }
 97    catch( final Throwable t ) {
 98  0 t.printStackTrace();
 99    }
 100    }
 101  6 public void run2() {
 102  6 if( throwable_ != null ) {
 103  2 if( throwable_ instanceof Exception ) {
 104  1 taskExceptionThrown( task_,
 105    (Exception)throwable_ );
 106    }
 107    else {
 108  1 taskErrorThrown( task_, throwable_ );
 109    }
 110    }
 111    else {
 112  4 try {
 113  4 task_.runOnUIThread();
 114  2 taskSuccessful( task_ );
 115    }
 116    catch( final Exception e ) {
 117  1 taskExceptionThrown( task_, e );
 118    }
 119    catch( final Throwable t ) {
 120  1 taskErrorThrown( task_, t );
 121    }
 122    }
 123  6 taskComplete( task_ );
 124    }
 125    } );
 126    }
 127    }
 128   
 129   
 130    /**
 131    * Create a new controller.
 132    */
 133  8 public AbstractUIController() {
 134    }
 135   
 136   
 137    /**
 138    * Set the current locale
 139    *
 140    * @param locale the new locale
 141    */
 142  2 public final void setLocale( final Locale locale ) {
 143  2 assertNotNull("locale", locale);
 144  1 locale_ = locale;
 145  1 localeChanged( locale_ );
 146    }
 147   
 148   
 149    /**
 150    * Return the current locale.
 151    *
 152    * @return The current locale
 153    */
 154  3 public final Locale getLocale() {
 155  3 return locale_;
 156    }
 157   
 158   
 159    /**
 160    * The main entry point into this controller
 161    */
 162  1 public final void run() {
 163  1 localeChanged( getLocale() );
 164  1 runImpl();
 165    }
 166   
 167   
 168    /**
 169    * Subclasses will override this to provide the run logic
 170    */
 171    protected abstract void runImpl();
 172   
 173   
 174    /**
 175    * Start a WorkerTask. This involves running some code on a background
 176    * thread and then some more on the ui thread. See WorkerTask for more
 177    * details. <p>
 178    *
 179    * When the task has completed, one of the following callbacks will be
 180    * called based on the success of the task.
 181    * <ul>
 182    * <li> If the task completed without error then {@link
 183    * #taskSuccessful(com.gargoylesoftware.base.gui.WorkerTask)
 184    * taskSuccessful()} will be called
 185    * <li> If an exception was thrown during processing of the task then
 186    * {@link #taskExceptionThrown(com.gargoylesoftware.base.gui.WorkerTask,Exception)
 187    * taskExceptionThrown()} will be called
 188    * <li> If an error was thrown during processing of the task then {@link
 189    * #taskErrorThrown(com.gargoylesoftware.base.gui.WorkerTask,Throwable)
 190    * taskErrorThrown()} will be called
 191    * </ul>
 192    * <br />
 193    * Finally, the method {@link #taskComplete(com.gargoylesoftware.base.gui.WorkerTask)
 194    * taskSuccessful()} will be called will be called to signal the completion
 195    * of the task
 196    *
 197    * @param task The WorkerTask that is about to execute.
 198    */
 199  6 protected final void startTask( final WorkerTask task ) {
 200  6 new Thread( new TaskRunnable(task) ).start();
 201    }
 202   
 203   
 204    /**
 205    * A callback that will be invoked when an exception is thrown during the
 206    * processing of a WorkerTask. Note that errors and other throwables will
 207    * processed by the method {@link #taskErrorThrown(WorkerTask,Throwable)}.<p>
 208    *
 209    * The default behaviour is to print the stack trace of the caught exception
 210    * to System.out. Override this method to provide custom error handling.
 211    *
 212    * @param task The task that failed
 213    * @param exception The exception that was caught.
 214    */
 215  0 protected void taskExceptionThrown( final WorkerTask task, final Exception exception ) {
 216  0 exception.printStackTrace();
 217    }
 218   
 219   
 220    /**
 221    * A callback that will be invoked when a system error is thrown during the
 222    * processing of a WorkerTask. System errors are any throwable objects not
 223    * descended from Exception. Typically, only system level code will be
 224    * concerned by the errors handled by this method. Application code should
 225    * only be concerned with the errors handled by
 226    * {@link #taskExceptionThrown(WorkerTask,Exception)}.
 227    *
 228    * The default behaviour is to print the stack trace of the caught error
 229    * to System.out. Override this method to provide custom error handling.
 230    *
 231    * @param task The task that failed
 232    * @param throwable The throwable object that was caught
 233    */
 234  0 protected void taskErrorThrown( final WorkerTask task, final Throwable throwable ) {
 235  0 throwable.printStackTrace();
 236    }
 237   
 238   
 239    /**
 240    * A callback that will be invoked when a task completed successfully.
 241    * Override this method to provide custom handling on completion
 242    * of a task.<p>
 243    *
 244    * The default behaviour is to do nothing. Override this to provide custom
 245    * behaviour.
 246    *
 247    * @param task The task that just finished.
 248    */
 249  0 protected void taskSuccessful( final WorkerTask task ) {
 250    }
 251   
 252   
 253    /**
 254    * A callback that will be invoked when a task has completed whether it was
 255    * successful or not. Override this method to provide custom handling on
 256    * completion of a task.
 257    *
 258    * The default behaviour is to do nothing. Override this to provide custom
 259    * behaviour.
 260    *
 261    * @param task The task that just finished.
 262    */
 263  0 protected void taskComplete( final WorkerTask task ) {
 264    }
 265   
 266   
 267    /**
 268    * The current locale has changed - update all locale specific information.
 269    * All logic that sets locale sensitive information should be executed in
 270    * this method.
 271    *
 272    * @param locale The new locale
 273    */
 274    protected abstract void localeChanged( final Locale locale );
 275   
 276   
 277    /**
 278    * Throw an exception if the specified object is null
 279    * @param fieldName The name of the paremeter we are checking
 280    * @param object The value of the parameter we are checking
 281    */
 282  2 protected final void assertNotNull( final String fieldName, final Object object ) {
 283  2 if( object == null ) {
 284  1 throw new DetailedNullPointerException("fieldName");
 285    }
 286    }
 287    }
 288