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        File grid = null;
046        // Check is the grid is installed in default PROJ.4 directories
047        for (File dir : Platform.determinePlatform().accept(this)) {
048            File file = new File(dir, gridFileName);
049            if (file.exists() && file.isFile()) {
050                grid = file;
051                break;
052            }
053        }
054        // If not, search into PROJ_LIB directory
055        if (grid == null) {
056            String projLib = Utils.getSystemProperty("PROJ_LIB");
057            if (projLib != null && !projLib.isEmpty()) {
058                File dir = new File(projLib);
059                if (dir.exists() && dir.isDirectory()) {
060                    File file = new File(dir, gridFileName);
061                    if (file.exists() && file.isFile()) {
062                        grid = file;
063                    }
064                }
065            }
066        }
067        if (grid != null) {
068            try {
069                return Files.newInputStream(grid.getAbsoluteFile().toPath());
070            } catch (IOException | InvalidPathException ex) {
071                Logging.warn("Unable to open NTV2 grid shift file: " + grid);
072                Logging.debug(ex);
073            }
074        }
075        return null;
076    }
077
078    private static List<File> visit(String prefSuffix, String... defaults) {
079        return Config.getPref().getList("ntv2.proj4.grid.dir." + prefSuffix, Arrays.asList(defaults))
080                               .stream().map(File::new).collect(Collectors.toList());
081    }
082
083    @Override
084    public List<File> visitUnixoid() {
085        return visit("unix", "/usr/local/share/proj", "/usr/share/proj");
086    }
087
088    @Override
089    public List<File> visitWindows() {
090        return visit("windows", "C:\\PROJ\\NAD");
091    }
092
093    @Override
094    public List<File> visitOsx() {
095        return Collections.emptyList();
096    }
097}