content: package org.opencyc.util;
  
  import javax.swing.SwingUtilities;
  
  /**
   * This is the 3rd version of SwingWorker (also known as
   * SwingWorker 3), an abstract class that you subclass to
   * perform GUI-related work in a dedicated thread.  For
   * instructions on using this class, see:
   * 
   * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
   *
   * Note that the API changed slightly in the 3rd version:
   * You must now invoke start() on the SwingWorker after
   * creating it.
   * 
   * Note: tbrussea added an event callback wrapper class based
   * on this one, called CycWorker that should be easier to use.
   * <p>
   * THIS SOFTWARE AND KNOWLEDGE BASE CONTENT ARE PROVIDED ``AS IS'' AND
   * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
   * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OPENCYC
   * ORGANIZATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE AND KNOWLEDGE
   * BASE CONTENT, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   * @version $Id: SwingWorker.java 138070 2012-01-10 19:46:08Z sbrown $
   */
  public abstract class SwingWorker {
      private Object value;  // see getValue(), setValue()
      private Thread thread;
      private Exception exception;
   
      /** 
       * Class to maintain reference to current worker thread
       * under separate synchronization control.
       */
      public static class ThreadVar {
          protected Thread thread;
          ThreadVar(Thread t) { thread = t; }
          public synchronized Thread get() { return thread; }
          public synchronized void clear() { thread = null; }
      }
  
      protected ThreadVar threadVar;
  
      /** 
       * Get the value produced by the worker thread, or null if it 
       * hasn't been constructed yet.
       */
      protected synchronized Object getValue() { 
          return value; 
      }
  
      /** 
       * Set the value produced by worker thread 
       */
      private synchronized void setValue(Object x) { 
          value = x; 
      }
  
      /** 
       * Compute the value to be returned by the <code>get</code> method. 
       */
      public abstract Object construct() throws Exception;
  
      /**
       * Called on the event dispatching thread (not on the worker thread)
       * after the <code>construct</code> method has returned.
       */
      public void finished() {
      }
  
      /**
       * A new method that interrupts the worker thread.  Call this method
       * to force the worker to stop what it's doing.
       */
      public void interrupt() {
          Thread t = threadVar.get();
          if (t != null) {
              t.interrupt();
          }
          threadVar.clear();
      }
  
      /**
       * Return the value created by the <code>construct</code> method.  
       * Returns null if either the constructing thread or the current
       * thread was interrupted before a value was produced.
       * 
       * @return the value created by the <code>construct</code> method
       */
      public Object get() {
          while (true) {  
              Thread t = threadVar.get();
              if (t == null) {
                  return getValue();
              }
              try {
                  t.join();
              }
              catch (InterruptedException e) {
                  Thread.currentThread().interrupt(); // propagate
                  return null;
              }
          }
      }
  
  
      /**
       * Start a thread that will call the <code>construct</code> method
       * and then exit.
       */
      public SwingWorker() {
          final Runnable doFinished = new Runnable() {
             public void run() { finished(); }
          };
  
          Runnable doConstruct = new Runnable() { 
              public void run() {
                  try {
                      setValue(construct());
                  } catch (Exception e) {
                    setException(e);
                  } finally {
                      threadVar.clear();
                  }
  
                  SwingUtilities.invokeLater(doFinished);
              }
          };
  
          Thread t = new Thread(doConstruct);
          threadVar = new ThreadVar(t);
      }
      
      /**
       * Start the worker thread.
       */
      public void start() {
          Thread t = threadVar.get();
          if (t != null) {
              t.start();
          }
      } 
      
    public Exception getException() {
      return exception;
    }
    
    public void setException(Exception exception) { 
      this.exception = exception;
    }
  
  }
  
  