package com.revolsys.swing.map.overlay;
import java.beans.PropertyChangeSupport;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Supplier;
import javax.swing.SwingWorker;
import com.revolsys.beans.PropertyChangeSupportProxy;
import com.revolsys.swing.parallel.Invoke;
import com.revolsys.swing.parallel.SupplierConsumerMaxThreadsSwingWorker;
public class BackgroundRefreshResource<T> implements PropertyChangeSupportProxy {
private T resource;
private final PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
private final Supplier<T> newResourceFactory;
private long refreshIndexLast = Long.MIN_VALUE;
private final AtomicLong refreshIndexNext = new AtomicLong(Long.MIN_VALUE);
private long refreshIndexCurrent = Long.MIN_VALUE;
private SwingWorker<T, Void> worker;
private final String key;
private final String description;
public BackgroundRefreshResource(final String description, final Supplier<T> newResourceFactory) {
this.description = description;
this.key = description;
this.newResourceFactory = newResourceFactory;
}
protected boolean canRefreshFinish(final long refreshIndex) {
if (refreshIndex >= this.refreshIndexLast) {
this.refreshIndexLast = refreshIndex;
return true;
} else {
return false;
}
}
@Override
public PropertyChangeSupport getPropertyChangeSupport() {
return this.propertyChangeSupport;
}
public T getResource() {
return this.resource;
}
public void refresh() {
long refreshIndex;
synchronized (this.refreshIndexNext) {
if (this.worker != null && !this.worker.isDone()
&& this.refreshIndexNext.get() > this.refreshIndexCurrent) {
return;
} else {
refreshIndex = this.refreshIndexNext.incrementAndGet();
}
}
if (this.worker != null) {
this.worker.cancel(true);
}
this.worker = new SupplierConsumerMaxThreadsSwingWorker<>(this.key, 1,
"Refresh: " + this.description, () -> {
return refreshBackground(refreshIndex);
}, (resource) -> {
refreshUi(refreshIndex, resource);
});
Invoke.worker(this.worker);
}
private T refreshBackground(final long refreshIndex) {
synchronized (this.refreshIndexNext) {
if (refreshIndex == this.refreshIndexNext.get()) {
this.refreshIndexCurrent = refreshIndex;
} else {
return null;
}
}
return this.newResourceFactory.get();
}
private void refreshUi(final long refreshIndex, final T resource) {
if (resource != null) {
final T oldValue = this.resource;
boolean changed = false;
synchronized (this.refreshIndexNext) {
if (refreshIndex == this.refreshIndexNext.get()) {
this.worker = null;
}
if (refreshIndex > this.refreshIndexLast) {
this.refreshIndexLast = refreshIndex;
this.resource = resource;
changed = true;
}
}
if (changed) {
this.propertyChangeSupport.firePropertyChange("resource", oldValue, resource);
}
}
}
}