I want to extend SwingWorker for a class but I have already extended one other class for that. I wanted to know whether there is some sort of a workaround like in threads (we can extend it or implement it), so that I maybe able to use in doInBackground method of SwingWorker.
I have a list of objects on which I need to perform an operation .The objects are of type A,B,C. I have made a superclass S and A,B,C are the sub classes for that superclass. I have an object of S and at runtime while going through the list I find the type of the item in the list and typecast the S to A,B or C and perform the operation . If I make S a SwingWorker, I can perform the operation only once, since Swing workers can be used only once. I can't make A,B,C extend SwingWorker because they are already extending S. So I need to implement SwingWorker for A,B,C
I also have a Connection object that A,B,C would use and I have made it as a Singleton because I don't want to initialize again and again.
An example composition example follows.
Expected output:
Received partial update list [Worker: start]
Progress: 20%...
Progress: 70%...
Progress: 100%...
Received partial update list [Worker: woken up, Worker: sending the result]
Worker Done
Launcher done.
Code:
package com.stackoverflow;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.List;
import javax.swing.SwingWorker;
public class DelegatingSwingWorkerDemo {
public static void main(String[] args) {
new Launcher().launch();
}
}
/**
* Use this, to launch the worker.
*/
class DelegatingSwingWorker<I, O> extends SwingWorker<I, O> {
SwingWorkerable<I, O> delegate;
Publisher<O> publisher;
public DelegatingSwingWorker(SwingWorkerable<I, O> delegate) {
this.delegate = delegate;
publisher = new Publisher<O>() {
@Override
public void publish(O... chunks) {
DelegatingSwingWorker.this.publish(chunks);
}
@Override
public void setProgress(int progress) {
DelegatingSwingWorker.this.setProgress(progress);
}
};
}
@Override
protected void process(List<O> chunks) {
delegate.process(chunks);
}
@Override
protected void done() {
delegate.done();
}
@Override
protected I doInBackground() throws Exception {
return delegate.doInBackground(publisher);
}
}
interface Publisher<O> {
void publish(O... chunks);
void setProgress(int progress);
}
/**
* Make your class implement the interface.
*/
interface SwingWorkerable<I, O> {
void process(List<O> chunks);
I doInBackground(Publisher<O> publisher);
void done();
}
/**
* Let's say this is your super class:
*/
class MySuperClass {
}
/**
* Use your super class, but implement the SwingWorkerable. Then
* launch using a DelegatingSwingWorker
*/
class SleepingDemoSwingWorkerable
extends MySuperClass
implements SwingWorkerable<String, String> {
@Override
public void process(List<String> chunks) {
System.out.println("Received partial update list " + chunks);
}
@Override
public String doInBackground(Publisher<String> publisher) {
publisher.publish("Worker: start");
try {
publisher.setProgress(0);
Thread.sleep(200);
publisher.setProgress(20);
Thread.sleep(500);
publisher.setProgress(70);
Thread.sleep(300);
publisher.setProgress(100);
publisher.publish("Worker: woken up");
} catch (InterruptedException e) {
e.printStackTrace();
}
publisher.publish("Worker: sending the result");
return "Second passed.";
}
@Override
public void done() {
System.out.println("Worker Done");
}
}
final class ConsoleProgressListener implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent event) {
switch (event.getPropertyName()) {
case "progress":
System.out.println("Progress: " + event.getNewValue() + "%...");
}
}
}
/**
* Launch
*/
class Launcher {
public void launch() {
SleepingDemoSwingWorkerable workerable = new SleepingDemoSwingWorkerable();
DelegatingSwingWorker<String, String> delegatingSwingWorker =
new DelegatingSwingWorker<String, String>(workerable);
delegatingSwingWorker.addPropertyChangeListener(new ConsoleProgressListener());
delegatingSwingWorker.execute();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Launcher done.");
}
}