Improve Geonames support.
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 30 Oct 2020 05:42:01 +0000 (06:42 +0100)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 30 Oct 2020 05:42:01 +0000 (06:42 +0100)
knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/GeonamesAdm.java
knowledge/org.argeo.support.geonames/src/org/argeo/support/geonames/ImportGeonamesAdmin.java

index ff1de7500fdc4b405a179ba1984eb60ea0e65cf8..d57827219fd8f04b5d709a3e98a05245682c813a 100644 (file)
@@ -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<String> 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<String> 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<GeonamesAdm> upperLevels = new ArrayList<>();
 
        private List<String> row;
 
-       public GeonamesAdm() {
-       }
-
        /** Initialise from a row in the main Geonames table. */
        public GeonamesAdm(List<String> 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<Long, GeonamesAdm> 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<String, String> 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<GeonamesAdm> getUpperLevels() {
+               return upperLevels;
+       }
+
        @Override
        public int hashCode() {
                return geonameId.intValue();
index 1801fefef3e4ea47b3e875666dbbc170c98db4b9..9af5987fa98a945176d3a6b6951dfeef3a8cd9a5 100644 (file)
@@ -20,6 +20,8 @@ public class ImportGeonamesAdmin {
 
        /** Loads the data. */
        public void parse(InputStream in) {
+               Map<String, Long> countryGeonameIds = new HashMap<>();
+               Map<String, Long> 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<Long, GeonamesAdm> 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);
+               }
        }
 
 }