001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.projection.datum;
003
004import java.io.IOException;
005import java.io.InputStream;
006import java.util.Collections;
007import java.util.Map;
008import java.util.TreeMap;
009
010/**
011 * Wrapper for {@link NTV2GridShiftFile}.
012 *
013 * Loads the shift file from disk, when it is first accessed.
014 * @since 5226
015 */
016public class NTV2GridShiftFileWrapper {
017
018    private NTV2GridShiftFile instance;
019    private final String gridFileName;
020
021    /** Priority for local NTV2 grid files */
022    public static final float NTV2_SOURCE_PRIORITY_LOCAL = 10f;
023    /** Priority for downloaded NTV2 grid files */
024    public static final float NTV2_SOURCE_PRIORITY_DOWNLOAD = 5f;
025
026    private static Map<Float, NTV2GridShiftFileSource> sources = new TreeMap<>(Collections.reverseOrder());
027
028    /**
029     * Register a source for NTV2 grid files.
030     * @param priority the priority, sources with higher priority are checked first;
031     * use {@link #NTV2_SOURCE_PRIORITY_LOCAL} for local files and
032     * {@link #NTV2_SOURCE_PRIORITY_DOWNLOAD} for remote downloads
033     * @param source the NTV2 grid file source
034     * @since 12777
035     */
036    public static void registerNTV2GridShiftFileSource(float priority, NTV2GridShiftFileSource source) {
037        sources.put(priority, source);
038    }
039
040    /**
041     * Constructs a new {@code NTV2GridShiftFileWrapper}.
042     * @param filename Path to the grid file (GSB format)
043     */
044    public NTV2GridShiftFileWrapper(String filename) {
045        this.gridFileName = filename;
046    }
047
048    /**
049     * Returns the actual {@link NTV2GridShiftFile} behind this wrapper.
050     * The grid file is only loaded once, when first accessed.
051     * @return The NTv2 grid file
052     * @throws IOException if the grid file cannot be found/loaded
053     */
054    public synchronized NTV2GridShiftFile getShiftFile() throws IOException {
055        if (instance == null) {
056            for (Map.Entry<Float, NTV2GridShiftFileSource> entry : sources.entrySet()) {
057                NTV2GridShiftFileSource source = entry.getValue();
058                try (InputStream is = source.getNTV2GridShiftFile(gridFileName)) {
059                    if (is != null) {
060                        NTV2GridShiftFile ntv2 = new NTV2GridShiftFile();
061                        ntv2.loadGridShiftFile(is, false);
062                        instance = ntv2;
063                        break;
064                    }
065                }
066            }
067        }
068        return instance;
069    }
070}