Ticket #11975: 0002-Evaluate-extended-Overpass-querty-geocodeArea.patch

File 0002-Evaluate-extended-Overpass-querty-geocodeArea.patch, 8.6 KB (added by simon04, 3 years ago)
  • src/org/openstreetmap/josm/io/NameFinder.java

    From 07c64bddd756f1bbaa36ee80dbf7052b4df4c278 Mon Sep 17 00:00:00 2001
    From: Simon Legner <Simon.Legner@gmail.com>
    Date: Thu, 4 Aug 2016 22:34:12 +0200
    Subject: [PATCH 2/2] Evaluate extended Overpass querty `geocodeArea`
    
    ---
     src/org/openstreetmap/josm/io/NameFinder.java      |  9 ++++
     .../josm/io/OverpassDownloadReader.java            |  5 +--
     .../josm/tools/OverpassTurboQueryWizard.java       | 49 ++++++++++++++++++++++
     .../josm/tools/OverpassTurboQueryWizardTest.java   | 32 +++++++++++++-
     4 files changed, 90 insertions(+), 5 deletions(-)
    
    diff --git a/src/org/openstreetmap/josm/io/NameFinder.java b/src/org/openstreetmap/josm/io/NameFinder.java
    index c7f9256..6bdb981 100644
    a b  
    1313
    1414import org.openstreetmap.josm.Main;
    1515import org.openstreetmap.josm.data.Bounds;
     16import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     17import org.openstreetmap.josm.data.osm.PrimitiveId;
     18import org.openstreetmap.josm.data.osm.SimplePrimitiveId;
    1619import org.openstreetmap.josm.tools.HttpClient;
    1720import org.openstreetmap.josm.tools.OsmUrlToBounds;
    1821import org.openstreetmap.josm.tools.UncheckedParseException;
    private NameFinder() { 
    6568        public double lon;
    6669        public int zoom;
    6770        public Bounds bounds;
     71        public PrimitiveId osmId;
    6872
    6973        public Bounds getDownloadArea() {
    7074            return bounds != null ? bounds : OsmUrlToBounds.positionToBounds(lat, lon, zoom);
    public void startElement(String namespaceURI, String localName, String qName, At 
    125129                    currentResult.bounds = new Bounds(
    126130                            Double.parseDouble(bbox[0]), Double.parseDouble(bbox[2]),
    127131                            Double.parseDouble(bbox[1]), Double.parseDouble(bbox[3]));
     132                    final String osmId = atts.getValue("osm_id");
     133                    final String osmType = atts.getValue("osm_type");
     134                    if (osmId != null && osmType != null) {
     135                        currentResult.osmId = new SimplePrimitiveId(Long.parseLong(osmId), OsmPrimitiveType.from(osmType));
     136                    }
    128137                    data.add(currentResult);
    129138                }
    130139            } catch (NumberFormatException x) {
  • src/org/openstreetmap/josm/io/OverpassDownloadReader.java

    diff --git a/src/org/openstreetmap/josm/io/OverpassDownloadReader.java b/src/org/openstreetmap/josm/io/OverpassDownloadReader.java
    index be43043..cfbb637 100644
    a b protected String getRequestForBbox(double lon1, double lat1, double lon2, double 
    5050        if (overpassQuery.isEmpty())
    5151            return super.getRequestForBbox(lon1, lat1, lon2, lat2);
    5252        else {
    53             String realQuery = completeOverpassQuery(overpassQuery);
    54             return "interpreter?data=" + Utils.encodeUrl(realQuery)
    55                     + "&bbox=" + lon1 + ',' + lat1 + ',' + lon2 + ',' + lat2;
     53            return "interpreter?data=" + Utils.encodeUrl(overpassQuery)
     54                    + (!overpassQuery.contains("searchArea") ? "&bbox=" + lon1 + ',' + lat1 + ',' + lon2 + ',' + lat2 : "");
    5655        }
    5756    }
    5857
  • src/org/openstreetmap/josm/tools/OverpassTurboQueryWizard.java

    diff --git a/src/org/openstreetmap/josm/tools/OverpassTurboQueryWizard.java b/src/org/openstreetmap/josm/tools/OverpassTurboQueryWizard.java
    index f0020d9..555a525 100644
    a b  
    11// License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.tools;
    33
     4import static org.openstreetmap.josm.tools.I18n.tr;
     5
    46import java.io.IOException;
    57import java.io.Reader;
     8import java.util.EnumMap;
     9import java.util.List;
     10import java.util.regex.Matcher;
     11import java.util.regex.Pattern;
    612
    713import javax.script.Invocable;
    814import javax.script.ScriptEngine;
     
    1016import javax.script.ScriptException;
    1117
    1218import org.openstreetmap.josm.Main;
     19import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
     20import org.openstreetmap.josm.data.osm.PrimitiveId;
    1321import org.openstreetmap.josm.io.CachedFile;
     22import org.openstreetmap.josm.io.NameFinder;
    1423
    1524/**
    1625 * Uses <a href="https://github.com/tyrasd/overpass-wizard/">Overpass Turbo query wizard</a> code (MIT Licensed)
    public String constructQuery(String search) { 
    7079            String query = (String) result;
    7180            if (query != null) {
    7281                query = query.replace("[bbox:{{bbox}}]", "");
     82                query = expandExtendedQueries(query);
    7383            }
    7484            return query;
    7585        } catch (NoSuchMethodException e) {
    public String constructQuery(String search) { 
    7888            throw new UncheckedParseException("Failed to execute OverpassTurboQueryWizard", e);
    7989        }
    8090    }
     91
     92    /**
     93     * Evaluates some features of overpass turbo extended query syntax.
     94     * See https://wiki.openstreetmap.org/wiki/Overpass_turbo/Extended_Overpass_Turbo_Queries
     95     */
     96    static String expandExtendedQueries(String query) {
     97        final StringBuffer sb = new StringBuffer();
     98        final Matcher matcher = Pattern.compile("\\{\\{(geocodeArea):([^}]+)\\}\\}").matcher(query);
     99        while (matcher.find()) {
     100            try {
     101                switch (matcher.group(1)) {
     102                    case "geocodeArea":
     103                        matcher.appendReplacement(sb, geocodeArea(matcher.group(2)));
     104                }
     105            } catch (Exception ex) {
     106                final String msg = tr("Failed to evaluate {0}", matcher.group());
     107                Main.warn(ex, msg);
     108                matcher.appendReplacement(sb, "// " + msg + "\n");
     109            }
     110        }
     111        matcher.appendTail(sb);
     112        query = sb.toString();
     113        return query;
     114    }
     115
     116    private static String geocodeArea(String area) {
     117        // Offsets defined in https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#By_element_id
     118        final EnumMap<OsmPrimitiveType, Long> idOffset = new EnumMap<>(OsmPrimitiveType.class);
     119        idOffset.put(OsmPrimitiveType.NODE, 0L);
     120        idOffset.put(OsmPrimitiveType.WAY, 2400000000L);
     121        idOffset.put(OsmPrimitiveType.RELATION, 3600000000L);
     122        try {
     123            final List<NameFinder.SearchResult> results = NameFinder.queryNominatim(area);
     124            final PrimitiveId osmId = results.iterator().next().osmId;
     125            return String.format("area(%d)", osmId.getUniqueId() + idOffset.get(osmId.getType()));
     126        } catch (IOException ex) {
     127            throw new UncheckedParseException(ex);
     128        }
     129    }
    81130}
  • test/unit/org/openstreetmap/josm/tools/OverpassTurboQueryWizardTest.java

    diff --git a/test/unit/org/openstreetmap/josm/tools/OverpassTurboQueryWizardTest.java b/test/unit/org/openstreetmap/josm/tools/OverpassTurboQueryWizardTest.java
    index 125042f..2a7226f 100644
    a b  
    1414 */
    1515public class OverpassTurboQueryWizardTest {
    1616    /**
    17      * Base test environment is enough
     17     * Some of this depends on preferences.
    1818     */
    1919    @Rule
    2020    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
    21     public JOSMTestRules test = new JOSMTestRules();
     21    public JOSMTestRules test = new JOSMTestRules().preferences();
    2222
    2323    /**
    2424     * Test key=value.
    public void testKeyValue() { 
    3838    }
    3939
    4040    /**
     41     * Tests evaluating the extended query feature {@code geocodeArea}.
     42     */
     43    @Test
     44    public void testGeocodeArea() {
     45        final String query = OverpassTurboQueryWizard.getInstance().constructQuery("amenity=drinking_water in London");
     46        assertEquals("" +
     47                "[out:xml][timeout:25];\n" +
     48                "area(3600065606)->.searchArea;\n" +
     49                "(\n" +
     50                "  node[\"amenity\"=\"drinking_water\"](area.searchArea);\n" +
     51                "  way[\"amenity\"=\"drinking_water\"](area.searchArea);\n" +
     52                "  relation[\"amenity\"=\"drinking_water\"](area.searchArea);\n" +
     53                ");\n" +
     54                "(._;>;);\n" +
     55                "out meta;", query);
     56    }
     57
     58    /**
     59     * Tests evaluating the extended query feature {@code geocodeArea}.
     60     */
     61    @Test
     62    public void testGeocodeUnknownArea() {
     63        final String query = OverpassTurboQueryWizard.expandExtendedQueries("{{geocodeArea:foo-bar-baz-does-not-exist}}");
     64        assertEquals("// Failed to evaluate {{geocodeArea:foo-bar-baz-does-not-exist}}\n", query);
     65
     66    }
     67
     68    /**
    4169     * Test erroneous value.
    4270     */
    4371    @Test(expected = UncheckedParseException.class)