From f1bad89ca61df0dc06b1304f147cf1c35d54803f Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 30 Oct 2020 06:42:01 +0100 Subject: [PATCH] Improve Geonames support. --- .../argeo/support/geonames/GeonamesAdm.java | 76 +++++++++++++++---- .../support/geonames/ImportGeonamesAdmin.java | 55 +++++++------- 2 files changed, 87 insertions(+), 44 deletions(-) diff --git a/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/GeonamesAdm.java b/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/GeonamesAdm.java index ff1de75..d578272 100644 --- a/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/GeonamesAdm.java +++ b/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/GeonamesAdm.java @@ -2,37 +2,47 @@ package org.argeo.support.geonames; import java.time.LocalDate; import java.time.ZoneId; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; +import java.util.function.Function; /** A Geonames administrative subdivision. */ public class GeonamesAdm { - private Long geonameId; - private String countryCode; - private String admLevel; - private Integer level; - private String name; - private String asciiName; - private List alternateNames; - private Double lat; - private Double lng; - private LocalDate lastUpdated; - private ZoneId timeZone; + private final Long geonameId; + private final String countryCode; + private final String adminCode1; + private final String admLevel; + private final Integer level; + private final String name; + private final String asciiName; + private final List alternateNames; + private final Double lat; + private final Double lng; + private final LocalDate lastUpdated; + private final ZoneId timeZone; + + private final Long[] upperLevelIds = new Long[5]; + private final List upperLevels = new ArrayList<>(); private List row; - public GeonamesAdm() { - } - /** Initialise from a row in the main Geonames table. */ public GeonamesAdm(List row) { geonameId = Long.parseLong(row.get(0)); admLevel = row.get(7); countryCode = row.get(8); - if (admLevel.startsWith("ADM") && !admLevel.endsWith("H")) { - level = Integer.parseInt(admLevel.substring(3)); + adminCode1 = row.get(10); + if (admLevel.startsWith("ADM")) { + if (admLevel.endsWith("H")) + level = Integer.parseInt(admLevel.substring(3, admLevel.length() - 1)); + else + level = Integer.parseInt(admLevel.substring(3)); } else if (admLevel.equals("PCLI")) { level = 0; + } else { + throw new IllegalArgumentException("Unsupported admin level " + admLevel); } name = row.get(1); asciiName = row.get(2); @@ -41,9 +51,23 @@ public class GeonamesAdm { lng = Double.parseDouble(row.get(5)); lastUpdated = LocalDate.parse(row.get(18)); timeZone = ZoneId.of(row.get(17)); + // upper levels + if (row.get(11) != null && !row.get(11).trim().equals("")) + upperLevelIds[2] = Long.parseLong(row.get(11)); + if (row.get(12) != null && !row.get(12).trim().equals("")) + upperLevelIds[3] = Long.parseLong(row.get(12)); + if (row.get(13) != null && !row.get(13).trim().equals("")) + upperLevelIds[4] = Long.parseLong(row.get(13)); this.row = row; } + public void mapUpperLevels(Map index) { + for (int i = 0; i < level; i++) { + Long geonameId = upperLevelIds[i]; + upperLevels.add(i, index.get(geonameId)); + } + } + public Long getGeonameId() { return geonameId; } @@ -56,6 +80,14 @@ public class GeonamesAdm { return name; } + public String getName(Function transform) { + if (transform != null) + return transform.apply(name); + else + return name; + + } + public String getAsciiName() { return asciiName; } @@ -92,6 +124,18 @@ public class GeonamesAdm { return timeZone; } + public String getAdminCode1() { + return adminCode1; + } + + public Long[] getUpperLevelIds() { + return upperLevelIds; + } + + public List getUpperLevels() { + return upperLevels; + } + @Override public int hashCode() { return geonameId.intValue(); diff --git a/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/ImportGeonamesAdmin.java b/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/ImportGeonamesAdmin.java index 1801fef..9af5987 100644 --- a/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/ImportGeonamesAdmin.java +++ b/knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/ImportGeonamesAdmin.java @@ -20,6 +20,8 @@ public class ImportGeonamesAdmin { /** Loads the data. */ public void parse(InputStream in) { + Map countryGeonameIds = new HashMap<>(); + Map admin1GeonameIds = new HashMap<>(); CsvParser csvParser = new CsvParser() { @Override @@ -28,27 +30,24 @@ public class ImportGeonamesAdmin { return; GeonamesAdm geonamesAdm = new GeonamesAdm(tokens); geonamesAdms.put(geonamesAdm.getGeonameId(), geonamesAdm); -// String featureName = tokens.get(7); -// String geonameId = tokens.get(0); -// String name = tokens.get(1); -// Double lat = Double.parseDouble(tokens.get(4)); -// Double lng = Double.parseDouble(tokens.get(5)); -// switch (featureName) { -// case "ADM1": -// case "ADM4": -// String adminCode1 = tokens.get(10); -// System.out.println( -// geonameId + " " + featureName + " " + lat + "," + lng + " " + adminCode1 + " " + name); -// break; -// default: -// break; -// } - + if (geonamesAdm.getAdmLevel().equals("PCLI")) + countryGeonameIds.put(geonamesAdm.getCountryCode(), geonamesAdm.getGeonameId()); + if (geonamesAdm.getAdmLevel().equals("ADM1")) + admin1GeonameIds.put(geonamesAdm.getAdminCode1(), geonamesAdm.getGeonameId()); } }; csvParser.setSeparator('\t'); csvParser.setNoHeader(true); csvParser.parse(in, StandardCharsets.UTF_8); + + // fill upper levels + for (GeonamesAdm adm : geonamesAdms.values()) { + adm.getUpperLevelIds()[0] = countryGeonameIds.get(adm.getCountryCode()); + if (adm.getLevel() > 0) + adm.getUpperLevelIds()[1] = admin1GeonameIds.get(adm.getAdminCode1()); + adm.mapUpperLevels(geonamesAdms); + } + } public Map getGeonamesAdms() { @@ -76,19 +75,19 @@ public class ImportGeonamesAdmin { } public static void main(String[] args) throws IOException { - String country = "allCountries"; - // String country = "CI"; - try (InputStream in = Files - .newInputStream(Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + ".txt")); - OutputStream out = Files.newOutputStream( - Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + "-adm.txt"))) { - ImportGeonamesAdmin.filterGeonamesAdm(in, out); - } -// try (InputStream in = Files.newInputStream( -// Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + "-adm.txt"))) { -// ImportGeonamesAdmin importGeonamesAdmin = new ImportGeonamesAdmin(); -// importGeonamesAdmin.parse(in); +// String country = "allCountries"; + String country = "CI"; +// try (InputStream in = Files +// .newInputStream(Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + ".txt")); +// OutputStream out = Files.newOutputStream( +// Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + "-adm.txt"))) { +// ImportGeonamesAdmin.filterGeonamesAdm(in, out); // } + try (InputStream in = Files.newInputStream( + Paths.get(System.getProperty("user.home") + "/gis/data/geonames/" + country + "-adm.txt"))) { + ImportGeonamesAdmin importGeonamesAdmin = new ImportGeonamesAdmin(); + importGeonamesAdmin.parse(in); + } } } -- 2.30.2