[11247] | 1 | // License: GPL. For details, see LICENSE file.
|
---|
| 2 | package org.openstreetmap.josm.tools;
|
---|
| 3 |
|
---|
[11360] | 4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
| 5 |
|
---|
[11247] | 6 | import java.io.IOException;
|
---|
| 7 | import java.io.InputStream;
|
---|
| 8 | import java.util.ArrayList;
|
---|
| 9 | import java.util.Collection;
|
---|
[11360] | 10 | import java.util.Collections;
|
---|
| 11 | import java.util.HashMap;
|
---|
[11247] | 12 | import java.util.Map;
|
---|
| 13 | import java.util.Set;
|
---|
| 14 |
|
---|
| 15 | import org.openstreetmap.josm.data.coor.LatLon;
|
---|
| 16 | import org.openstreetmap.josm.data.osm.DataSet;
|
---|
| 17 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
[11360] | 18 | import org.openstreetmap.josm.data.osm.Relation;
|
---|
| 19 | import org.openstreetmap.josm.data.osm.Way;
|
---|
[11247] | 20 | import org.openstreetmap.josm.io.CachedFile;
|
---|
| 21 | import org.openstreetmap.josm.io.IllegalDataException;
|
---|
| 22 | import org.openstreetmap.josm.io.OsmReader;
|
---|
| 23 |
|
---|
| 24 | /**
|
---|
| 25 | * Look up territories ISO3166 codes at a certain place.
|
---|
| 26 | */
|
---|
| 27 | public final class Territories {
|
---|
| 28 |
|
---|
[12484] | 29 | /** Internal OSM filename */
|
---|
| 30 | public static final String FILENAME = "boundaries.osm";
|
---|
| 31 |
|
---|
[11247] | 32 | private static final String ISO3166_1 = "ISO3166-1:alpha2";
|
---|
| 33 | private static final String ISO3166_2 = "ISO3166-2";
|
---|
| 34 |
|
---|
| 35 | private static DataSet dataSet;
|
---|
| 36 |
|
---|
[11360] | 37 | private static volatile Map<String, GeoPropertyIndex<Boolean>> iso3166Cache;
|
---|
[11247] | 38 |
|
---|
| 39 | private Territories() {
|
---|
| 40 | // Hide implicit public constructor for utility classes
|
---|
| 41 | }
|
---|
| 42 |
|
---|
| 43 | /**
|
---|
| 44 | * Get all known ISO3166-1 and ISO3166-2 codes.
|
---|
| 45 | *
|
---|
| 46 | * @return the ISO3166-1 and ISO3166-2 codes for the given location
|
---|
| 47 | */
|
---|
| 48 | public static synchronized Set<String> getKnownIso3166Codes() {
|
---|
[11360] | 49 | return iso3166Cache.keySet();
|
---|
[11247] | 50 | }
|
---|
| 51 |
|
---|
| 52 | /**
|
---|
[11360] | 53 | * Determine, if a point is inside a territory with the given the ISO3166-1
|
---|
| 54 | * or ISO3166-2 code.
|
---|
[11247] | 55 | *
|
---|
[11360] | 56 | * @param code the ISO3166-1 or ISO3166-2 code
|
---|
[11247] | 57 | * @param ll the coordinates of the point
|
---|
[11360] | 58 | * @return true, if the point is inside a territory with the given code
|
---|
[11247] | 59 | */
|
---|
[11360] | 60 | public static synchronized boolean isIso3166Code(String code, LatLon ll) {
|
---|
| 61 | GeoPropertyIndex<Boolean> gpi = iso3166Cache.get(code);
|
---|
| 62 | if (gpi == null) {
|
---|
[12620] | 63 | Logging.warn(tr("Unknown territory id: {0}", code));
|
---|
[11360] | 64 | return false;
|
---|
| 65 | }
|
---|
| 66 | return gpi.get(ll);
|
---|
[11247] | 67 | }
|
---|
| 68 |
|
---|
| 69 | /**
|
---|
| 70 | * Returns the territories dataset.
|
---|
| 71 | * @return the territories dataset
|
---|
| 72 | */
|
---|
| 73 | public static synchronized DataSet getDataSet() {
|
---|
| 74 | return new DataSet(dataSet);
|
---|
| 75 | }
|
---|
| 76 |
|
---|
| 77 | /**
|
---|
| 78 | * Initializes territories.
|
---|
| 79 | * TODO: Synchronization can be refined inside the {@link GeoPropertyIndex} as most look-ups are read-only.
|
---|
| 80 | */
|
---|
| 81 | public static synchronized void initialize() {
|
---|
[11360] | 82 | iso3166Cache = new HashMap<>();
|
---|
[12484] | 83 | try (CachedFile cf = new CachedFile("resource://data/" + FILENAME);
|
---|
[11247] | 84 | InputStream is = cf.getInputStream()) {
|
---|
| 85 | dataSet = OsmReader.parseDataSet(is, null);
|
---|
| 86 | Collection<OsmPrimitive> candidates = new ArrayList<>(dataSet.getWays());
|
---|
| 87 | candidates.addAll(dataSet.getRelations());
|
---|
| 88 | for (OsmPrimitive osm : candidates) {
|
---|
| 89 | String iso1 = osm.get(ISO3166_1);
|
---|
| 90 | String iso2 = osm.get(ISO3166_2);
|
---|
[11360] | 91 | if (iso1 != null || iso2 != null) {
|
---|
| 92 | GeoProperty<Boolean> gp;
|
---|
| 93 | if (osm instanceof Way) {
|
---|
| 94 | gp = new DefaultGeoProperty(Collections.singleton((Way) osm));
|
---|
| 95 | } else {
|
---|
| 96 | gp = new DefaultGeoProperty((Relation) osm);
|
---|
| 97 | }
|
---|
[11362] | 98 | GeoPropertyIndex<Boolean> gpi = new GeoPropertyIndex<>(gp, 24);
|
---|
[11360] | 99 | if (iso1 != null) {
|
---|
| 100 | iso3166Cache.put(iso1, gpi);
|
---|
| 101 | }
|
---|
| 102 | if (iso2 != null) {
|
---|
| 103 | iso3166Cache.put(iso2, gpi);
|
---|
| 104 | }
|
---|
[11247] | 105 | }
|
---|
| 106 | }
|
---|
| 107 | } catch (IOException | IllegalDataException ex) {
|
---|
[11374] | 108 | throw new JosmRuntimeException(ex);
|
---|
[11247] | 109 | }
|
---|
| 110 | }
|
---|
| 111 | }
|
---|