001// License: GPL. For details, see LICENSE file.
002package org.openstreetmap.josm.io;
003
004import static org.openstreetmap.josm.tools.I18n.tr;
005
006import java.io.IOException;
007import java.io.InputStream;
008import java.util.Collections;
009import java.util.List;
010
011import org.openstreetmap.josm.data.gpx.GpxData;
012import org.openstreetmap.josm.data.notes.Note;
013import org.openstreetmap.josm.data.osm.DataSet;
014import org.openstreetmap.josm.gui.progress.ProgressMonitor;
015import org.openstreetmap.josm.io.UrlPatterns.GpxUrlPattern;
016import org.openstreetmap.josm.tools.Utils;
017import org.xml.sax.SAXException;
018
019/**
020 * Read content from OSM server for a given URL
021 * @since 1146
022 */
023public class OsmServerLocationReader extends OsmServerReader {
024
025    protected final String url;
026
027    /**
028     * Constructs a new {@code OsmServerLocationReader}.
029     * @param url The URL to fetch
030     */
031    public OsmServerLocationReader(String url) {
032        this.url = url;
033    }
034
035    /**
036     * Returns the URL to fetch
037     * @return the URL to fetch
038     * @since 15247
039     */
040    public final String getUrl() {
041        return url;
042    }
043
044    protected abstract static class Parser<T> {
045        protected final ProgressMonitor progressMonitor;
046        protected final Compression compression;
047        protected InputStream in;
048
049        protected Parser(ProgressMonitor progressMonitor, Compression compression) {
050            this.progressMonitor = progressMonitor;
051            this.compression = compression;
052        }
053
054        public abstract T parse() throws OsmTransferException, IllegalDataException, IOException, SAXException;
055    }
056
057    protected final <T> T doParse(Parser<T> parser, final ProgressMonitor progressMonitor) throws OsmTransferException {
058        progressMonitor.beginTask(tr("Contacting Server...", 10));
059        try { // NOPMD
060            return parser.parse();
061        } catch (OsmTransferException e) {
062            throw e;
063        } catch (IOException | SAXException | IllegalDataException e) {
064            if (cancel)
065                return null;
066            throw new OsmTransferException(e);
067        } finally {
068            progressMonitor.finishTask();
069            activeConnection = null;
070            Utils.close(parser.in);
071            parser.in = null;
072        }
073    }
074
075    @Override
076    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
077        return parseOsm(progressMonitor, Compression.NONE);
078    }
079
080    @Override
081    public DataSet parseOsm(ProgressMonitor progressMonitor, Compression compression) throws OsmTransferException {
082        return doParse(new OsmParser(progressMonitor, compression), progressMonitor);
083    }
084
085    @Override
086    public DataSet parseOsmChange(ProgressMonitor progressMonitor) throws OsmTransferException {
087        return parseOsmChange(progressMonitor, Compression.NONE);
088    }
089
090    @Override
091    public DataSet parseOsmChange(ProgressMonitor progressMonitor, Compression compression) throws OsmTransferException {
092        return doParse(new OsmChangeParser(progressMonitor, compression), progressMonitor);
093    }
094
095    @Override
096    public GpxData parseRawGps(ProgressMonitor progressMonitor) throws OsmTransferException {
097        return parseRawGps(progressMonitor, Compression.NONE);
098    }
099
100    @Override
101    public GpxData parseRawGps(ProgressMonitor progressMonitor, Compression compression) throws OsmTransferException {
102        return doParse(new GpxParser(progressMonitor, compression), progressMonitor);
103    }
104
105    @Override
106    public List<Note> parseRawNotes(ProgressMonitor progressMonitor) throws OsmTransferException {
107        return parseRawNotes(progressMonitor, Compression.NONE);
108    }
109
110    @Override
111    public List<Note> parseRawNotes(ProgressMonitor progressMonitor, Compression compression) throws OsmTransferException {
112        return doParse(new NoteParser(progressMonitor, compression), progressMonitor);
113    }
114
115    protected class OsmParser extends Parser<DataSet> {
116        protected OsmParser(ProgressMonitor progressMonitor, Compression compression) {
117            super(progressMonitor, compression);
118        }
119
120        @Override
121        public DataSet parse() throws OsmTransferException, IllegalDataException, IOException {
122            in = getInputStreamRaw(url, progressMonitor.createSubTaskMonitor(9, false));
123            if (in == null)
124                return null;
125            progressMonitor.subTask(tr("Downloading OSM data..."));
126            InputStream uncompressedInputStream = compression.getUncompressedInputStream(in); // NOPMD
127            ProgressMonitor subTaskMonitor = progressMonitor.createSubTaskMonitor(1, false);
128            if ("application/json".equals(contentType)) {
129                return OsmJsonReader.parseDataSet(uncompressedInputStream, subTaskMonitor);
130            } else {
131                return OsmReader.parseDataSet(uncompressedInputStream, subTaskMonitor);
132            }
133        }
134    }
135
136    protected class OsmChangeParser extends Parser<DataSet> {
137        protected OsmChangeParser(ProgressMonitor progressMonitor, Compression compression) {
138            super(progressMonitor, compression);
139        }
140
141        @Override
142        public DataSet parse() throws OsmTransferException, IllegalDataException, IOException {
143            in = getInputStreamRaw(url, progressMonitor.createSubTaskMonitor(9, false));
144            if (in == null)
145                return null;
146            progressMonitor.subTask(tr("Downloading OSM data..."));
147            return OsmChangeReader.parseDataSet(compression.getUncompressedInputStream(in), progressMonitor.createSubTaskMonitor(1, false));
148        }
149    }
150
151    protected class GpxParser extends Parser<GpxData> {
152        protected GpxParser(ProgressMonitor progressMonitor, Compression compression) {
153            super(progressMonitor, compression);
154        }
155
156        @Override
157        public GpxData parse() throws OsmTransferException, IllegalDataException, IOException, SAXException {
158            in = getInputStreamRaw(url, progressMonitor.createSubTaskMonitor(1, true), null, true);
159            if (in == null)
160                return null;
161            progressMonitor.subTask(tr("Downloading OSM data..."));
162            GpxReader reader = new GpxReader(compression.getUncompressedInputStream(in));
163            gpxParsedProperly = reader.parse(false);
164            GpxData result = reader.getGpxData();
165            result.fromServer = GpxUrlPattern.isGpxFromServer(url);
166            return result;
167        }
168    }
169
170    protected class NoteParser extends Parser<List<Note>> {
171
172        public NoteParser(ProgressMonitor progressMonitor, Compression compression) {
173            super(progressMonitor, compression);
174        }
175
176        @Override
177        public List<Note> parse() throws OsmTransferException, IllegalDataException, IOException, SAXException {
178            in = getInputStream(url, progressMonitor.createSubTaskMonitor(1, true));
179            if (in == null) {
180                return Collections.emptyList();
181            }
182            progressMonitor.subTask(tr("Downloading OSM notes..."));
183            NoteReader reader = new NoteReader(compression.getUncompressedInputStream(in));
184            return reader.parse();
185        }
186    }
187}