package org.archstudio.bna.logics.information;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
import org.archstudio.bna.IBNAWorld;
import org.archstudio.bna.logics.AbstractThingLogic;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.ui.PlatformUI;
public class ProgressLogic extends AbstractThingLogic {
class ProgressLogicJob extends Job {
IRunnableWithProgress runnable;
public ProgressLogicJob(String name, IRunnableWithProgress runnable) {
super(name);
this.runnable = runnable;
setUser(false);
setSystem(false);
setPriority(Job.SHORT);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
monitor.beginTask(getName(), 1);
runnable.run(monitor);
return Status.OK_STATUS;
}
catch (InvocationTargetException | InterruptedException e) {
e.printStackTrace();
return new Status(IStatus.ERROR, "org.archstudio.bna", "Failed to execute: " + getName(), e);
}
finally {
tasks.decrementAndGet();
synchronized (tasks) {
tasks.notifyAll();
}
}
}
}
static ExecutorService asyncExecutor = Executors.newCachedThreadPool(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setDaemon(true);
t.setName(ProgressLogic.class.getName());
return t;
}
});
private final AtomicInteger tasks = new AtomicInteger();
public ProgressLogic(IBNAWorld world) {
super(world);
}
public void run(final String description, final IRunnableWithProgress runnable) {
tasks.incrementAndGet();
if (Platform.isRunning() && PlatformUI.isWorkbenchRunning()) {
new ProgressLogicJob(description, runnable).schedule();
}
else {
asyncExecutor.execute(new Runnable() {
@Override
public void run() {
try {
runnable.run(null);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
tasks.decrementAndGet();
synchronized (tasks) {
tasks.notifyAll();
}
}
}
});
}
}
public void waitForCompletion() {
if (Platform.isRunning()) {
try {
Job.getJobManager().join(ProgressLogic.class, null);
}
catch (OperationCanceledException | InterruptedException e) {
e.printStackTrace();
}
}
else {
synchronized (tasks) {
while (tasks.get() > 0) {
try {
tasks.wait();
}
catch (InterruptedException e) {
}
}
}
}
}
//TODO: use join to wait for thread completion
}