/***************************************************
*
* cismet GmbH, Saarbruecken, Germany
*
* ... and it just works.
*
****************************************************/
package Sirius.navigator.method;
import Sirius.navigator.ui.progress.*;
import javax.swing.SwingUtilities;
import de.cismet.tools.CismetThreadPool;
/**
* 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:
*
* <p>http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html</p>
*
* <p>Note that the API changed slightly in the 3rd version: You must now invoke start() on the SwingWorker after
* creating it.</p>
*
* @version $Revision$, $Date$
*/
public abstract class MultithreadedMethod {
//~ Instance fields --------------------------------------------------------
protected ProgressObserver progressObserver;
private ThreadVar threadVar;
//~ Constructors -----------------------------------------------------------
/**
* Start a thread that will call the <code>construct</code> method and then exit.
*/
public MultithreadedMethod() {
this(null);
}
/**
* Creates a new MultithreadedMethod object.
*
* @param progressObserver DOCUMENT ME!
*/
public MultithreadedMethod(final ProgressObserver progressObserver) {
this.progressObserver = progressObserver;
this.threadVar = new ThreadVar();
}
//~ Methods ----------------------------------------------------------------
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final ProgressObserver getProgressObserver() {
return this.progressObserver;
}
/**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
*/
public final boolean isProgressObservable() {
return (this.progressObserver != null) ? true : false;
}
/**
* Start the worker thread.
*
* @param object DOCUMENT ME!
*/
public final void invoke(final Object object) {
if (threadVar.get() == null) {
threadVar.set(new Thread(new DoInvokeThread(), "MultithreadedMethod"));
this.init(object);
CismetThreadPool.execute(threadVar.get());
}
}
/**
* A new method that interrupts the worker thread. Call this method to force the worker to stop what it's doing.
*/
public final void interrupt() {
final Thread thread = threadVar.get();
if (thread != null) {
thread.interrupt();
}
if (this.isProgressObservable()) {
progressObserver.setInterrupted(true);
}
threadVar.clear();
}
// #########################################################################
/**
* Place your code that should be executed before the thread starts here.
*
* @param object DOCUMENT ME!
*/
protected void init(final Object object) {
}
// .........................................................................
/**
* Place your code that should be executed in a new thread here.
*/
protected abstract void doInvoke();
// .........................................................................
/**
* Place your code that should be executed after the thread has finished here. This method is called on the event
* dispatching thread.
*/
protected void finish() {
}
//~ Inner Classes ----------------------------------------------------------
// #########################################################################
/**
* Class to maintain reference to current worker thread under separate synchronization control.
*
* @version $Revision$, $Date$
*/
private static final class ThreadVar {
//~ Instance fields ----------------------------------------------------
private Thread thread = null;
//~ Methods ------------------------------------------------------------
/**
* ThreadVar(Thread thread) { this.thread = thread; }.
*
* @return DOCUMENT ME!
*/
synchronized Thread get() {
return thread;
}
/**
* DOCUMENT ME!
*/
synchronized void clear() {
thread = null;
}
/**
* DOCUMENT ME!
*
* @param thread DOCUMENT ME!
*/
synchronized void set(final Thread thread) {
if (this.thread == null) {
this.thread = thread;
}
}
}
/**
* #########################################################################.
*
* @version $Revision$, $Date$
*/
private final class DoInvokeThread implements Runnable {
//~ Methods ------------------------------------------------------------
@Override
public void run() {
try {
doInvoke();
} finally {
threadVar.clear();
}
SwingUtilities.invokeLater(new UpdateUIThread());
}
//~ Inner Classes ------------------------------------------------------
/**
* DOCUMENT ME!
*
* @version $Revision$, $Date$
*/
private final class UpdateUIThread implements Runnable {
//~ Methods --------------------------------------------------------
@Override
public void run() {
finish();
}
}
}
}