Index: /applications/viewer/jmapviewer/build.xml
===================================================================
--- /applications/viewer/jmapviewer/build.xml	(revision 36222)
+++ /applications/viewer/jmapviewer/build.xml	(revision 36223)
@@ -8,5 +8,4 @@
     <property name="java.lang.version" value="8" />
     <dirname property="base.dir" file="${ant.file.jmapviewer}"/>
-    <property name="tools.dir" location="${base.dir}/tools"/>
     <property name="jacoco.includes" value="org.openstreetmap.gui.jmapviewer.*" />
     <property name="jacoco.inclbootstrapclasses" value="false" />
@@ -14,18 +13,9 @@
     <!-- For Java specific stuff by version -->
     <condition property="isJava9"><matches string="${ant.java.version}" pattern="(1.)?(9|1[0-9])" /></condition>
-    <condition property="isJava10"><matches string="${ant.java.version}" pattern="(1|2)[0-9]" /></condition>
-    <condition property="isJava11"><matches string="${ant.java.version}" pattern="1[1-9]|[2-9][0-9]" /></condition>
-    <condition property="isJava12"><matches string="${ant.java.version}" pattern="1[2-9]|[2-9][0-9]" /></condition>
-    <condition property="isJava13"><matches string="${ant.java.version}" pattern="1[3-9]|[2-9][0-9]" /></condition>
-    <condition property="isJava14"><matches string="${ant.java.version}" pattern="1[4-9]|[2-9][0-9]" /></condition>
-    <condition property="isJava16"><matches string="${ant.java.version}" pattern="1[6-9]|[2-9][0-9]" /></condition>
-    <condition property="isJava18"><matches string="${ant.java.version}" pattern="1[8-9]|[2-9][0-9]" /></condition>
-    <condition property="isJava19"><matches string="${ant.java.version}" pattern="19|[2-9][0-9]" /></condition>
-    <condition property="isJava20"><matches string="${ant.java.version}" pattern="[2-9][0-9]" /></condition>
-    <condition property="isJava21"><matches string="${ant.java.version}" pattern="2[1-9]|[3-9][0-9]" /></condition>
-    <!-- Disable jacoco on Java 18+, see https://github.com/jacoco/jacoco/pull/1132 -->
+    <condition property="isJava23"><matches string="${ant.java.version}" pattern="2[3-9]|[3-9][0-9]" /></condition>
+    <!-- Disable jacoco 0.8.11 on Java 23+, see https://www.jacoco.org/jacoco/trunk/doc/changes.html for latest supported version -->
     <condition property="coverageByDefault">
         <not>
-            <isset property="isJava18"/>
+            <isset property="isJava23"/>
         </not>
     </condition>
Index: /applications/viewer/jmapviewer/ivy.xml
===================================================================
--- /applications/viewer/jmapviewer/ivy.xml	(revision 36222)
+++ /applications/viewer/jmapviewer/ivy.xml	(revision 36223)
@@ -8,22 +8,22 @@
     </configurations>
     <dependencies>
-        <!-- jacocoant->default -->
-        <dependency conf="jacocoant->default" org="org.jacoco" name="org.jacoco.ant" rev="0.8.10">
+        <!-- jacocoant->default - don't forget to update the Jacoco disable section in build.xml -->
+        <dependency conf="jacocoant->default" org="org.jacoco" name="org.jacoco.ant" rev="0.8.11">
             <artifact name="org.jacoco.ant" type="jar" maven:classifier="nodeps"/>
         </dependency>
         <!-- test->default -->
-        <dependency conf="test->default" org="com.github.spotbugs" name="spotbugs-annotations" rev="4.7.3"/>
-        <dependency conf="test->default" org="org.junit.platform" name="junit-platform-launcher" rev="1.10.0"/>
-        <dependency conf="test->default" org="org.junit.platform" name="junit-platform-suite" rev="1.10.0"/>
-        <dependency conf="test->default" org="org.junit.vintage" name="junit-vintage-engine" rev="5.10.0"/>
-        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-params" rev="5.10.0"/>
-        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-api" rev="5.10.0"/>
-        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-engine" rev="5.10.0"/>
-        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-migrationsupport" rev="5.10.0"/>
+        <dependency conf="test->default" org="com.github.spotbugs" name="spotbugs-annotations" rev="4.8.3"/>
+        <dependency conf="test->default" org="org.junit.platform" name="junit-platform-launcher" rev="1.10.2"/>
+        <dependency conf="test->default" org="org.junit.platform" name="junit-platform-suite" rev="1.10.2"/>
+        <dependency conf="test->default" org="org.junit.vintage" name="junit-vintage-engine" rev="5.10.2"/>
+        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-params" rev="5.10.2"/>
+        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-api" rev="5.10.2"/>
+        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-engine" rev="5.10.2"/>
+        <dependency conf="test->default" org="org.junit.jupiter" name="junit-jupiter-migrationsupport" rev="5.10.2"/>
         <!-- checkstyle->default -->
         <dependency org="com.puppycrawl.tools" name="checkstyle" rev="9.3" conf="checkstyle->default"/>
         <!-- spotbugs->default -->
