Up to now the names of the countries were taken from the
LocatorConfig.xml file no matter what has been configured in the
name-tag-list option.
But the name-tag-list option was used to get the country names from the
precompiled bounds which causes a problem if country name in the special
language is not contained in the LocatorConfig.xml.
The patch now uses the name-tag-list consistently for all places where
country names are standardized.
Additionally the values in the LocatorConfig.xml are automatically
completed by all name tags of the precompiled boundaries.
http://files.mkgmap.org.uk/detail/37 links to r2047 including this patch.
WanMil
Index: src/uk/me/parabola/mkgmap/reader/osm/LocationHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/LocationHook.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/reader/osm/LocationHook.java (working copy)
@@ -15,7 +15,6 @@
import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@@ -34,6 +33,7 @@
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.build.Locator;
+import uk.me.parabola.mkgmap.build.LocatorUtil;
import uk.me.parabola.mkgmap.reader.osm.boundary.Boundary;
import uk.me.parabola.mkgmap.reader.osm.boundary.BoundaryUtil;
import uk.me.parabola.util.ElementQuadTree;
@@ -45,13 +45,11 @@
private ElementSaver saver;
private final List<String> nameTags = new ArrayList<String>();
- private final Locator locator = new Locator();
+ private Locator locator;
private final Set<String> autofillOptions = new HashSet<String>();
private File boundaryDir;
- private static final Pattern COMMA_OR_SPACE_PATTERN = Pattern
- .compile("[,\\s]+");
private static final Pattern COMMA_OR_SEMICOLON_PATTERN = Pattern
.compile("[,;]+");
@@ -80,17 +78,18 @@
return false;
}
+ this.locator = new Locator(props);
+
this.saver = saver;
- autofillOptions.addAll(Locator.parseAutofillOption(props.getProperty("location-autofill", "bounds")));
+ autofillOptions.addAll(LocatorUtil.parseAutofillOption(props));
if (autofillOptions.isEmpty()) {
log.info("Disable LocationHook because no location-autofill option set.");
return false;
}
- String nameTagProp = props.getProperty("name-tag-list", "name");
- nameTags.addAll(Arrays.asList(COMMA_OR_SPACE_PATTERN.split(nameTagProp)));
+ nameTags.addAll(LocatorUtil.getNameTags(props));
if (autofillOptions.contains(BOUNDS_OPTION)) {
@@ -165,15 +164,11 @@
}
if ("2".equals(b.getTags().get("admin_level"))) {
- log.info("Input country: " + name);
- String lowercaseName = name;
- name = locator.fixCountryString(name);
- log.info("Fixed country: " + name);
- String cCode = locator.getCountryCode(name);
- if (cCode != null) {
- name = cCode;
+ String isoCode = locator.addCountry(b.getTags());
+ if (isoCode != null) {
+ name = isoCode;
} else {
- log.error("Country name "+lowercaseName+" not in locator config. Country may not be assigned correctly.");
+ log.error("Country name "+name+" not in locator config. Country may not be assigned correctly.");
}
log.info("Coded: " + name);
}
@@ -400,7 +395,30 @@
}
+ /**
+ * These tags are used to retrieve the name of admin_level=2 boundaries. They need to
+ * be handled special because their name is changed to the 3 letter ISO code using
+ * the Locator class and the LocatorConfig.xml file.
+ */
+ private static final String[] LEVEL2_NAMES = new String[]{"name","name:en","int_name"};
+
private String getName(Tags tags) {
+ if ("2".equals(tags.get("admin_level"))) {
+ for (String enNameTag : LEVEL2_NAMES)
+ {
+ String nameTagValue = tags.get(enNameTag);
+ if (nameTagValue == null) {
+ continue;
+ }
+
+ String[] nameParts = COMMA_OR_SEMICOLON_PATTERN.split(nameTagValue);
+ if (nameParts.length == 0) {
+ continue;
+ }
+ return nameParts[0].trim().intern();
+ }
+ }
+
for (String nameTag : nameTags) {
String nameTagValue = tags.get(nameTag);
if (nameTagValue == null) {
Index: src/uk/me/parabola/mkgmap/build/MapBuilder.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/MapBuilder.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/build/MapBuilder.java (working copy)
@@ -100,7 +100,7 @@
private boolean doRoads;
- private final Locator locator = new Locator();
+ private Locator locator;
private final java.util.Map<String, Highway> highways = new HashMap<String, Highway>();
@@ -128,10 +128,11 @@
public MapBuilder() {
regionName = null;
+ locator = new Locator();
}
public void config(EnhancedProperties props) {
-
+
countryName = props.getProperty("country-name", countryName);
countryAbbr = props.getProperty("country-abbr", countryAbbr);
regionName = props.getProperty("region-name", null);
@@ -153,7 +154,7 @@
routeCenterBoundaryType = props.getProperty("route-center-boundary", 0);
- locator.setLocationAutofill(Locator.parseAutofillOption(props.getProperty("location-autofill", "bounds")));
+ locator = new Locator(props);
}
/**
@@ -255,12 +256,12 @@
String countryStr = p.getCountry();
if (countryStr != null) {
- countryStr = locator.fixCountryString(countryStr);
+ countryStr = locator.normalizeCountry(countryStr);
p.setCountry(countryStr);
}
if(countryStr != null) {
- thisCountry = lbl.createCountry(countryStr, locator.getCountryCode(countryStr));
+ thisCountry = lbl.createCountry(countryStr, locator.getCountryISOCode(countryStr));
} else
thisCountry = getDefaultCountry();
@@ -293,7 +294,7 @@
String cityName = line.getCity();
String cityCountryName = line.getCountry();
if (cityCountryName != null) {
- cityCountryName = locator.fixCountryString(cityCountryName);
+ cityCountryName = locator.normalizeCountry(cityCountryName);
line.setCountry(cityCountryName);
}
String cityRegionName = line.getRegion();
@@ -319,7 +320,7 @@
if(cityName != null) {
- Country cc = (cityCountryName == null)? getDefaultCountry() : lbl.createCountry(cityCountryName, locator.getCountryCode(cityCountryName));
+ Country cc = (cityCountryName == null)? getDefaultCountry() : lbl.createCountry(cityCountryName, locator.getCountryISOCode(cityCountryName));
Region cr = (cityRegionName == null)? getDefaultRegion() : lbl.createRegion(cc, cityRegionName, null);
@@ -362,7 +363,7 @@
String cityStr = p.getCity();
if(countryStr != null)
- countryStr = locator.fixCountryString(countryStr);
+ countryStr = locator.normalizeCountry(countryStr);
if(countryStr == null || regionStr == null || (zipStr == null && cityStr == null))
{
@@ -415,7 +416,7 @@
Country thisCountry;
if(countryStr != null)
- thisCountry = lbl.createCountry(countryStr, locator.getCountryCode(countryStr));
+ thisCountry = lbl.createCountry(countryStr, locator.getCountryISOCode(countryStr));
else
thisCountry = getDefaultCountry();
Index: src/uk/me/parabola/mkgmap/build/Locator.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/Locator.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/build/Locator.java (working copy)
@@ -1,68 +1,28 @@
/*
- * Copyright (C) 2009 Bernhard Heibler
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program 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 General Public License for more details.
- *
- * The Locator tries to fill missing country, region, postal code information
- *
- * The algorithm works like this:
+ * Copyright (C) 2006, 2011.
*
- * 1. Step: Go through all cities an check if they have useful country region info
- * The best case is if the tags is_in:country and is_in:county are present that's easy.
- * Some cities have is_in information that can be used. We check for three different
- * formats:
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
*
- * County, State, Country, Continent
- * County, State, Country
- * Continent, Country, State, County, ...
- *
- * In "openGeoDb countries" this info is pretty reliable since it was imported from a
- * external db into osm. Other countries have very sparse is_in info.
- *
- * All this cities that have such info will end up in "city" list. All which lack
- * such information in "location" list.
- *
- * 2. Step: Go through the "location" list and check if the is_in info has some relations
- * to the cities we have info about.
- *
- * Especially hamlets often have no full is_in information. They only have one entry in
- * is_in that points to the city they belong to. I will check if I can find the name
- * of this city in the "City" list. If there are more with the same name I use the
- * closest one. If we can't find the exact name I use fuzzy name search. That's a
- * workaround for german umlaut since sometimes there are used in the tags and
- * sometimes there are written as ue ae oe.
- *
- * 3. Step: Do the same like in step 2 once again. This is used to support at least
- * one level of recursion in is_in relations.
- *
- * If there is still no info found I use brute force and use the information from the
- * next city. Has to be used for countries with poor is_in tagging.
- *
- * Author: Bernhard Heibler
- * Create date: 02-Jan-2009
+ * This program 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
+ * General Public License for more details.
*/
-
package uk.me.parabola.mkgmap.build;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import java.util.regex.Pattern;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.general.MapPoint;
import uk.me.parabola.mkgmap.general.MapPointFastFindMap;
+import uk.me.parabola.mkgmap.reader.osm.Tags;
+import uk.me.parabola.util.EnhancedProperties;
public class Locator {
private static final Logger log = Logger.getLogger(Locator.class);
@@ -70,53 +30,23 @@
private final MapPointFastFindMap cityMap = new MapPointFastFindMap();
private final List<MapPoint> placesMap = new ArrayList<MapPoint>();
+ /** Contains the tags defined by the option name-tag-list */
+ private final List<String> nameTags;
+
private final LocatorConfig locConfig = LocatorConfig.get();
- private final Set<String> locationAutofill = new HashSet<String>();
+ private final Set<String> locationAutofill;
private static final double MAX_CITY_DIST = 30000;
- private static final Pattern COMMA_OR_SPACE_PATTERN = Pattern.compile("[,\\s]+");
-
- /**
- * Parses the parameters of the location-autofill option. Establishes also downwards
- * compatibility with the old integer values of location-autofill.
- * @param optionStr the value of location-autofill
- * @return the options
- */
- public static Set<String> parseAutofillOption(String optionStr) {
- if (optionStr == null) {
- return Collections.emptySet();
- }
-
- Set<String> autofillOptions = new HashSet<String>(Arrays.asList(COMMA_OR_SPACE_PATTERN
- .split(optionStr)));
-
- // convert the old autofill options to the new parameters
- if (autofillOptions.contains("0")) {
- autofillOptions.add("is_in");
- autofillOptions.remove("0");
- }
- if (autofillOptions.contains("1")) {
- autofillOptions.add("is_in");
- // PENDING: fuzzy search
- autofillOptions.remove("1");
- }
- if (autofillOptions.contains("2")) {
- autofillOptions.add("is_in");
- // PENDING: fuzzy search
- autofillOptions.add("nearest");
- autofillOptions.remove("2");
- }
- if (autofillOptions.contains("3")) {
- autofillOptions.add("is_in");
- // PENDING: fuzzy search
- autofillOptions.add("nearest");
- autofillOptions.remove("3");
- }
- return autofillOptions;
+ public Locator() {
+ this(new EnhancedProperties());
}
+ public Locator(EnhancedProperties props) {
+ this.nameTags = LocatorUtil.getNameTags(props);
+ this.locationAutofill = new HashSet<String>(LocatorUtil.parseAutofillOption(props));
+ }
public void addCityOrPlace(MapPoint p)
{
@@ -131,7 +61,7 @@
// correct the country name
// usually this is the translation from 3letter ISO code to country name
if(p.getCountry() != null)
- p.setCountry(fixCountryString(p.getCountry()));
+ p.setCountry(normalizeCountry(p.getCountry()));
resolveIsInInfo(p); // Pre-process the is_in field
@@ -150,34 +80,51 @@
log.debug("E City 0x"+Integer.toHexString(p.getType()), p.getName(), "|", p.getCity(), "|", p.getRegion(), "|", p.getCountry());
}
-
- public void setLocationAutofill(Collection<String> autofillOptions) {
- this.locationAutofill.addAll(autofillOptions);
- }
-
public void setDefaultCountry(String country, String abbr)
{
locConfig.setDefaultCountry(country, abbr);
}
-
- public String fixCountryString(String country)
+
+ public String normalizeCountry(String country)
{
- return locConfig.fixCountryString(country);
+ if (country == null) {
+ return null;
+ }
+
+ String iso = locConfig.getCountryISOCode(country);
+ if (iso != null) {
+ String normedCountryName = locConfig.getCountryName(iso, nameTags);
+ if (normedCountryName != null) {
+ return normedCountryName;
+ }
+ }
+
+ // cannot find the country in our config => return the country itself
+ return country;
}
- private String isCountry(String country)
+ /**
+ * Checks if the country given by attached tags is already known, adds or completes
+ * the Locator information about this country and return the three letter ISO code
+ * (in case the country is known in the LocatorConfig.xml) or the country name.
+ *
+ * @param tags the countries tags
+ * @return the three letter ISO code or <code>null</code> if ISO code is unknown
+ */
+ public String addCountry(Tags tags)
{
- return locConfig.isCountry(country);
+ return locConfig.addCountryWithTags(tags);
}
+
- public String getCountryCode(String country)
+ public String getCountryISOCode(String country)
{
- return locConfig.getCountryCode(country);
+ return locConfig.getCountryISOCode(country);
}
public int getPOIDispFlag(String country)
{
- return locConfig.getPoiDispFlag(country);
+ return locConfig.getPoiDispFlag(getCountryISOCode(country));
}
private boolean isContinent(String continent)
@@ -216,11 +163,11 @@
{
if (p.getCountry() == null) {
// The one before continent should be the country
- p.setCountry(fixCountryString(cityList[cityList.length-2].trim()));
+ p.setCountry(normalizeCountry(cityList[cityList.length-2].trim()));
}
// aks the config which info to use for region info
- int offset = locConfig.getRegionOffset(p.getCountry()) + 1;
+ int offset = locConfig.getRegionOffset(getCountryISOCode(p.getCountry())) + 1;
if(cityList.length > offset && p.getRegion() == null)
p.setRegion(cityList[cityList.length-(offset+1)].trim());
@@ -233,10 +180,10 @@
{
if (p.getCountry() == null) {
// The one before continent should be the country
- p.setCountry(fixCountryString(cityList[1].trim()));
+ p.setCountry(normalizeCountry(cityList[1].trim()));
}
- int offset = locConfig.getRegionOffset(p.getCountry()) + 1;
+ int offset = locConfig.getRegionOffset(getCountryISOCode(p.getCountry())) + 1;
if(cityList.length > offset && p.getRegion() == null)
p.setRegion(cityList[offset].trim());
@@ -247,14 +194,12 @@
if(p.getCountry() == null && cityList.length > 0)
{
// I don't like to check for a list of countries but I don't want other stuff in country field
-
- String countryStr = isCountry(cityList[cityList.length-1]);
-
- if(countryStr != null)
+ String isoCode = locConfig.getCountryISOCode(cityList[cityList.length-1]);
+ if (isoCode != null)
{
- p.setCountry(countryStr);
+ p.setCountry(normalizeCountry(isoCode));
- int offset = locConfig.getRegionOffset(countryStr) + 1;
+ int offset = locConfig.getRegionOffset(isoCode) + 1;
if(cityList.length > offset && p.getRegion() == null)
p.setRegion(cityList[cityList.length-(offset+1)].trim());
Index: src/uk/me/parabola/mkgmap/build/LocatorConfig.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/LocatorConfig.java (revision 2047)
+++ src/uk/me/parabola/mkgmap/build/LocatorConfig.java (working copy)
@@ -1,45 +1,49 @@
/*
- * Copyright (C) 2009 Bernhard Heibler
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This program 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 General Public License for more details.
- *
- * The Locator tries to fill missing country, region, postal code information
+ * Copyright (C) 2006, 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
*
- * To do so we analyse the is_in information and if this doesn't helps us we
- * try to get info from the next known city
- *
- * Author: Bernhard Heibler
- * Create date: 02-Jan-2009
+ * This program 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
+ * General Public License for more details.
*/
package uk.me.parabola.mkgmap.build;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
+import java.util.Map.Entry;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.reader.osm.Tags;
+
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
public class LocatorConfig {
+ private static final Logger log = Logger.getLogger(LocatorConfig.class);
- private final Map<String,String> variantMap = new HashMap<String,String>();
- private final Map<String,String> abrMap = new HashMap<String,String>();
+ private final Map<String,String> isoMap = new HashMap<String,String>();
private final Map<String,Integer> regOffsetMap = new HashMap<String,Integer>();
private final Map<String,Integer> poiDispFlagMap = new HashMap<String,Integer>();
private final Map<String,Boolean> continentMap = new HashMap<String,Boolean>();
+ /** maps ISO => default country name */
+ private final Map<String, String> defaultCountryNames = new HashMap<String, String>();
+
+ /** Maps 3 letter ISO code to all tags of a country */
+ private final Map<String, Tags> countryTagMap = new HashMap<String, Tags>();
+
private final static LocatorConfig instance = new LocatorConfig();
public static LocatorConfig get() {
@@ -98,46 +102,59 @@
{
NamedNodeMap attr = cNode.getAttributes();
Node nameTag = null;
-
+ Node abrTag = attr.getNamedItem("abr");
+ String iso = null;
+ if (abrTag != null) {
+ iso = abrTag.getNodeValue().toUpperCase().trim().intern();
+ if (iso.length() != 3) {
+ log.error("ISO code (abr) must have three characters: "+iso);
+ }
+ }
+
if(attr != null)
{
nameTag = attr.getNamedItem("name");
- Node abrTag = attr.getNamedItem("abr");
-
- if(abrTag != null && nameTag != null)
- addAbr(nameTag.getNodeValue(),abrTag.getNodeValue());
+ if(iso != null && nameTag != null) {
+ addISO(nameTag.getNodeValue(),iso);
+ defaultCountryNames.put(iso, nameTag.getNodeValue().trim());
+ }
+
+ if (iso != null)
+ addISO(iso, iso);
- if(abrTag == null && nameTag != null)
- addAbr(nameTag.getNodeValue(),"");
+ if(iso == null && nameTag != null)
+ addISO(nameTag.getNodeValue(),"");
+
Node regionOffsetTag = attr.getNamedItem("regionOffset");
- if(regionOffsetTag != null && nameTag != null)
+ if(regionOffsetTag != null && iso != null)
{
- addRegionOffset(nameTag.getNodeValue(),Integer.parseInt(regionOffsetTag.getNodeValue()));
+ addRegionOffset(iso,Integer.parseInt(regionOffsetTag.getNodeValue()));
}
Node poiDispTag = attr.getNamedItem("poiDispFlag");
- if(poiDispTag != null && nameTag != null)
+ if(poiDispTag != null && iso != null)
{
- addPoiDispTag(nameTag.getNodeValue(),Integer.decode(poiDispTag.getNodeValue()));
+ addPoiDispTag(iso,Integer.decode(poiDispTag.getNodeValue()));
}
}
- Node cEntryNode = cNode.getFirstChild();
- while(cEntryNode != null)
- {
- if(cEntryNode.getNodeName().equals("variant"))
+ if (iso != null) {
+ Node cEntryNode = cNode.getFirstChild();
+ while(cEntryNode != null)
{
- Node nodeText = cEntryNode.getFirstChild();
-
- if(nodeText != null && nameTag != null)
- addVariant(nameTag.getNodeValue(), nodeText.getNodeValue());
-
+ if(cEntryNode.getNodeName().equals("variant"))
+ {
+ Node nodeText = cEntryNode.getFirstChild();
+
+ if (nodeText != null)
+ addISO(nodeText.getNodeValue(), iso);
+ }
+ cEntryNode = cEntryNode.getNextSibling();
}
- cEntryNode = cEntryNode.getNextSibling();
}
}
@@ -156,34 +173,21 @@
}
}
- private void addVariant(String country, String variant)
- {
- String cStr = country.toUpperCase().trim();
- String vStr = variant.toUpperCase().trim();
-
- variantMap.put(vStr,cStr);
- }
-
- private void addAbr(String country, String abr)
+ private void addISO(String country, String iso)
{
String cStr = country.toUpperCase().trim();
- String aStr = abr.toUpperCase().trim();
- abrMap.put(cStr,aStr);
+ isoMap.put(cStr,iso);
}
- private void addRegionOffset(String country, Integer offset)
+ private void addRegionOffset(String iso, Integer offset)
{
- String cStr = country.toUpperCase().trim();
-
- regOffsetMap.put(cStr,offset);
+ regOffsetMap.put(iso,offset);
}
- private void addPoiDispTag(String country, Integer flag)
+ private void addPoiDispTag(String iso, Integer flag)
{
- String cStr = country.toUpperCase().trim();
-
- poiDispFlagMap.put(cStr,flag);
+ poiDispFlagMap.put(iso,flag);
}
private void addContinent(String continent)
@@ -196,43 +200,119 @@
public synchronized void setDefaultCountry(String country, String abbr)
{
- addAbr(country, abbr);
+ addISO(country, abbr);
}
- public synchronized String fixCountryString(String country)
+ public synchronized boolean isCountry(String country)
{
- String cStr = country.toUpperCase().trim();
+ return isoMap.containsKey(country.toUpperCase().trim());
+ }
+
+ private final static String[] PREFERRED_NAME_TAGS = {"name","name:en","int_name"};
+
+ public synchronized String addCountryWithTags(Tags countryTags) {
+ String isoCode = null;
+ for (String nameTag : PREFERRED_NAME_TAGS) {
+ String nameValue = countryTags.get(nameTag);
+ isoCode = getCountryISOCode(nameValue);
+ if (isoCode != null) {
+ break;
+ }
+ }
- String fixedString = variantMap.get(cStr);
-
- if(fixedString != null)
- return fixedString;
- else
- return(cStr);
+ if (isoCode == null) {
+ for (String countryStr : countryTags.getTagsWithPrefix("name:", false).values()) {
+ isoCode = getCountryISOCode(countryStr);
+ if (isoCode != null) {
+ break;
+ }
+ }
+ }
+
+ if (isoCode == null) {
+ // cannot find three letter iso code for this countries
+ // do not use it
+ log.warn("Cannot find country with tags", countryTags);
+ return null;
+ }
+
+ if (countryTagMap.containsKey(isoCode)) {
+ // country is already known
+ return isoCode;
+ }
+
+ // add it as new country to the tag map
+ Tags cTagsCopy = new Tags();
+ Iterator<Entry<String,String>> tagIter = countryTags.entryIterator();
+ while (tagIter.hasNext()) {
+ Entry<String,String> nextTag = tagIter.next();
+ cTagsCopy.put(nextTag.getKey(), nextTag.getValue());
+ }
+ countryTagMap.put(isoCode, cTagsCopy);
+
+ String name = countryTags.get("name");
+ if (name != null) {
+ addISO(name, isoCode);
+ }
+ String int_name = countryTags.get("int_name");
+ if (int_name != null) {
+ addISO(int_name, isoCode);
+ }
+ // add all variants to the abbreviation map
+ for (String countryName : countryTags.getTagsWithPrefix("name:", false).values()) {
+ addISO(countryName, isoCode);
+ }
+ return isoCode;
}
- public synchronized String isCountry(String country)
+ /**
+ * Retrieves the three letter ISO code which is used by the Garmins.
+ * @param country a country name
+ * @return the three letter ISO code (<code>null</code> = unknown)
+ */
+ public synchronized String getCountryISOCode(String country)
{
- String cStr = fixCountryString(country);
-
- if(getCountryCode(cStr) != null)
- return cStr;
- else
+ if (country == null) {
return null;
-
+ }
+ return isoMap.get(country.toUpperCase().trim());
}
-
- public synchronized String getCountryCode(String country)
- {
- String cStr = country.toUpperCase().trim();
- return abrMap.get(cStr);
+
+ /**
+ * Retrieves the name of a country by its three letter iso code and the list of
+ * name tags. The first available value of the tags in the nameTags list is returned.
+ *
+ * @param isoCode the three letter ISO code
+ * @param nameTags the list of name tags
+ * @return the full country name (<code>null</code> if unknown)
+ */
+ public synchronized String getCountryName(String isoCode, List<String> nameTags) {
+ Tags countryTags = countryTagMap.get(isoCode);
+ if (countryTags==null) {
+ // no tags for this country available
+ // return the default country name from the LocatorConfig.xml
+ return defaultCountryNames.get(isoCode);
+ }
+
+ // search for the first available tag of the nameTags list
+ for (String nameTag : nameTags) {
+ String name = countryTags.get(nameTag);
+ if (name != null) {
+ return name;
+ }
+ }
+
+ // last try: just the simple "name" tag
+ return countryTags.get("name");
}
- public synchronized int getRegionOffset(String country)
+ public synchronized int getRegionOffset(String iso)
{
- String cStr = country.toUpperCase().trim();
+ if (iso == null) {
+ return 1;
+ }
- Integer regOffset = regOffsetMap.get(cStr);
+ Integer regOffset = regOffsetMap.get(iso);
if(regOffset != null)
return regOffset;
@@ -240,16 +320,18 @@
return 1; // Default is 1 the next string after before country
}
- public synchronized int getPoiDispFlag(String country)
+ public synchronized int getPoiDispFlag(String iso)
{
- String cStr = country.toUpperCase().trim();
+ if (iso == null) {
+ return 0;
+ }
- Integer flag = poiDispFlagMap.get(cStr);
+ Integer flag = poiDispFlagMap.get(iso);
if(flag != null)
return flag;
else
- return 0; // Default is 1 the next string after before country
+ return 0; // Default is 0
}
public synchronized boolean isContinent(String continent)
Index: src/uk/me/parabola/mkgmap/build/LocatorUtil.java
===================================================================
--- src/uk/me/parabola/mkgmap/build/LocatorUtil.java (revision 0)
+++ src/uk/me/parabola/mkgmap/build/LocatorUtil.java (revision 0)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2006, 2011.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program 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
+ * General Public License for more details.
+ */
+package uk.me.parabola.mkgmap.build;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.regex.Pattern;
+
+import uk.me.parabola.util.EnhancedProperties;
+
+public class LocatorUtil {
+
+ private static final Pattern COMMA_OR_SPACE_PATTERN = Pattern
+ .compile("[,\\s]+");
+
+ public static List<String> getNameTags(EnhancedProperties props) {
+ String nameTagProp = props.getProperty("name-tag-list", "name");
+ return Arrays.asList(COMMA_OR_SPACE_PATTERN.split(nameTagProp));
+ }
+
+ /**
+ * Parses the parameters of the location-autofill option. Establishes also downwards
+ * compatibility with the old integer values of location-autofill.
+ * @param optionStr the value of location-autofill
+ * @return the options
+ */
+ public static Set<String> parseAutofillOption(EnhancedProperties props) {
+ String optionStr = props.getProperty("location-autofill", "bounds");
+ if (optionStr == null) {
+ return Collections.emptySet();
+ }
+
+ Set<String> autofillOptions = new HashSet<String>(Arrays.asList(COMMA_OR_SPACE_PATTERN
+ .split(optionStr)));
+
+ // convert the old autofill options to the new parameters
+ if (autofillOptions.contains("0")) {
+ autofillOptions.add("is_in");
+ autofillOptions.remove("0");
+ }
+ if (autofillOptions.contains("1")) {
+ autofillOptions.add("is_in");
+ // PENDING: fuzzy search
+ autofillOptions.remove("1");
+ }
+ if (autofillOptions.contains("2")) {
+ autofillOptions.add("is_in");
+ // PENDING: fuzzy search
+ autofillOptions.add("nearest");
+ autofillOptions.remove("2");
+ }
+ if (autofillOptions.contains("3")) {
+ autofillOptions.add("is_in");
+ // PENDING: fuzzy search
+ autofillOptions.add("nearest");
+ autofillOptions.remove("3");
+ }
+ return autofillOptions;
+ }
+}
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev