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