Changeset 11916 in josm


Ignore:
Timestamp:
2017-04-15T16:15:28+02:00 (6 months ago)
Author:
Don-vip
Message:

see #14653 - add support for multiple Overpass API output formats

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/io/OverpassDownloadReader.java

    r11627 r11916  
    77import java.io.InputStream;
    88import java.util.EnumMap;
     9import java.util.Map;
    910import java.util.NoSuchElementException;
     11import java.util.Objects;
     12import java.util.concurrent.ConcurrentHashMap;
    1013import java.util.concurrent.TimeUnit;
    1114import java.util.regex.Matcher;
     
    4649    }
    4750
     51    /**
     52     * Possible Overpass API output format, with the {@code [out:<directive>]} statement.
     53     * @since 11916
     54     */
     55    enum OverpassOutpoutFormat {
     56        /** Default output format: plain OSM XML */
     57        OSM_XML("xml"),
     58        /** OSM JSON format (not GeoJson) */
     59        OSM_JSON("json"),
     60        /** CSV, see https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Output_Format_.28out.29 */
     61        CSV("csv"),
     62        /** Custom, see https://overpass-api.de/output_formats.html#custom */
     63        CUSTOM("custom"),
     64        /** Popup, see https://overpass-api.de/output_formats.html#popup */
     65        POPUP("popup"),
     66        /** PBF, see https://josm.openstreetmap.de/ticket/14653 */
     67        PBF("pbf");
     68
     69        private final String directive;
     70
     71        OverpassOutpoutFormat(String directive) {
     72            this.directive = directive;
     73        }
     74
     75        /**
     76         * Returns the directive used in {@code [out:<directive>]} statement.
     77         * @return the directive used in {@code [out:<directive>]} statement
     78         */
     79        public String getDirective() {
     80            return directive;
     81        }
     82
     83        /**
     84         * Returns the {@code OverpassOutpoutFormat} matching the given directive.
     85         * @param directive directive used in {@code [out:<directive>]} statement
     86         * @return {@code OverpassOutpoutFormat} matching the given directive
     87         * @throws IllegalArgumentException in case of invalid directive
     88         */
     89        static OverpassOutpoutFormat from(String directive) {
     90            for (OverpassOutpoutFormat oof : values()) {
     91                if (oof.directive.equals(directive)) {
     92                    return oof;
     93                }
     94            }
     95            throw new IllegalArgumentException(directive);
     96        }
     97    }
     98
     99    static final Pattern OUTPUT_FORMAT_STATEMENT = Pattern.compile(".*\\[out:([a-z]{3,})\\].*", Pattern.DOTALL);
     100
     101    static final Map<OverpassOutpoutFormat, Class<? extends OsmReader>> outputFormatReaders = new ConcurrentHashMap<>();
     102
    48103    final String overpassServer;
    49104    final String overpassQuery;
     
    60115        this.overpassServer = overpassServer;
    61116        this.overpassQuery = overpassQuery.trim();
     117    }
     118
     119    /**
     120     * Registers an OSM reader for the given Overpass output format.
     121     * @param format Overpass output format
     122     * @param readerClass OSM reader class
     123     * @return the previous value associated with {@code format}, or {@code null} if there was no mapping
     124     */
     125    public static final Class<? extends OsmReader> registerOverpassOutpoutFormatReader(
     126            OverpassOutpoutFormat format, Class<? extends OsmReader> readerClass) {
     127        return outputFormatReaders.put(Objects.requireNonNull(format), Objects.requireNonNull(readerClass));
     128    }
     129
     130    static {
     131        registerOverpassOutpoutFormatReader(OverpassOutpoutFormat.OSM_XML, OverpassOsmReader.class);
    62132    }
    63133
     
    160230    @Override
    161231    protected DataSet parseDataSet(InputStream source, ProgressMonitor progressMonitor) throws IllegalDataException {
    162         return new OverpassOsmReader().doParseDataSet(source, progressMonitor);
     232        OsmReader reader = null;
     233        Matcher m = OUTPUT_FORMAT_STATEMENT.matcher(overpassQuery);
     234        if (m.matches()) {
     235            Class<? extends OsmReader> readerClass = outputFormatReaders.get(OverpassOutpoutFormat.from(m.group(1)));
     236            if (readerClass != null) {
     237                try {
     238                    reader = readerClass.getConstructor().newInstance();
     239                } catch (ReflectiveOperationException | IllegalArgumentException | SecurityException e) {
     240                    Main.error(e);
     241                }
     242            }
     243        }
     244        if (reader == null) {
     245            reader = new OverpassOsmReader();
     246        }
     247        return reader.doParseDataSet(source, progressMonitor);
    163248    }
    164249
  • trunk/test/unit/org/openstreetmap/josm/io/OverpassDownloadReaderTest.java

    r11009 r11916  
    33
    44import static org.junit.Assert.assertEquals;
     5import static org.junit.Assert.assertTrue;
    56
    67import org.junit.Rule;
     
    89import org.openstreetmap.josm.data.Bounds;
    910import org.openstreetmap.josm.gui.preferences.server.OverpassServerPreference;
     11import org.openstreetmap.josm.io.OverpassDownloadReader.OverpassOutpoutFormat;
    1012import org.openstreetmap.josm.testutils.JOSMTestRules;
    1113import org.openstreetmap.josm.tools.OverpassTurboQueryWizard;
     
    7779        assertEquals("// Failed to evaluate {{geocodeArea:foo-bar-baz-does-not-exist}}\n", query);
    7880    }
     81
     82    /**
     83     * Tests evaluating the overpass output format statements.
     84     */
     85    @Test
     86    public void testOutputFormatStatement() {
     87        for (OverpassOutpoutFormat oof : OverpassOutpoutFormat.values()) {
     88            assertTrue(OverpassDownloadReader.OUTPUT_FORMAT_STATEMENT.matcher("[out:"+oof.getDirective()+"]").matches());
     89        }
     90
     91        assertTrue(OverpassDownloadReader.OUTPUT_FORMAT_STATEMENT.matcher(
     92                "[out:pbf][timeout:25][bbox:{{bbox}}];\n" +
     93                "(\n" +
     94                "  node[\"amenity\"=\"pharmacy\"];\n" +
     95                "  way[\"amenity\"=\"pharmacy\"];\n" +
     96                "  relation[\"amenity\"=\"pharmacy\"];\n" +
     97                ");\n" +
     98                "(._;>;);\n" +
     99                "out meta;").matches());
     100    }
    79101}
Note: See TracChangeset for help on using the changeset viewer.