-        <dependency org="com.github.spotbugs" name="spotbugs" rev="4.7.3" conf="spotbugs->default"/>
-        <dependency org="com.github.spotbugs" name="spotbugs-ant" rev="4.7.3" conf="spotbugs->default"/>
+        <dependency org="com.github.spotbugs" name="spotbugs" rev="4.8.3" conf="spotbugs->default"/>
+        <dependency org="com.github.spotbugs" name="spotbugs-ant" rev="4.8.3" conf="spotbugs->default"/>
     </dependencies>
 </ivy-module>
Index: /applications/viewer/jmapviewer/pom.xml
===================================================================
--- /applications/viewer/jmapviewer/pom.xml	(revision 36222)
+++ /applications/viewer/jmapviewer/pom.xml	(revision 36223)
@@ -84,5 +84,5 @@
                 <groupId>org.junit</groupId>
                 <artifactId>junit-bom</artifactId>
-                <version>5.10.1</version>
+                <version>5.10.2</version>
                 <type>pom</type>
                 <scope>import</scope>
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/AttributionSupport.java	(revision 36223)
@@ -19,4 +19,6 @@
 
 public class AttributionSupport {
+    public static final Font ATTR_FONT = new Font("Arial", Font.PLAIN, 10);
+    public static final Font ATTR_LINK_FONT;
 
     private Attributed source;
@@ -25,6 +27,4 @@
     private String attrTermsText;
     private String attrTermsUrl;
-    public static final Font ATTR_FONT = new Font("Arial", Font.PLAIN, 10);
-    public static final Font ATTR_LINK_FONT;
 
     protected Rectangle attrTextBounds;
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Coordinate.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Coordinate.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Coordinate.java	(revision 36223)
@@ -74,5 +74,5 @@
     public boolean equals(Object o) {
         if (this == o) return true;
-        if (!(o instanceof Coordinate)) return false;
+        if (o == null || !this.getClass().equals(o.getClass())) return false;
         Coordinate that = (Coordinate) o;
         return Double.compare(that.x, x) == 0 && Double.compare(that.y, y) == 0;
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/DefaultMapController.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/DefaultMapController.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/DefaultMapController.java	(revision 36223)
@@ -137,5 +137,5 @@
                 break;
             default:
-                throw new RuntimeException("Unsupported button");
+                throw new JMapViewerRuntimeException("Unsupported button");
         }
     }
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Demo.java	(revision 36223)
@@ -5,6 +5,4 @@
 import java.awt.Cursor;
 import java.awt.Point;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
@@ -84,18 +82,8 @@
                 new BingAerialTileSource(),
         });
-        tileSourceSelector.addItemListener(new ItemListener() {
-            @Override
-            public void itemStateChanged(ItemEvent e) {
-                map().setTileSource((TileSource) e.getItem());
-            }
-        });
+        tileSourceSelector.addItemListener(e -> map().setTileSource((TileSource) e.getItem()));
         JComboBox<TileLoader> tileLoaderSelector;
         tileLoaderSelector = new JComboBox<>(new TileLoader[] {new OsmTileLoader(map())});
-        tileLoaderSelector.addItemListener(new ItemListener() {
-            @Override
-            public void itemStateChanged(ItemEvent e) {
-                map().setTileLoader((TileLoader) e.getItem());
-            }
-        });
+        tileLoaderSelector.addItemListener(e -> map().setTileLoader((TileLoader) e.getItem()));
         map().setTileLoader((TileLoader) tileLoaderSelector.getSelectedItem());
         panelTop.add(tileSourceSelector);
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/FeatureAdapter.java	(revision 36223)
@@ -299,8 +299,6 @@
                 try {
                     Desktop.getDesktop().browse(new URI(url));
-                } catch (IOException e) {
-                    e.printStackTrace();
-                } catch (URISyntaxException e) {
-                    e.printStackTrace();
+                } catch (IOException | URISyntaxException e) {
+                    getLogger(FeatureAdapter.class).log(Level.SEVERE, e.getMessage(), e);
                 }
             } else {
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewer.java	(revision 36223)
@@ -13,4 +13,5 @@
 import java.util.Collections;
 import java.util.List;
+import java.util.logging.Level;
 
 import javax.swing.ImageIcon;
@@ -137,7 +138,7 @@
         tileSource = new OsmTileSource.Mapnik();
         tileController = new TileController(tileSource, tileCache, this);
-        mapMarkerList = Collections.synchronizedList(new ArrayList<MapMarker>());
-        mapPolygonList = Collections.synchronizedList(new ArrayList<MapPolygon>());
-        mapRectangleList = Collections.synchronizedList(new ArrayList<MapRectangle>());
+        mapMarkerList = Collections.synchronizedList(new ArrayList<>());
+        mapPolygonList = Collections.synchronizedList(new ArrayList<>());
+        mapRectangleList = Collections.synchronizedList(new ArrayList<>());
         mapMarkersVisible = true;
         mapRectanglesVisible = true;
@@ -197,5 +198,5 @@
                 return new ImageIcon(FeatureAdapter.readImage(url));
             } catch (IOException e) {
-                e.printStackTrace();
+                FeatureAdapter.getLogger(JMapViewer.class).log(Level.FINE, e.getMessage(), e);
             }
         }
