001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.data.projection.datum;
003
004import java.io.File;
005import java.io.IOException;
006import java.io.InputStream;
007import java.nio.file.Files;
008import java.nio.file.InvalidPathException;
009import java.util.Arrays;
010import java.util.Collections;
011import java.util.List;
012import java.util.stream.Collectors;
013
014import org.openstreetmap.josm.spi.preferences.Config;
015import org.openstreetmap.josm.tools.Logging;
016import org.openstreetmap.josm.tools.Platform;
017import org.openstreetmap.josm.tools.PlatformVisitor;
018import org.openstreetmap.josm.tools.Utils;
019
020/**
021 * Shift file source that scans the common data directories of the proj4 library.
022 * @since 12777
023 */
024public final class NTV2Proj4DirGridShiftFileSource implements NTV2GridShiftFileSource, PlatformVisitor<List<File>> {
025
026    private NTV2Proj4DirGridShiftFileSource() {
027        // hide constructor
028    }
029
030    // lazy initialization
031    private static class InstanceHolder {
032        static final NTV2Proj4DirGridShiftFileSource INSTANCE = new NTV2Proj4DirGridShiftFileSource();
033    }
034
035    /**
036     * Get the singleton instance of this class.
037     * @return the singleton instance of this class
038     */
039    public static NTV2Proj4DirGridShiftFileSource getInstance() {
040        return InstanceHolder.INSTANCE;
041    }
042
043    @Override
044    public InputStream getNTV2GridShiftFile(String gridFileName) {
045        // Check is the grid is installed in default PROJ.4 directories
046        File grid = Platform.determinePlatform().accept(this).stream()
047                .map(dir -> new File(dir, gridFileName))
048                .filter(file -> file.exists() && file.isFile())
049                .findFirst().orElse(null);
050        // If not, search into PROJ_LIB directory
051        if (grid == null) {
052            String projLib = Utils.getSystemProperty("PROJ_LIB");
053            if (!Utils.isEmpty(projLib)) {
054                File dir = new File(projLib);
055                if (dir.exists() && dir.isDirectory()) {
056                    File file = new File(dir, gridFileName);
057                    if (file.exists() && file.isFile()) {
058                        grid = file;
059                    }
060                }
061            }
062        }
063        if (grid != null) {
064            try {
065                return Files.newInputStream(grid.getAbsoluteFile().toPath());
066            } catch (IOException | InvalidPathException ex) {
067                Logging.warn("Unable to open NTV2 grid shift file: " + grid);
068                Logging.debug(ex);
069            }
070        }
071        return null;
072    }
073
074    private static List<File> visit(String prefSuffix, String... defaults) {
075        return Config.getPref().getList("ntv2.proj4.grid.dir." + prefSuffix, Arrays.asList(defaults))
076                               .stream().map(File::new).collect(Collectors.toList());
077    }
078
079    @Override
080    public List<File> visitUnixoid() {
081        return visit("unix", "/usr/local/share/proj", "/usr/share/proj");
082    }
083
084    @Override
085    public List<File> visitWindows() {
086        return visit("windows", "C:\\PROJ\\NAD");
087    }
088
089    @Override
090    public List<File> visitOsx() {
091        return Collections.emptyList();
092    }
093}