Ignore:
Timestamp:
2020-02-17T16:33:43+01:00 (4 years ago)
Author:
Don-vip
Message:

fix #18729, see #18302 - support regional taginfo instances from Geofabrik

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/Territories.java

    r15569 r15876  
    77import java.io.InputStream;
    88import java.util.ArrayList;
     9import java.util.Arrays;
    910import java.util.Collection;
    1011import java.util.Collections;
    1112import java.util.HashMap;
     13import java.util.List;
     14import java.util.Locale;
    1215import java.util.Map;
    1316import java.util.Map.Entry;
     17import java.util.Optional;
    1418import java.util.Set;
    1519import java.util.TreeMap;
    1620import java.util.stream.Collectors;
     21
     22import javax.json.Json;
     23import javax.json.JsonArray;
     24import javax.json.JsonObject;
     25import javax.json.JsonString;
     26import javax.json.JsonValue;
     27import javax.json.stream.JsonParser;
     28import javax.json.stream.JsonParser.Event;
    1729
    1830import org.openstreetmap.josm.data.coor.LatLon;
     
    2436import org.openstreetmap.josm.io.IllegalDataException;
    2537import org.openstreetmap.josm.io.OsmReader;
     38import org.openstreetmap.josm.spi.preferences.Config;
    2639
    2740/**
     
    3548    private static final String ISO3166_1 = "ISO3166-1:alpha2";
    3649    private static final String ISO3166_2 = "ISO3166-2";
     50    private static final String ISO3166_1_LC = ISO3166_1.toLowerCase(Locale.ENGLISH);
     51    private static final String ISO3166_2_LC = ISO3166_2.toLowerCase(Locale.ENGLISH);
    3752    private static final String TAGINFO = "taginfo";
    3853
     
    4055
    4156    private static volatile Map<String, GeoPropertyIndex<Boolean>> iso3166Cache;
    42     private static volatile Map<String, String> taginfoCache;
     57    private static volatile Map<String, TaginfoRegionalInstance> taginfoCache;
     58    private static volatile Map<String, TaginfoRegionalInstance> taginfoGeofabrikCache;
    4359
    4460    private Territories() {
     
    104120     */
    105121    public static synchronized void initialize() {
     122        initializeInternalData();
     123        initializeExternalData();
     124    }
     125
     126    private static void initializeInternalData() {
    106127        iso3166Cache = new HashMap<>();
    107128        taginfoCache = new TreeMap<>();
     
    126147                        String taginfo = osm.get(TAGINFO);
    127148                        if (taginfo != null) {
    128                             taginfoCache.put(iso1, taginfo);
     149                            taginfoCache.put(iso1, new TaginfoRegionalInstance(taginfo, Collections.singleton(iso1)));
    129150                        }
    130151                    }
     
    139160    }
    140161
    141     /**
    142      * Returns a map of national taginfo instances for the given location.
     162    private static void initializeExternalData() {
     163        taginfoGeofabrikCache = new TreeMap<>();
     164        try (CachedFile cf = new CachedFile(Config.getUrls().getJOSMWebsite() + "/remote/geofabrik-index-v1-nogeom.json");
     165                InputStream is = cf.getInputStream();
     166                JsonParser json = Json.createParser(is)) {
     167            while (json.hasNext()) {
     168                Event event = json.next();
     169                if (event == Event.START_OBJECT) {
     170                    for (JsonValue feature : json.getObject().getJsonArray("features")) {
     171                        JsonObject props = feature.asJsonObject().getJsonObject("properties");
     172                        if (props != null) {
     173                            JsonObject urls = props.getJsonObject("urls");
     174                            if (urls != null) {
     175                                String taginfo = urls.getString(TAGINFO);
     176                                if (taginfo != null) {
     177                                    JsonArray iso1 = props.getJsonArray(ISO3166_1_LC);
     178                                    JsonArray iso2 = props.getJsonArray(ISO3166_2_LC);
     179                                    if (iso1 != null) {
     180                                        readExternalTaginfo(taginfo, iso1);
     181                                    } else if (iso2 != null) {
     182                                        readExternalTaginfo(taginfo, iso2);
     183                                    }
     184                                }
     185                            }
     186                        }
     187                    }
     188                }
     189            }
     190        } catch (IOException e) {
     191            throw new JosmRuntimeException(e);
     192        }
     193    }
     194
     195    private static void readExternalTaginfo(String taginfo, JsonArray jsonCodes) {
     196        Set<String> isoCodes = jsonCodes.getValuesAs(JsonString.class).stream().map(JsonString::getString).collect(Collectors.toSet());
     197        isoCodes.forEach(s -> taginfoGeofabrikCache.put(s, new TaginfoRegionalInstance(taginfo, isoCodes, "Geofabrik")));
     198    }
     199
     200    /**
     201     * Returns a map of regional taginfo instances for the given location.
    143202     * @param ll lat/lon where to look.
    144      * @return a map of national taginfo instances for the given location (code / url)
    145      * @since 15565
    146      */
    147     public static Map<String, String> getNationalTaginfoUrls(LatLon ll) {
    148         Map<String, String> result = new TreeMap<>();
     203     * @return a map of regional taginfo instances for the given location (code / url)
     204     * @since 15876
     205     */
     206    public static Map<String, List<TaginfoRegionalInstance>> getRegionalTaginfoUrls(LatLon ll) {
     207        Map<String, List<TaginfoRegionalInstance>> result = new TreeMap<>();
    149208        if (iso3166Cache != null) {
    150209            for (String code : iso3166Cache.entrySet().parallelStream().distinct()
     
    152211                .map(Entry<String, GeoPropertyIndex<Boolean>>::getKey)
    153212                .collect(Collectors.toSet())) {
    154                 String taginfo = taginfoCache.get(code);
    155                 if (taginfo != null) {
    156                     result.put(code, taginfo);
     213                for (Map<String, TaginfoRegionalInstance> cache : Arrays.asList(taginfoCache, taginfoGeofabrikCache)) {
     214                    Optional.ofNullable(cache.get(code)).ifPresent(
     215                            taginfo -> result.computeIfAbsent(code, c -> new ArrayList<>()).add(taginfo));
    157216                }
    158217            }
Note: See TracChangeset for help on using the changeset viewer.