@@ -502,5 +503,5 @@
         else if (p != null) {
             Integer radius = getLatOffset(marker.getLat(), marker.getLon(), marker.getRadius(), false);
-            radius = radius == null ? null : p.y - radius;
+            radius = radius == null ? null : (p.y - radius);
             return radius;
         } else
@@ -543,10 +544,10 @@
     public double getMeterPerPixel() {
         Point origin = new Point(5, 5);
-        Point center = new Point(getWidth() / 2, getHeight() / 2);
-
-        double pDistance = center.distance(origin);
+        Point centerPixel = new Point(getWidth() / 2, getHeight() / 2);
+
+        double pDistance = centerPixel.distance(origin);
 
         ICoordinate originCoord = getPosition(origin);
-        ICoordinate centerCoord = getPosition(center);
+        ICoordinate centerCoord = getPosition(centerPixel);
 
         double mDistance = tileSource.getDistance(originCoord.getLat(), originCoord.getLon(),
@@ -560,5 +561,5 @@
         super.paintComponent(g);
 
-        int iMove = 0;
+        int iMove;
 
         int tilesize = tileSource.getTileSize();
@@ -1101,7 +1102,7 @@
     public void setTileSource(TileSource tileSource) {
         if (tileSource.getMaxZoom() > MAX_ZOOM)
-            throw new RuntimeException("Maximum zoom level too high");
+            throw new JMapViewerRuntimeException("Maximum zoom level too high");
         if (tileSource.getMinZoom() < MIN_ZOOM)
-            throw new RuntimeException("Minimum zoom level too low");
+            throw new JMapViewerRuntimeException("Minimum zoom level too low");
         ICoordinate position = getPosition();
         this.tileSource = tileSource;
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewerRuntimeException.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewerRuntimeException.java	(revision 36223)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/JMapViewerRuntimeException.java	(revision 36223)
@@ -0,0 +1,46 @@
+// License: GPL. For details, see Readme.txt file.
+package org.openstreetmap.gui.jmapviewer;
+
+/**
+ * A {@link RuntimeException} specific to JMapViewer
+ * @since JMapViewer 2.20
+ */
+public class JMapViewerRuntimeException extends RuntimeException {
+
+    /**
+     * Create a new exception without a specified cause or message
+     * @see Exception#Exception()
+     */
+    public JMapViewerRuntimeException() {
+        super();
+    }
+
+    /**
+     * Create a new exception with a message
+     * @param message The message for the exception
+     * @see Exception#Exception(String)
+     */
+    public JMapViewerRuntimeException(String message) {
+        super(message);
+    }
+
+    /**
+     * Create a new message with a given message and cause
+     * @param message The message for the exception
+     * @param cause The cause of the exception
+     * @see Exception#Exception(String, Throwable)
+     */
+    public JMapViewerRuntimeException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    /**
+     * Constructs a new exception with the specified cause
+     *
+     * @param cause the cause of the exception
+     * @see Exception#Exception(Throwable)
+     */
+    public JMapViewerRuntimeException(Throwable cause) {
+        super(cause);
+    }
+}
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/MemoryTileCache.java	(revision 36223)
@@ -4,4 +4,5 @@
 import java.util.HashMap;
 import java.util.Map;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -18,5 +19,10 @@
 public class MemoryTileCache implements TileCache {
 
-    protected static final Logger log = Logger.getLogger(MemoryTileCache.class.getName());
+    private static final Logger LOGGER = Logger.getLogger(MemoryTileCache.class.getName());
+    /**
+     * @deprecated since 2.20 (create a class specific logger)
+     */
+    @Deprecated
+    protected static final Logger log = LOGGER;
 
     /**
@@ -79,5 +85,5 @@
             }
         } catch (NullPointerException e) {
-            log.warning(e.getMessage());
+            LOGGER.log(Level.WARNING, e.getMessage(), e);
         }
     }
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmMercator.java	(revision 36223)
@@ -58,5 +58,5 @@
      */
     public long getMaxPixels(int aZoomlevel) {
-        return tileSize * (1 << aZoomlevel);
+        return tileSize * (1L << aZoomlevel);
     }
 
@@ -162,5 +162,5 @@
         long mp = getMaxPixels(aZoomlevel);
         double y = mp * (0.5 - (log / (4.0 * Math.PI)));
-        return Math.min(y, mp - 1);
+        return Math.min(y, mp - 1d);
     }
 
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/OsmTileLoader.java	(revision 36223)
@@ -177,5 +177,5 @@
                 // ignore malformed Cache-Control headers
                 if (JMapViewer.debug) {
-                    System.err.println(e.getMessage());
+                    LOG.log(Level.FINE, e.getMessage(), e);
                 }
             }
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Projected.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Projected.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Projected.java	(revision 36223)
@@ -62,5 +62,5 @@
         if (this == obj)
             return true;
-        if (!(obj instanceof Projected))
+        if (obj == null || !this.getClass().equals(obj.getClass()))
             return false;
         final Projected other = (Projected) obj;
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Style.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Style.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Style.java	(revision 36223)
@@ -8,11 +8,11 @@
 
 public class Style {
+    private static final AlphaComposite TRANSPARENCY = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
+    private static final AlphaComposite OPAQUE = AlphaComposite.getInstance(AlphaComposite.SRC);
+
     private Color color;
     private Color backColor;
     private Stroke stroke;
     private Font font;
-
-    private static final AlphaComposite TRANSPARENCY = AlphaComposite.getInstance(AlphaComposite.SRC_OVER);
-    private static final AlphaComposite OPAQUE = AlphaComposite.getInstance(AlphaComposite.SRC);
 
     public Style() {
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Tile.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Tile.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/Tile.java	(revision 36223)
@@ -12,4 +12,5 @@
 import java.util.Objects;
 import java.util.concurrent.Callable;
+import java.util.logging.Level;
 
 import javax.imageio.ImageIO;
@@ -84,5 +85,5 @@
             return FeatureAdapter.readImage(JMapViewer.class.getResource(path));
         } catch (IOException | IllegalArgumentException ex) {
-            ex.printStackTrace();
+            FeatureAdapter.getLogger(Tile.class).log(Level.SEVERE, ex.getMessage(), ex);
             return null;
         }
@@ -110,5 +111,5 @@
             } catch (Exception e) {
                 // this should not happen here
-                throw new RuntimeException(e);
+                throw new JMapViewerRuntimeException(e);
             }
         }
@@ -125,10 +126,6 @@
          *  this way we can avoid object creation until we're sure it's needed
          */
-        final CachedCallable<BufferedImage> tmpImage = new CachedCallable<>(new Callable<BufferedImage>() {
-            @Override
-            public BufferedImage call() throws Exception {
-                return new BufferedImage(source.getTileSize(), source.getTileSize(), BufferedImage.TYPE_INT_ARGB);
-            }
-        });
+        final CachedCallable<BufferedImage> tmpImage = new CachedCallable<>(() ->
+                new BufferedImage(source.getTileSize(), source.getTileSize(), BufferedImage.TYPE_INT_ARGB));
 
         for (int zoomDiff = 1; zoomDiff < 5; zoomDiff++) {
@@ -146,11 +143,8 @@
                  * something to draw
                  */
-                CachedCallable<Graphics2D> graphics = new CachedCallable<>(new Callable<Graphics2D>() {
-                    @Override
-                    public Graphics2D call() throws Exception {
-                        Graphics2D g = (Graphics2D) tmpImage.call().getGraphics();
-                        g.setTransform(AffineTransform.getScaleInstance(scale, scale));
-                        return g;
-                    }
+                CachedCallable<Graphics2D> graphics = new CachedCallable<>(() -> {
+                    Graphics2D g = (Graphics2D) tmpImage.call().getGraphics();
+                    g.setTransform(AffineTransform.getScaleInstance(scale, scale));
+                    return g;
                 });
 
@@ -177,16 +171,12 @@
                 final int factor = 1 << zoomDiff;
                 final double scale = factor;
-                CachedCallable<Graphics2D> graphics = new CachedCallable<>(new Callable<Graphics2D>() {
-                    @Override
-                    public Graphics2D call() throws Exception {
-                        Graphics2D g = (Graphics2D) tmpImage.call().getGraphics();
-                        AffineTransform at = new AffineTransform();
-                        int translateX = (xtile % factor) * source.getTileSize();
-                        int translateY = (ytile % factor) * source.getTileSize();
-                        at.setTransform(scale, 0, 0, scale, -translateX, -translateY);
-                        g.setTransform(at);
-                        return g;
-                    }
-
+                CachedCallable<Graphics2D> graphics = new CachedCallable<>(() -> {
+                    Graphics2D g = (Graphics2D) tmpImage.call().getGraphics();
+                    AffineTransform at = new AffineTransform();
+                    int translateX = (xtile % factor) * source.getTileSize();
+                    int translateY = (ytile % factor) * source.getTileSize();
+                    at.setTransform(scale, 0, 0, scale, -translateX, -translateY);
+                    g.setTransform(at);
+                    return g;
                 });
 
@@ -341,5 +331,5 @@
         if (this == obj)
             return true;
-        if (obj == null || !(obj instanceof Tile))
+        if (obj == null || !this.getClass().equals(obj.getClass()))
             return false;
         final Tile other = (Tile) obj;
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeEditor.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeEditor.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodeEditor.java	(revision 36223)
@@ -3,5 +3,4 @@
 
 import java.awt.Component;
-import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
 import java.awt.event.MouseAdapter;
@@ -85,11 +84,7 @@
 
         // editor always selected / focused
-        final ItemListener itemListener = new ItemListener() {
-
-            @Override
-            public void itemStateChanged(final ItemEvent itemEvent) {
-                if (stopCellEditing()) {
-                    fireEditingStopped();
-                }
+        final ItemListener itemListener = itemEvent -> {
+            if (stopCellEditing()) {
+                fireEditingStopped();
             }
         };
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodePanel.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodePanel.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/checkBoxTree/CheckBoxNodePanel.java	(revision 36223)
@@ -33,5 +33,5 @@
             check.getModel().setArmed(true);
         } else {
-            check.setSelected(bool.booleanValue());
+            check.setSelected(bool);
             check.getModel().setArmed(false);
         }
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/events/JMVCommandEvent.java	(revision 36223)
@@ -17,9 +17,10 @@
     }
 
-    private COMMAND command;
     /**
      *
      */
     private static final long serialVersionUID = 8701544867914969620L;
+
+    private COMMAND command;
 
     public JMVCommandEvent(COMMAND cmd, Object source) {
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/IProjected.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/IProjected.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/interfaces/IProjected.java	(revision 36223)
@@ -4,5 +4,5 @@
 /**
  * Projected coordinates (east / north space).
- *
+ * <p>
  * For most projections, one unit in projected space is roughly one meter, but
  * can also be degrees or feet.
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/AbstractTMSTileSource.java	(revision 36223)
@@ -179,7 +179,7 @@
                 for (final int v : byteDigest) {
                     int vn = (v & 0xf0) >> 4;
-                    hexChars[j++] = (char) (vn + (vn >= 10 ? 'a' - 10 : '0'));
+                    hexChars[j++] = (char) (vn + (vn >= 10 ? ('a' - 10) : '0'));
                     vn = (v & 0xf);
-                    hexChars[j++] = (char) (vn + (vn >= 10 ? 'a' - 10 : '0'));
+                    hexChars[j++] = (char) (vn + (vn >= 10 ? ('a' - 10) : '0'));
                 }
                 for (String val: searchEntry.getValue()) {
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/BingAerialTileSource.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/BingAerialTileSource.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/BingAerialTileSource.java	(revision 36223)
@@ -32,4 +32,5 @@
 import org.openstreetmap.gui.jmapviewer.FeatureAdapter;
 import org.openstreetmap.gui.jmapviewer.JMapViewer;
+import org.openstreetmap.gui.jmapviewer.JMapViewerRuntimeException;
 import org.openstreetmap.gui.jmapviewer.interfaces.ICoordinate;
 import org.w3c.dom.Document;
@@ -62,13 +63,13 @@
     /** Original Bing API key created by Potlatch2 developers in 2010 */
     private static final String API_KEY = "Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU";
-    
+
+    private static final Pattern PATTERN_SUBDOMAIN = Pattern.compile("\\{subdomain}");
+    private static final Pattern PATTERN_QUADKEY = Pattern.compile("\\{quadkey}");
+    private static final Pattern PATTERN_CULTURE = Pattern.compile("\\{culture}");
+
     private volatile Future<List<Attribution>> attributions; // volatile is required for getAttribution(), see below.
     private String imageUrlTemplate;
     private int imageryZoomMax = Integer.MIN_VALUE;
     private String[] subdomains;
-
-    private static final Pattern subdomainPattern = Pattern.compile("\\{subdomain}");
-    private static final Pattern quadkeyPattern = Pattern.compile("\\{quadkey}");
-    private static final Pattern culturePattern = Pattern.compile("\\{culture}");
     private String brandLogoUri;
     private String layer = "Aerial";
@@ -108,6 +109,6 @@
 
         String url = imageUrlTemplate;
-        url = subdomainPattern.matcher(url).replaceAll(subdomain);
-        url = quadkeyPattern.matcher(url).replaceAll(computeQuadTree(zoom, tilex, tiley));
+        url = PATTERN_SUBDOMAIN.matcher(url).replaceAll(subdomain);
+        url = PATTERN_QUADKEY.matcher(url).replaceAll(computeQuadTree(zoom, tilex, tiley));
 
         return url;
@@ -289,5 +290,5 @@
             return attributions.get();
         } catch (ExecutionException ex) {
-            throw new RuntimeException(ex);
+            throw new JMapViewerRuntimeException(ex);
         } catch (InterruptedException ign) {
             LOG.log(Level.SEVERE, "InterruptedException: {0}", ign.getMessage());
@@ -319,5 +320,5 @@
         String noHttpTemplate = template.replace("http://ecn.{subdomain}.tiles.virtualearth.net/",
                 "https://ecn.{subdomain}.tiles.virtualearth.net/");
-        this.imageUrlTemplate = culturePattern.matcher(noHttpTemplate).replaceAll(Locale.getDefault().toString());
+        this.imageUrlTemplate = PATTERN_CULTURE.matcher(noHttpTemplate).replaceAll(Locale.getDefault().toString());
     }
 
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/OsmTileSource.java	(revision 36223)
@@ -32,5 +32,5 @@
         @Override
         public String getBaseUrl() {
-            String url = String.format(this.baseUrl, new Object[] {SERVER[serverNum]});
+            String url = String.format(this.baseUrl, SERVER[serverNum]);
             serverNum = (serverNum + 1) % SERVER.length;
             return url;
@@ -58,5 +58,5 @@
         @Override
         public String getBaseUrl() {
-            String url = String.format(this.baseUrl, new Object[] {SERVER[serverNum]});
+            String url = String.format(this.baseUrl, SERVER[serverNum]);
             serverNum = (serverNum + 1) % SERVER.length;
             return url;
@@ -65,6 +65,6 @@
         /**
          * Get the thunderforest API key.
-         *
-         * Needs to be registered at their web site.
+         * <p>
+         * Needs to be registered at their website.
          * @return the API key
          */
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/ScanexTileSource.java	(revision 36223)
@@ -14,8 +14,8 @@
 /**
  * This tilesource uses different to OsmMercator projection.
- *
+ * <p>
  * Earth is assumed an ellipsoid in this projection, unlike
  * sphere in OsmMercator, so latitude calculation differs a lot.
- *
+ * <p>
  * The longitude calculation is the same as in OsmMercator,
  * we inherit it from AbstractTMSTileSource.
@@ -24,7 +24,12 @@
  */
 public class ScanexTileSource extends TMSTileSource {
-    private static final String DEFAULT_URL = "http://maps.kosmosnimki.ru";
+    private static final String DEFAULT_URL = "https://maps.kosmosnimki.ru";
     private static final int DEFAULT_MAXZOOM = 14;
     private static final String API_KEY = "4018C5A9AECAD8868ED5DEB2E41D09F7";
+
+    // Latitude to Y and back calculations.
+    private static final double RADIUS_E = 6_378_137;   /* radius of Earth at equator, m */
+    private static final double EQUATOR = 40075016.68557849; /* equator length, m */
+    private static final double E = 0.0818191908426;  /* eccentricity of Earth's ellipsoid */
 
     private enum ScanexLayer {
@@ -50,5 +55,5 @@
     /** IRS by default */
     private ScanexLayer layer = ScanexLayer.IRS;
-    private TemplatedTMSTileSource TemplateSource = null;
+    private TemplatedTMSTileSource templateSource;
 
     /** cached latitude used in {@link #tileYToLat(double, int)} */
@@ -63,8 +68,8 @@
         String url = info.getUrl();
 
-        /**
+        /*
          * The formulae in tileYToLat() and latToTileY() have 2^8
          * hardcoded in them, so explicitly state that.  For now
-         * the assignment matches OsmMercator.DEFAUL_TILE_SIZE, and
+         * the assignment matches OsmMercator.DEFAULT_TILE_SIZE, and
          * thus is extraneous.  But let it be there just in case if
          * OsmMercator changes.
@@ -82,7 +87,7 @@
             }
         }
-        /** If not "irs" or "spot" keyword, then a custom URL. */
+        /* If not "irs" or "spot" keyword, then a custom URL. */
         TemplatedTMSTileSource.checkUrl(info.getUrl());
-        this.TemplateSource = new TemplatedTMSTileSource(info);
+        this.templateSource = new TemplatedTMSTileSource(info);
     }
 
@@ -94,6 +99,6 @@
    @Override
     public String getTileUrl(int zoom, int tilex, int tiley) {
-        if (this.TemplateSource != null)
-            return this.TemplateSource.getTileUrl(zoom, tilex, tiley);
+        if (this.templateSource != null)
+            return this.templateSource.getTileUrl(zoom, tilex, tiley);
         else
             return this.getBaseUrl() + getTilePath(zoom, tilex, tiley);
@@ -102,5 +107,5 @@
     @Override
     public String getTilePath(int zoom, int tilex, int tiley) {
-        int tmp = (int) Math.pow(2.0, zoom - 1);
+        int tmp = (int) Math.pow(2.0, zoom - 1d);
 
         tilex = tilex - tmp;
@@ -109,9 +114,4 @@
         return this.layer.getUri() + "&apikey=" + API_KEY + "&x=" + tilex + "&y=" + tiley + "&z=" + zoom;
     }
-
-    // Latitude to Y and back calculations.
-    private static final double RADIUS_E = 6378137;   /* radius of Earth at equator, m */
-    private static final double EQUATOR = 40075016.68557849; /* equator length, m */
-    private static final double E = 0.0818191908426;  /* eccentricity of Earth's ellipsoid */
 
     @Override
@@ -143,9 +143,9 @@
         return new Coordinate(
                 tileYToLat(y, zoom),
-                osmMercator.xToLon(x * getTileSize(), zoom)
+                osmMercator.xToLon((long) x * getTileSize(), zoom)
                 );
     }
 
-    private double latToTileY(double lat, int zoom) {
+    private static double latToTileY(double lat, int zoom) {
         double tmp = Math.tan(Math.PI/4 * (1 + lat/90));
         double pow = Math.pow(Math.tan(Math.PI/4 + Math.asin(E * Math.sin(Math.toRadians(lat)))/2), E);
@@ -183,5 +183,5 @@
         double cosl = Math.cos(lat);
 
-        zoom = (int) Math.pow(2.0, zoom - 1);
+        zoom = (int) Math.pow(2.0, zoom - 1d);
         double ec = Math.exp((1 - y/zoom)*Math.PI);
 
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/TMSTileSource.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/TMSTileSource.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/TMSTileSource.java	(revision 36223)
@@ -75,6 +75,6 @@
     public ICoordinate tileXYToLatLon(int x, int y, int zoom) {
         return new Coordinate(
-                osmMercator.yToLat(y * getTileSize(), zoom),
-                osmMercator.xToLon(x * getTileSize(), zoom)
+                osmMercator.yToLat((long) y * getTileSize(), zoom),
+                osmMercator.xToLon((long) x * getTileSize(), zoom)
                 );
     }
Index: /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSource.java
===================================================================
--- /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSource.java	(revision 36222)
+++ /applications/viewer/jmapviewer/src/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSource.java	(revision 36223)
@@ -17,46 +17,48 @@
  * Handles templated TMS Tile Source. Templated means, that some patterns within
  * URL gets substituted.
- *
+ * <p>
  * Supported parameters
- * {zoom} - substituted with zoom level
- * {z} - as above
- * {NUMBER-zoom} - substituted with result of equation "NUMBER - zoom",
- *                  eg. {20-zoom} for zoom level 15 will result in 5 in this place
- * {zoom+number} - substituted with result of equation "zoom + number",
- *                 eg. {zoom+5} for zoom level 15 will result in 20.
- * {x} - substituted with X tile number
- * {y} - substituted with Y tile number
- * {!y} - substituted with Yahoo Y tile number
- * {-y} - substituted with reversed Y tile number
- * {apikey} - substituted with API key retrieved for the imagery id
- * {switch:VAL_A,VAL_B,VAL_C,...} - substituted with one of VAL_A, VAL_B, VAL_C. Usually
- *                                  used to specify many tile servers
- * {header:(HEADER_NAME,HEADER_VALUE)} - sets the headers to be sent to tile server
+ * <ul>
+ * <li>{zoom} - substituted with zoom level</li>
+ * <li>{z} - as above</li>
+ * <li>{NUMBER-zoom} - substituted with result of equation "NUMBER - zoom",
+ *                  eg. {20-zoom} for zoom level 15 will result in 5 in this place</li>
+ * <li>{zoom+number} - substituted with result of equation "zoom + number",
+ *                 eg. {zoom+5} for zoom level 15 will result in 20.</li>
+ * <li>{x} - substituted with X tile number</li>
+ * <li>{y} - substituted with Y tile number</li>
+ * <li>{!y} - substituted with Yahoo Y tile number</li>
+ * <li>{-y} - substituted with reversed Y tile number</li>
+ * <li>{apikey} - substituted with API key retrieved for the imagery id</li>
+ * <li>{switch:VAL_A,VAL_B,VAL_C,...} - substituted with one of VAL_A, VAL_B, VAL_C. Usually
+ *                                  used to specify many tile servers</li>
+ * <li>{header:(HEADER_NAME,HEADER_VALUE)} - sets the headers to be sent to tile server</li>
+ * </ul>
  */
 public class TemplatedTMSTileSource extends TMSTileSource implements TemplatedTileSource {
+
+    // CHECKSTYLE.OFF: SingleSpaceSeparator
+    private static final String COOKIE_HEADER   = "Cookie";
+    private static final Pattern PATTERN_ZOOM    = Pattern.compile("\\{(?:(\\d+)-)?z(?:oom)?([+-]\\d+)?}");
+    private static final Pattern PATTERN_X       = Pattern.compile("\\{x}");
+    private static final Pattern PATTERN_Y       = Pattern.compile("\\{y}");
+    private static final Pattern PATTERN_Y_YAHOO = Pattern.compile("\\{!y}");
+    private static final Pattern PATTERN_NEG_Y   = Pattern.compile("\\{-y}");
+    private static final Pattern PATTERN_SWITCH  = Pattern.compile("\\{switch:([^}]+)}");
+    private static final Pattern PATTERN_HEADER  = Pattern.compile("\\{header\\(([^,]+),([^}]+)\\)}");
+    private static final Pattern PATTERN_API_KEY = Pattern.compile("\\{apikey}");
+    private static final Pattern PATTERN_PARAM  = Pattern.compile("\\{((?:\\d+-)?z(?:oom)?(:?[+-]\\d+)?|x|y|!y|-y|switch:([^}]+))}");
+
+    // CHECKSTYLE.ON: SingleSpaceSeparator
+
+    private static final Pattern[] ALL_PATTERNS = {
+            PATTERN_HEADER, PATTERN_ZOOM, PATTERN_X, PATTERN_Y, PATTERN_Y_YAHOO, PATTERN_NEG_Y, PATTERN_SWITCH, PATTERN_API_KEY
+    };
 
     private Random rand;
     private String[] randomParts;
     private final Map<String, String> headers = new HashMap<>();
-    private boolean inverse_zoom = false;
-    private int zoom_offset = 0;
-
-    // CHECKSTYLE.OFF: SingleSpaceSeparator
-    private static final String COOKIE_HEADER   = "Cookie";
-    private static final Pattern PATTERN_ZOOM    = Pattern.compile("\\{(?:(\\d+)-)?z(?:oom)?([+-]\\d+)?\\}");
-    private static final Pattern PATTERN_X       = Pattern.compile("\\{x\\}");
-    private static final Pattern PATTERN_Y       = Pattern.compile("\\{y\\}");
-    private static final Pattern PATTERN_Y_YAHOO = Pattern.compile("\\{!y\\}");
-    private static final Pattern PATTERN_NEG_Y   = Pattern.compile("\\{-y\\}");
-    private static final Pattern PATTERN_SWITCH  = Pattern.compile("\\{switch:([^}]+)\\}");
-    private static final Pattern PATTERN_HEADER  = Pattern.compile("\\{header\\(([^,]+),([^}]+)\\)\\}");
-    private static final Pattern PATTERN_API_KEY = Pattern.compile("\\{apikey\\}");
-    private static final Pattern PATTERN_PARAM  = Pattern.compile("\\{((?:\\d+-)?z(?:oom)?(:?[+-]\\d+)?|x|y|!y|-y|switch:([^}]+))\\}");
-
-    // CHECKSTYLE.ON: SingleSpaceSeparator
-
-    private static final Pattern[] ALL_PATTERNS = {
-        PATTERN_HEADER, PATTERN_ZOOM, PATTERN_X, PATTERN_Y, PATTERN_Y_YAHOO, PATTERN_NEG_Y, PATTERN_SWITCH, PATTERN_API_KEY
-    };
+    private boolean inverse_zoom;
+    private int zoom_offset;
 
     /**
@@ -137,5 +139,5 @@
             case "z": // PATTERN_ZOOM
             case "zoom":
-                replacement = Integer.toString((inverse_zoom ? -1 * zoom : zoom) + zoom_offset);
+                replacement = Integer.toString((inverse_zoom ? -zoom : zoom) + zoom_offset);
                 break;
             case "x": // PATTERN_X
@@ -146,5 +148,5 @@
                 break;
             case "!y": // PATTERN_Y_YAHOO
-                replacement = Integer.toString((int) Math.pow(2, zoom-1)-1-tiley);
+                replacement = Integer.toString((int) Math.pow(2, zoom - 1d) - 1 - tiley);
                 break;
             case "-y": // PATTERN_NEG_Y
@@ -157,5 +159,5 @@
                 // handle switch/zoom here, as group will contain parameters and switch will not work
                 if (PATTERN_ZOOM.matcher("{" + matcher.group(1) + "}").matches()) {
-                    replacement = Integer.toString((inverse_zoom ? -1 * zoom : zoom) + zoom_offset);
+                    replacement = Integer.toString((inverse_zoom ? -zoom : zoom) + zoom_offset);
                 } else if (PATTERN_SWITCH.matcher("{" + matcher.group(1) + "}").matches()) {
                     replacement = getRandomPart(randomParts);
@@ -180,5 +182,5 @@
     public static void checkUrl(String url) {
         assert url != null && !"".equals(url) : "URL cannot be null or empty";
-        Matcher m = Pattern.compile("\\{[^}]*\\}").matcher(url);
+        Matcher m = Pattern.compile("\\{[^}]*}").matcher(url);
         while (m.find()) {
             boolean isSupportedPattern = Arrays.stream(ALL_PATTERNS).anyMatch(pattern -> pattern.matcher(m.group()).matches());
Index: /applications/viewer/jmapviewer/test/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSourceTest.java
===================================================================
--- /applications/viewer/jmapviewer/test/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSourceTest.java	(revision 36222)
+++ /applications/viewer/jmapviewer/test/org/openstreetmap/gui/jmapviewer/tilesources/TemplatedTMSTileSourceTest.java	(revision 36223)
@@ -8,4 +8,5 @@
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.function.Predicate;
 import java.util.stream.Stream;
@@ -14,10 +15,9 @@
 
 /**
- * Tests for TemplaedTMSTileSource
+ * Tests for TemplatedTMSTileSource
  */
 public class TemplatedTMSTileSourceTest {
 
-    private static final Collection<String> TMS_IMAGERIES = Arrays.asList(new String[]{
-            "http://imagico.de/map/osmim_tiles.php?layer=S2A_R136_N41_20150831T093006&z={zoom}&x={x}&y={-y}",
+    private static final Collection<String> TMS_IMAGERIES = Collections.singleton("http://imagico.de/map/osmim_tiles.php?layer=S2A_R136_N41_20150831T093006&z={zoom}&x={x}&y={-y}"
             /*
              *  generate for example with:
@@ -25,6 +25,5 @@
              *    xmlstarlet sel -N 'josm=http://josm.openstreetmap.de/maps-1.0' -t -v "//josm:entry[josm:type='tms']/josm:url" -n  | \
              *    sed -e 's/\&amp;/\&/g' -e 's/^/"/' -e 's/$/",/'
-             */
-    });
+             */);
 
     /**
