diff --git a/schema/boundary.fbs b/schema/boundary.fbs index dc2be87..df8f7ef 100644 --- a/schema/boundary.fbs +++ b/schema/boundary.fbs @@ -8,7 +8,8 @@ table Boundary { osm_id: long; level: int; name: string; - + code: string; + // Minimum Bounding Rectangle (The "Outer" box) min_x: double; min_y: double; diff --git a/schema/poi.fbs b/schema/poi.fbs index 2451759..fbbcde8 100644 --- a/schema/poi.fbs +++ b/schema/poi.fbs @@ -21,6 +21,7 @@ table HierarchyItem { type:string; // e.g., "country", "state", "city" name:string; // Localized name osm_id:long; // Reference to boundary geometry + code:string; // ISO3166-1 if available } // POI Geometry (stored as WKB bytes) diff --git a/src/main/java/com/dedicatedcode/paikka/dto/POIResponse.java b/src/main/java/com/dedicatedcode/paikka/dto/POIResponse.java index 540e18c..e8f4553 100644 --- a/src/main/java/com/dedicatedcode/paikka/dto/POIResponse.java +++ b/src/main/java/com/dedicatedcode/paikka/dto/POIResponse.java @@ -111,23 +111,28 @@ public static class HierarchyItem { @JsonProperty("osm_id") private long osmId; - + + @JsonProperty("country_code") + private String code; + @JsonProperty("geometry_url") private String geometryUrl; public HierarchyItem() {} - public HierarchyItem(int level, String type, String name, long osmId) { + public HierarchyItem(int level, String type, String name, String code, long osmId) { this.level = level; this.type = type; this.name = name; + this.code = code; this.osmId = osmId; } - public HierarchyItem(int level, String type, String name, long osmId, String geometryUrl) { + public HierarchyItem(int level, String type, String name, String code, long osmId, String geometryUrl) { this.level = level; this.type = type; this.name = name; + this.code = code; this.osmId = osmId; this.geometryUrl = geometryUrl; } @@ -146,6 +151,9 @@ public HierarchyItem(int level, String type, String name, long osmId, String geo public String getGeometryUrl() { return geometryUrl; } public void setGeometryUrl(String geometryUrl) { this.geometryUrl = geometryUrl; } + + public String getCode() { return code; } + public void setCode(String code) { this.code = code; } } public static class QueryInfo { diff --git a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Address.java b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Address.java index 770b0c2..4c3a1b0 100644 --- a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Address.java +++ b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Address.java @@ -1,19 +1,3 @@ -/* - * This file is part of paikka. - * - * Paikka is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 or - * any later version. - * - * Paikka is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * You should have received a copy of the GNU Affero General Public License - * along with Paikka. If not, see . - */ - // automatically generated by the FlatBuffers compiler, do not modify package com.dedicatedcode.paikka.flatbuffers; diff --git a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Boundary.java b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Boundary.java index 8aeb5ec..da9b36c 100644 --- a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Boundary.java +++ b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Boundary.java @@ -1,19 +1,3 @@ -/* - * This file is part of paikka. - * - * Paikka is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 or - * any later version. - * - * Paikka is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * You should have received a copy of the GNU Affero General Public License - * along with Paikka. If not, see . - */ - // automatically generated by the FlatBuffers compiler, do not modify package com.dedicatedcode.paikka.flatbuffers; @@ -36,21 +20,25 @@ public final class Boundary extends Table { public String name() { int o = __offset(8); return o != 0 ? __string(o + bb_pos) : null; } public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(8, 1); } public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); } - public double minX() { int o = __offset(10); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } - public double minY() { int o = __offset(12); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } - public double maxX() { int o = __offset(14); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } - public double maxY() { int o = __offset(16); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } - public double mirMinX() { int o = __offset(18); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } - public double mirMinY() { int o = __offset(20); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } - public double mirMaxX() { int o = __offset(22); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } - public double mirMaxY() { int o = __offset(24); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public String code() { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer codeAsByteBuffer() { return __vector_as_bytebuffer(10, 1); } + public ByteBuffer codeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 10, 1); } + public double minX() { int o = __offset(12); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public double minY() { int o = __offset(14); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public double maxX() { int o = __offset(16); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public double maxY() { int o = __offset(18); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public double mirMinX() { int o = __offset(20); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public double mirMinY() { int o = __offset(22); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public double mirMaxX() { int o = __offset(24); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } + public double mirMaxY() { int o = __offset(26); return o != 0 ? bb.getDouble(o + bb_pos) : 0.0; } public com.dedicatedcode.paikka.flatbuffers.Geometry geometry() { return geometry(new com.dedicatedcode.paikka.flatbuffers.Geometry()); } - public com.dedicatedcode.paikka.flatbuffers.Geometry geometry(com.dedicatedcode.paikka.flatbuffers.Geometry obj) { int o = __offset(26); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } + public com.dedicatedcode.paikka.flatbuffers.Geometry geometry(com.dedicatedcode.paikka.flatbuffers.Geometry obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } public static int createBoundary(FlatBufferBuilder builder, long osmId, int level, int nameOffset, + int codeOffset, double minX, double minY, double maxX, @@ -60,7 +48,7 @@ public static int createBoundary(FlatBufferBuilder builder, double mirMaxX, double mirMaxY, int geometryOffset) { - builder.startTable(12); + builder.startTable(13); Boundary.addMirMaxY(builder, mirMaxY); Boundary.addMirMaxX(builder, mirMaxX); Boundary.addMirMinY(builder, mirMinY); @@ -71,24 +59,26 @@ public static int createBoundary(FlatBufferBuilder builder, Boundary.addMinX(builder, minX); Boundary.addOsmId(builder, osmId); Boundary.addGeometry(builder, geometryOffset); + Boundary.addCode(builder, codeOffset); Boundary.addName(builder, nameOffset); Boundary.addLevel(builder, level); return Boundary.endBoundary(builder); } - public static void startBoundary(FlatBufferBuilder builder) { builder.startTable(12); } + public static void startBoundary(FlatBufferBuilder builder) { builder.startTable(13); } public static void addOsmId(FlatBufferBuilder builder, long osmId) { builder.addLong(0, osmId, 0L); } public static void addLevel(FlatBufferBuilder builder, int level) { builder.addInt(1, level, 0); } public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(2, nameOffset, 0); } - public static void addMinX(FlatBufferBuilder builder, double minX) { builder.addDouble(3, minX, 0.0); } - public static void addMinY(FlatBufferBuilder builder, double minY) { builder.addDouble(4, minY, 0.0); } - public static void addMaxX(FlatBufferBuilder builder, double maxX) { builder.addDouble(5, maxX, 0.0); } - public static void addMaxY(FlatBufferBuilder builder, double maxY) { builder.addDouble(6, maxY, 0.0); } - public static void addMirMinX(FlatBufferBuilder builder, double mirMinX) { builder.addDouble(7, mirMinX, 0.0); } - public static void addMirMinY(FlatBufferBuilder builder, double mirMinY) { builder.addDouble(8, mirMinY, 0.0); } - public static void addMirMaxX(FlatBufferBuilder builder, double mirMaxX) { builder.addDouble(9, mirMaxX, 0.0); } - public static void addMirMaxY(FlatBufferBuilder builder, double mirMaxY) { builder.addDouble(10, mirMaxY, 0.0); } - public static void addGeometry(FlatBufferBuilder builder, int geometryOffset) { builder.addOffset(11, geometryOffset, 0); } + public static void addCode(FlatBufferBuilder builder, int codeOffset) { builder.addOffset(3, codeOffset, 0); } + public static void addMinX(FlatBufferBuilder builder, double minX) { builder.addDouble(4, minX, 0.0); } + public static void addMinY(FlatBufferBuilder builder, double minY) { builder.addDouble(5, minY, 0.0); } + public static void addMaxX(FlatBufferBuilder builder, double maxX) { builder.addDouble(6, maxX, 0.0); } + public static void addMaxY(FlatBufferBuilder builder, double maxY) { builder.addDouble(7, maxY, 0.0); } + public static void addMirMinX(FlatBufferBuilder builder, double mirMinX) { builder.addDouble(8, mirMinX, 0.0); } + public static void addMirMinY(FlatBufferBuilder builder, double mirMinY) { builder.addDouble(9, mirMinY, 0.0); } + public static void addMirMaxX(FlatBufferBuilder builder, double mirMaxX) { builder.addDouble(10, mirMaxX, 0.0); } + public static void addMirMaxY(FlatBufferBuilder builder, double mirMaxY) { builder.addDouble(11, mirMaxY, 0.0); } + public static void addGeometry(FlatBufferBuilder builder, int geometryOffset) { builder.addOffset(12, geometryOffset, 0); } public static int endBoundary(FlatBufferBuilder builder) { int o = builder.endTable(); return o; diff --git a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Geometry.java b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Geometry.java index 3225bbc..d05b52d 100644 --- a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Geometry.java +++ b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Geometry.java @@ -1,19 +1,3 @@ -/* - * This file is part of paikka. - * - * Paikka is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 or - * any later version. - * - * Paikka is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * You should have received a copy of the GNU Affero General Public License - * along with Paikka. If not, see . - */ - // automatically generated by the FlatBuffers compiler, do not modify package com.dedicatedcode.paikka.flatbuffers; diff --git a/src/main/java/com/dedicatedcode/paikka/flatbuffers/HierarchyItem.java b/src/main/java/com/dedicatedcode/paikka/flatbuffers/HierarchyItem.java index 238c3c8..7e3680e 100644 --- a/src/main/java/com/dedicatedcode/paikka/flatbuffers/HierarchyItem.java +++ b/src/main/java/com/dedicatedcode/paikka/flatbuffers/HierarchyItem.java @@ -1,19 +1,3 @@ -/* - * This file is part of paikka. - * - * Paikka is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 or - * any later version. - * - * Paikka is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * You should have received a copy of the GNU Affero General Public License - * along with Paikka. If not, see . - */ - // automatically generated by the FlatBuffers compiler, do not modify package com.dedicatedcode.paikka.flatbuffers; @@ -39,25 +23,31 @@ public final class HierarchyItem extends Table { public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(8, 1); } public ByteBuffer nameInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 8, 1); } public long osmId() { int o = __offset(10); return o != 0 ? bb.getLong(o + bb_pos) : 0L; } + public String code() { int o = __offset(12); return o != 0 ? __string(o + bb_pos) : null; } + public ByteBuffer codeAsByteBuffer() { return __vector_as_bytebuffer(12, 1); } + public ByteBuffer codeInByteBuffer(ByteBuffer _bb) { return __vector_in_bytebuffer(_bb, 12, 1); } public static int createHierarchyItem(FlatBufferBuilder builder, int level, int typeOffset, int nameOffset, - long osmId) { - builder.startTable(4); + long osmId, + int codeOffset) { + builder.startTable(5); HierarchyItem.addOsmId(builder, osmId); + HierarchyItem.addCode(builder, codeOffset); HierarchyItem.addName(builder, nameOffset); HierarchyItem.addType(builder, typeOffset); HierarchyItem.addLevel(builder, level); return HierarchyItem.endHierarchyItem(builder); } - public static void startHierarchyItem(FlatBufferBuilder builder) { builder.startTable(4); } + public static void startHierarchyItem(FlatBufferBuilder builder) { builder.startTable(5); } public static void addLevel(FlatBufferBuilder builder, int level) { builder.addInt(0, level, 0); } public static void addType(FlatBufferBuilder builder, int typeOffset) { builder.addOffset(1, typeOffset, 0); } public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(2, nameOffset, 0); } public static void addOsmId(FlatBufferBuilder builder, long osmId) { builder.addLong(3, osmId, 0L); } + public static void addCode(FlatBufferBuilder builder, int codeOffset) { builder.addOffset(4, codeOffset, 0); } public static int endHierarchyItem(FlatBufferBuilder builder) { int o = builder.endTable(); return o; diff --git a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Name.java b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Name.java index ef69af2..cdacdbf 100644 --- a/src/main/java/com/dedicatedcode/paikka/flatbuffers/Name.java +++ b/src/main/java/com/dedicatedcode/paikka/flatbuffers/Name.java @@ -1,19 +1,3 @@ -/* - * This file is part of paikka. - * - * Paikka is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 or - * any later version. - * - * Paikka is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * You should have received a copy of the GNU Affero General Public License - * along with Paikka. If not, see . - */ - // automatically generated by the FlatBuffers compiler, do not modify package com.dedicatedcode.paikka.flatbuffers; diff --git a/src/main/java/com/dedicatedcode/paikka/flatbuffers/POI.java b/src/main/java/com/dedicatedcode/paikka/flatbuffers/POI.java index 8666670..b9d3b16 100644 --- a/src/main/java/com/dedicatedcode/paikka/flatbuffers/POI.java +++ b/src/main/java/com/dedicatedcode/paikka/flatbuffers/POI.java @@ -1,19 +1,3 @@ -/* - * This file is part of paikka. - * - * Paikka is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 or - * any later version. - * - * Paikka is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * You should have received a copy of the GNU Affero General Public License - * along with Paikka. If not, see . - */ - // automatically generated by the FlatBuffers compiler, do not modify package com.dedicatedcode.paikka.flatbuffers; diff --git a/src/main/java/com/dedicatedcode/paikka/flatbuffers/POIList.java b/src/main/java/com/dedicatedcode/paikka/flatbuffers/POIList.java index 85b77ff..3361fd5 100644 --- a/src/main/java/com/dedicatedcode/paikka/flatbuffers/POIList.java +++ b/src/main/java/com/dedicatedcode/paikka/flatbuffers/POIList.java @@ -1,19 +1,3 @@ -/* - * This file is part of paikka. - * - * Paikka is free software: you can redistribute it and/or - * modify it under the terms of the GNU Affero General Public License - * as published by the Free Software Foundation, either version 3 or - * any later version. - * - * Paikka is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Affero General Public License for more details. - * You should have received a copy of the GNU Affero General Public License - * along with Paikka. If not, see . - */ - // automatically generated by the FlatBuffers compiler, do not modify package com.dedicatedcode.paikka.flatbuffers; diff --git a/src/main/java/com/dedicatedcode/paikka/service/ReverseGeocodingService.java b/src/main/java/com/dedicatedcode/paikka/service/ReverseGeocodingService.java index d308906..37738c2 100644 --- a/src/main/java/com/dedicatedcode/paikka/service/ReverseGeocodingService.java +++ b/src/main/java/com/dedicatedcode/paikka/service/ReverseGeocodingService.java @@ -265,6 +265,7 @@ private List loadPOIsFromShard(long shardId) throws RocksDBException { item.level(), itemType != null ? itemType : "unknown", itemName != null ? itemName : "Unknown", + item.code(), item.osmId() )); logger.debug("Copied hierarchy: level={}, type={}, name={}", @@ -388,11 +389,11 @@ private POIResponse convertPOIToResponse(POIData poi, double queryLat, double qu logger.debug("POI {} has {} hierarchy items", poi.id(), poi.hierarchy().size()); for (HierarchyData item : poi.hierarchy()) { - logger.debug("Hierarchy: level={}, type={}, name={}, osmId={}", - item.level(), item.type(), item.name(), item.osmId()); + logger.debug("Hierarchy: level={}, type={}, name={}, osmId={}, code={}", + item.level(), item.type(), item.name(), item.osmId(), item.code()); String geometryUrl = buildGeometryUrl(item.osmId()); - hierarchy.add(new POIResponse.HierarchyItem(item.level(), item.type(), item.name(), item.osmId(), geometryUrl)); + hierarchy.add(new POIResponse.HierarchyItem(item.level(), item.type(), item.name(), item.code(), item.osmId(), geometryUrl)); } response.setHierarchy(hierarchy); @@ -428,7 +429,7 @@ private record POIData(long id, float lat, float lon, String type, String subtyp private record AddressData(String street, String houseNumber, String postcode, String city, String country) { } - private record HierarchyData(int level, String type, String name, long osmId) { + private record HierarchyData(int level, String type, String name, String code, long osmId) { } private record POIWithDistance(POIData poi, double distance) { diff --git a/src/main/java/com/dedicatedcode/paikka/service/importer/HierarchyCache.java b/src/main/java/com/dedicatedcode/paikka/service/importer/HierarchyCache.java index cf6a33c..c8b9451 100644 --- a/src/main/java/com/dedicatedcode/paikka/service/importer/HierarchyCache.java +++ b/src/main/java/com/dedicatedcode/paikka/service/importer/HierarchyCache.java @@ -89,7 +89,7 @@ private List refresh(double lon, double lat, long cellId) { return lastActiveBoundaries.stream() .sorted(Comparator.comparingInt(b -> b.level)) - .map(cb -> new SimpleHierarchyItem(cb.level, "administrative", cb.name, cb.osmId)) + .map(cb -> new SimpleHierarchyItem(cb.level, "administrative", cb.name, cb.osmId, cb.code)) .toList(); } @@ -107,7 +107,7 @@ private CachedBoundary fetchFromDb(long id) { wkbBuf.get(wkb); IndexedPointInAreaLocator locator = new IndexedPointInAreaLocator(wkbReader.read(wkb)); - return new CachedBoundary(b.level(), b.name(), b.osmId(), mir, mbr, locator); + return new CachedBoundary(b.level(), b.name(), b.code(), b.osmId(), mir, mbr, locator); } catch (Exception e) { return null; } } @@ -118,7 +118,7 @@ private long[] fetchGridCandidates(long cellId) { } catch (Exception e) { return null; } } - public record CachedBoundary(int level, String name, long osmId, Envelope mir, Envelope mbr, + public record CachedBoundary(int level, String name, String code, long osmId, Envelope mir, Envelope mbr, IndexedPointInAreaLocator locator) { public boolean contains(double lon, double lat) { if (mir != null && mir.contains(lon, lat)) return true; @@ -127,5 +127,5 @@ public boolean contains(double lon, double lat) { } } - public record SimpleHierarchyItem(int level, String type, String name, long osmId) {} + public record SimpleHierarchyItem(int level, String type, String name, long osmId, String code) {} } \ No newline at end of file diff --git a/src/main/java/com/dedicatedcode/paikka/service/importer/ImportService.java b/src/main/java/com/dedicatedcode/paikka/service/importer/ImportService.java index e295c88..23c35c6 100644 --- a/src/main/java/com/dedicatedcode/paikka/service/importer/ImportService.java +++ b/src/main/java/com/dedicatedcode/paikka/service/importer/ImportService.java @@ -740,7 +740,7 @@ private void processAdministrativeBoundariesFromIndex(RocksDB relIndexDb, RocksD org.locationtech.jts.geom.Geometry geometry = buildGeometryFromRelRec(rec, nodeCache, wayIndexDb, stats); if (geometry != null && geometry.isValid()) { org.locationtech.jts.geom.Geometry simplified = geometrySimplificationService.simplifyByAdminLevel(geometry, rec.level); - return new BoundaryResultLite(rec.osmId, rec.level, rec.name, simplified); + return new BoundaryResultLite(rec.osmId, rec.level, rec.name, rec.code, simplified); } return null; } finally { @@ -755,7 +755,7 @@ private void processAdministrativeBoundariesFromIndex(RocksDB relIndexDb, RocksD try { BoundaryResultLite r = f.get(); if (r != null) { - storeBoundary(r.osmId(), r.level(), r.name(), r.geometry(), boundariesWriter, gridsIndexDb); + storeBoundary(r.osmId(), r.level(), r.name(), r.code(), r.geometry(), boundariesWriter, gridsIndexDb); stats.incrementBoundariesProcessed(); } } catch (Exception e) { @@ -771,7 +771,7 @@ private void processAdministrativeBoundariesFromIndex(RocksDB relIndexDb, RocksD Future f = ecs.take(); BoundaryResultLite r = f.get(); if (r != null) { - storeBoundary(r.osmId(), r.level(), r.name(), r.geometry(), boundariesWriter, gridsIndexDb); + storeBoundary(r.osmId(), r.level(), r.name(), r.code(), r.geometry(), boundariesWriter, gridsIndexDb); stats.incrementBoundariesProcessed(); } } catch (Exception e) { @@ -795,7 +795,7 @@ private PoiData createPoiDataFromIndex(PoiIndexRec rec, double lat, double lon, sorted.sort(Comparator.comparingInt(HierarchyCache.SimpleHierarchyItem::level).reversed()); for (HierarchyCache.SimpleHierarchyItem item : sorted) { if (city == null && item.level() >= 6 && item.level() <= 10) city = item.name(); - if (country == null && item.level() == 2) country = item.name(); + if (country == null && item.level() == 2) country = item.code(); if (city != null && country != null) break; } } @@ -879,7 +879,7 @@ private int serializePoiData(FlatBufferBuilder builder, PoiData poi) { int[] hierOffs = new int[hierarchy.size()]; for (int j = 0; j < hierarchy.size(); j++) { HierarchyCache.SimpleHierarchyItem h = hierarchy.get(j); - hierOffs[j] = com.dedicatedcode.paikka.flatbuffers.HierarchyItem.createHierarchyItem(builder, h.level(), builder.createString(h.type()), builder.createString(h.name()), h.osmId()); + hierOffs[j] = com.dedicatedcode.paikka.flatbuffers.HierarchyItem.createHierarchyItem(builder, h.level(), builder.createString(h.type()), builder.createString(h.name()), h.osmId(), builder.createString(h.code())); } int hierVecOff = POI.createHierarchyVector(builder, hierOffs); @@ -1049,9 +1049,11 @@ private int copyPoiFromFlatBuffer(FlatBufferBuilder builder, POI poi, Name reusa poi.hierarchy(reusableHier, j); String hType = reusableHier.type(); String hName = reusableHier.name(); + String hCode = reusableHier.code(); int hTypeOff = hType != null ? builder.createString(hType) : 0; int hNameOff = hName != null ? builder.createString(hName) : 0; - hierOffs[j] = com.dedicatedcode.paikka.flatbuffers.HierarchyItem.createHierarchyItem(builder, reusableHier.level(), hTypeOff, hNameOff, reusableHier.osmId()); + int hCodeOff = hCode != null ? builder.createString(hCode) : 0; + hierOffs[j] = com.dedicatedcode.paikka.flatbuffers.HierarchyItem.createHierarchyItem(builder, reusableHier.level(), hTypeOff, hNameOff, reusableHier.osmId(), hCodeOff); } hierVecOff = POI.createHierarchyVector(builder, hierOffs); } else { @@ -1279,7 +1281,7 @@ private List> buildConnectedRings(List wayIds, RocksDB no return rings; } - private void storeBoundary(long osmId, int level, String name, org.locationtech.jts.geom.Geometry geometry, RocksBatchWriter boundariesWriter, RocksDB gridsIndexDb) throws Exception { + private void storeBoundary(long osmId, int level, String name, String code, org.locationtech.jts.geom.Geometry geometry, RocksBatchWriter boundariesWriter, RocksDB gridsIndexDb) throws Exception { FlatBufferBuilder fbb = new FlatBufferBuilder(1024); byte[] wkb = new WKBWriter().write(geometry); int geomDataOffset = Geometry.createDataVector(fbb, wkb); @@ -1290,10 +1292,12 @@ private void storeBoundary(long osmId, int level, String name, org.locationtech. Coordinate center = mic.getCenter().getCoordinate(); double offset = radius / Math.sqrt(2); int nameOffset = fbb.createString(name != null ? name : "Unknown"); + int codeOffset = fbb.createString(code != null ? code : ""); Boundary.startBoundary(fbb); Boundary.addOsmId(fbb, osmId); Boundary.addLevel(fbb, level); Boundary.addName(fbb, nameOffset); + Boundary.addCode(fbb, codeOffset); Boundary.addMinX(fbb, mbr.getMinX()); Boundary.addMinY(fbb, mbr.getMinY()); Boundary.addMaxX(fbb, mbr.getMaxX()); @@ -1483,7 +1487,7 @@ private record NameData(String lang, String text) { private record AddressData(String street, String houseNumber, String postcode, String city, String country) { } - private record BoundaryResultLite(long osmId, int level, String name, org.locationtech.jts.geom.Geometry geometry) { + private record BoundaryResultLite(long osmId, int level, String name, String code, org.locationtech.jts.geom.Geometry geometry) { } private Long safeEntityId(EntityContainer container) { @@ -1610,6 +1614,7 @@ private static class RelRec { long osmId; int level; String name; + String code; long[] outer; long[] inner; } @@ -1664,6 +1669,7 @@ private RelRec buildRelRec(OsmRelation r) { } int level = 10; String name = null; + String code = null; for (int i = 0; i < r.getNumberOfTags(); i++) { OsmTag t = r.getTag(i); if ("admin_level".equals(t.getKey())) { @@ -1674,12 +1680,15 @@ private RelRec buildRelRec(OsmRelation r) { } } else if ("name".equals(t.getKey())) { name = t.getValue(); + } else if ("ISO3166-1".equals(t.getKey())) { + code = t.getValue(); } } RelRec rec = new RelRec(); rec.osmId = r.getId(); rec.level = level; rec.name = name; + rec.code = code; rec.outer = outer.stream().mapToLong(x -> x).toArray(); rec.inner = inner.stream().mapToLong(x -> x).toArray(); return rec; @@ -1746,10 +1755,16 @@ private PoiIndexRec decodePoiIndexRec(byte[] b) { private byte[] encodeRelRec(RelRec r) { byte[] nameB = bytes(r.name); - int cap = 4 + nameB.length + 4 + 8 * (r.outer != null ? r.outer.length : 0) + 4 + 8 * (r.inner != null ? r.inner.length : 0) + 4; + byte[] codeB = bytes(r.code); + int cap = 4 // level (was missing!) + + 4 + nameB.length // name length + data + + 4 + codeB.length // code length + data + + 4 + 8 * (r.outer != null ? r.outer.length : 0) // outer count + data + + 4 + 8 * (r.inner != null ? r.inner.length : 0); // inner count + data ByteBuffer bb = ByteBuffer.allocate(cap); bb.putInt(r.level); putBytes(bb, nameB); + putBytes(bb, codeB); bb.putInt(r.outer != null ? r.outer.length : 0); if (r.outer != null) for (long v : r.outer) bb.putLong(v); bb.putInt(r.inner != null ? r.inner.length : 0); @@ -1763,6 +1778,7 @@ private RelRec decodeRelRec(byte[] b, long id) { r.osmId = id; r.level = bb.getInt(); r.name = getString(bb); + r.code = getString(bb); int oc = bb.getInt(); r.outer = new long[oc]; for (int i = 0; i < oc; i++) r.outer[i] = bb.getLong();