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