// License: GPL. For details, see LICENSE file.
package cadastre_fr;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.gui.MapView;
import org.openstreetmap.josm.io.OsmTransferException;
public class GrabThread extends Thread {
private boolean canceled;
private CadastreGrabber grabber;
private WMSLayer wmsLayer;
private Lock lockImagesToGrag = new ReentrantLock();
private ArrayList<EastNorthBound> imagesToGrab = new ArrayList<>();
private CacheControl cacheControl = null;
private EastNorthBound currentGrabImage;
private Lock lockCurrentGrabImage = new ReentrantLock();
/**
* Call directly grabber for raster images or prepare thread for vector images
*/
public void addImages(ArrayList<EastNorthBound> moreImages) {
lockImagesToGrag.lock();
imagesToGrab.addAll(moreImages);
lockImagesToGrag.unlock();
synchronized (this) {
this.notify();
}
Main.info("Added " + moreImages.size() + " to the grab thread");
if (wmsLayer.isRaster()) {
waitNotification();
}
}
public int getImagesToGrabSize() {
lockImagesToGrag.lock();
int size = imagesToGrab.size();
lockImagesToGrag.unlock();
return size;
}
public ArrayList<EastNorthBound> getImagesToGrabCopy() {
ArrayList<EastNorthBound> copyList = new ArrayList<>();
lockImagesToGrag.lock();
for (EastNorthBound img : imagesToGrab) {
EastNorthBound imgCpy = new EastNorthBound(img.min, img.max);
copyList.add(imgCpy);
}
lockImagesToGrag.unlock();
return copyList;
}
public void clearImagesToGrab() {
lockImagesToGrag.lock();
imagesToGrab.clear();
lockImagesToGrag.unlock();
}
@Override
public void run() {
for (;;) {
while (getImagesToGrabSize() > 0) {
lockImagesToGrag.lock();
lockCurrentGrabImage.lock();
currentGrabImage = imagesToGrab.get(0);
lockCurrentGrabImage.unlock();
imagesToGrab.remove(0);
lockImagesToGrag.unlock();
if (canceled) {
break;
} else {
GeorefImage newImage;
try {
Main.map.repaint(); // paint the current grab box
newImage = grabber.grab(wmsLayer, currentGrabImage.min, currentGrabImage.max);
} catch (IOException e) {
Main.warn("Download action canceled by user or server did not respond");
setCanceled(true);
break;
} catch (OsmTransferException e) {
Main.error("OSM transfer failed");
setCanceled(true);
break;
}
if (grabber.getWmsInterface().downloadCanceled) {
Main.info("Download action canceled by user");
setCanceled(true);
break;
}
try {
if (CadastrePlugin.backgroundTransparent) {
wmsLayer.imagesLock.lock();
for (GeorefImage img : wmsLayer.getImages()) {
if (img.overlap(newImage))
// mask overlapping zone in already grabbed image
img.withdraw(newImage);
else
// mask overlapping zone in new image only when new image covers completely the
// existing image
newImage.withdraw(img);
}
wmsLayer.imagesLock.unlock();
}
wmsLayer.addImage(newImage);
Main.map.mapView.repaint();
saveToCache(newImage);
} catch (NullPointerException e) {
Main.info("Layer destroyed. Cancel grab thread");
setCanceled(true);
}
}
}
Main.info("grab thread list empty");
lockCurrentGrabImage.lock();
currentGrabImage = null;
lockCurrentGrabImage.unlock();
if (canceled) {
clearImagesToGrab();
canceled = false;
}
if (wmsLayer.isRaster()) {
notifyWaiter();
}
waitNotification();
}
}
public void saveToCache(GeorefImage image) {
if (CacheControl.cacheEnabled && !wmsLayer.isRaster()) {
getCacheControl().saveCache(image);
}
}
public void saveNewCache() {
if (CacheControl.cacheEnabled) {
getCacheControl().deleteCacheFile();
wmsLayer.imagesLock.lock();
for (GeorefImage image : wmsLayer.getImages()) {
getCacheControl().saveCache(image);
}
wmsLayer.imagesLock.unlock();
}
}
public void cancel() {
clearImagesToGrab();
if (cacheControl != null) {
while (!cacheControl.isCachePipeEmpty()) {
Main.info("Try to close a WMSLayer which is currently saving in cache : wait 1 sec.");
CadastrePlugin.safeSleep(1000);
}
}
}
public CacheControl getCacheControl() {
if (cacheControl == null)
cacheControl = new CacheControl(wmsLayer);
return cacheControl;
}
public GrabThread(WMSLayer wmsLayer) {
this.wmsLayer = wmsLayer;
}
public void paintBoxesToGrab(Graphics g, MapView mv) {
if (getImagesToGrabSize() > 0) {
ArrayList<EastNorthBound> imagesToGrab = getImagesToGrabCopy();
for (EastNorthBound img : imagesToGrab) {
paintBox(g, mv, img, Color.red);
}
}
lockCurrentGrabImage.lock();
if (currentGrabImage != null) {
paintBox(g, mv, currentGrabImage, Color.orange);
}
lockCurrentGrabImage.unlock();
}
private void paintBox(Graphics g, MapView mv, EastNorthBound img, Color color) {
Point[] croppedPoint = new Point[5];
croppedPoint[0] = mv.getPoint(img.min);
croppedPoint[1] = mv.getPoint(new EastNorth(img.min.east(), img.max.north()));
croppedPoint[2] = mv.getPoint(img.max);
croppedPoint[3] = mv.getPoint(new EastNorth(img.max.east(), img.min.north()));
croppedPoint[4] = croppedPoint[0];
for (int i = 0; i < 4; i++) {
g.setColor(color);
g.drawLine(croppedPoint[i].x, croppedPoint[i].y, croppedPoint[i+1].x, croppedPoint[i+1].y);
}
}
public boolean isCanceled() {
return canceled;
}
public void setCanceled(boolean canceled) {
this.canceled = canceled;
}
public CadastreGrabber getGrabber() {
return grabber;
}
public void setGrabber(CadastreGrabber grabber) {
this.grabber = grabber;
}
private synchronized void notifyWaiter() {
this.notify();
}
private synchronized void waitNotification() {
try {
wait();
} catch (InterruptedException e) {
Main.error(e);
}
}
}