/*******************************************************************************
* Gisgraphy Project
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
*
* Copyright 2008 Gisgraphy project
* David Masclet <davidmasclet@gisgraphy.com>
*
*
*******************************************************************************/
package com.gisgraphy.importer;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_AND_ADM1CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_AND_ADM2CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_AND_ADM3CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_AND_ADM4CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_AND_ADM5CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_OR_ADM1CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_OR_ADM2CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_OR_ADM3CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_OR_ADM4CODE;
import static com.gisgraphy.importer.MunicipalityDetector.MunicipalityDetectionStrategy.POPULATION_OR_ADM5CODE;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.gisgraphy.domain.geoloc.entity.GisFeature;
import com.gisgraphy.domain.valueobject.GISSource;
/**
* @author david masclet
* geonames classify features with some code. there is no real definition of City. city are populated place
* without any distinction. this class try to detect if the place is a city. to do this we search for population administrative division code (one or the other or both
* and apply a strategy depends on country. for each country we have search for the number of city and search what is the best fields to look to see if it is a city.
* e.g : for France there is about 36000 city. in geonames there is about 58000 place. if we look at the adm4 code and the population (both) we identify 36875 city.
* <br/>
* it is not deterministic but probabilistic approach.if you got better idea to identify city, please let us know. This can seems tricky but this works well and improve geocoding
* when we fill the is_in fields,we have a city and not a quater)
*
*this code is for the moment replace by the osm conditionsthis seems to be more reliable, but we
*keep this code for some country specificities based on user feedbacks
*/
@Service
public class MunicipalityDetector implements IMunicipalityDetector {
public enum MunicipalityOSMDetectionStrategy{
ALL,
OSM,
R,//R and W
R_AND_N_CITY_VILLAGE_TOWN,// R and W
N,
N_CITY_VILLAGE_TOWN,
N_CITY_TOWN
}
public final static Map<String, MunicipalityOSMDetectionStrategy> countrycodeToCityOSMDetectionStrategy = new HashMap<String, MunicipalityDetector.MunicipalityOSMDetectionStrategy>(){
{
put("IT",MunicipalityOSMDetectionStrategy.R);
put("DE",MunicipalityOSMDetectionStrategy.R);
put("CN",MunicipalityOSMDetectionStrategy.OSM);
put("FR",MunicipalityOSMDetectionStrategy.R);
put("IN",MunicipalityOSMDetectionStrategy.ALL);
put("ID",MunicipalityOSMDetectionStrategy.N);
put("BR",MunicipalityOSMDetectionStrategy.R);
put("US",MunicipalityOSMDetectionStrategy.R);
put("LU",MunicipalityOSMDetectionStrategy.R);
put("AR",MunicipalityOSMDetectionStrategy.N);
put("SK",MunicipalityOSMDetectionStrategy.R_AND_N_CITY_VILLAGE_TOWN);
put("BE",MunicipalityOSMDetectionStrategy.OSM);
put("NG",MunicipalityOSMDetectionStrategy.ALL);
put("RU",MunicipalityOSMDetectionStrategy.ALL);
put("JP",MunicipalityOSMDetectionStrategy.R);
put("FI",MunicipalityOSMDetectionStrategy.OSM);
put("CA",MunicipalityOSMDetectionStrategy.ALL);
put("MX",MunicipalityOSMDetectionStrategy.OSM);
put("EG",MunicipalityOSMDetectionStrategy.ALL);
put("TR",MunicipalityOSMDetectionStrategy.N_CITY_VILLAGE_TOWN);
put("GB",MunicipalityOSMDetectionStrategy.ALL);
put("KR",MunicipalityOSMDetectionStrategy.N_CITY_TOWN);
put("SP",MunicipalityOSMDetectionStrategy.R);
put("UA",MunicipalityOSMDetectionStrategy.OSM);
put("CO",MunicipalityOSMDetectionStrategy.R);
put("PL",MunicipalityOSMDetectionStrategy.OSM);
put("DZ",MunicipalityOSMDetectionStrategy.ALL);
put("MA",MunicipalityOSMDetectionStrategy.R);
put("PE",MunicipalityOSMDetectionStrategy.R);
put("IQ",MunicipalityOSMDetectionStrategy.ALL);
put("TW",MunicipalityOSMDetectionStrategy.N_CITY_TOWN);
put("SY",MunicipalityOSMDetectionStrategy.R);
put("RO",MunicipalityOSMDetectionStrategy.OSM);
put("AT",MunicipalityOSMDetectionStrategy.R);
put("AU",MunicipalityOSMDetectionStrategy.ALL);
put("CL",MunicipalityOSMDetectionStrategy.ALL);
put("NL",MunicipalityOSMDetectionStrategy.R);
put("EC",MunicipalityOSMDetectionStrategy.R);
put("PT",MunicipalityOSMDetectionStrategy.OSM);
put("CZ",MunicipalityOSMDetectionStrategy.R);
put("BO",MunicipalityOSMDetectionStrategy.N);
put("HU",MunicipalityOSMDetectionStrategy.R);
put("BY",MunicipalityOSMDetectionStrategy.ALL);
put("SE",MunicipalityOSMDetectionStrategy.R);
put("CH",MunicipalityOSMDetectionStrategy.R);
put("IL",MunicipalityOSMDetectionStrategy.ALL);
put("BG",MunicipalityOSMDetectionStrategy.N);
put("PY",MunicipalityOSMDetectionStrategy.N);
put("DK",MunicipalityOSMDetectionStrategy.OSM);
put("NO",MunicipalityOSMDetectionStrategy.OSM);
put("HR",MunicipalityOSMDetectionStrategy.OSM);
put("NZ",MunicipalityOSMDetectionStrategy.N);
put("LT",MunicipalityOSMDetectionStrategy.ALL);
put("AL",MunicipalityOSMDetectionStrategy.N);
put("LV",MunicipalityOSMDetectionStrategy.ALL);
put("SI",MunicipalityOSMDetectionStrategy.R);
put("EE",MunicipalityOSMDetectionStrategy.ALL);
put("IS",MunicipalityOSMDetectionStrategy.ALL);
put("NC",MunicipalityOSMDetectionStrategy.ALL);
}
};
public boolean isMunicipality(String countryCode,String placetype,String nodeType,GISSource source){
if (countryCode==null || "".equals(countryCode)){
return true;
}
MunicipalityOSMDetectionStrategy strategy = countrycodeToCityOSMDetectionStrategy.get(countryCode.toUpperCase());
if (strategy == null || strategy == MunicipalityOSMDetectionStrategy.ALL){
return true;
}
if (source == GISSource.OSM){
if (strategy == MunicipalityOSMDetectionStrategy.OSM){
return true;
}
if ("R".equalsIgnoreCase(nodeType)|| "W".equalsIgnoreCase(nodeType)){
if (strategy == MunicipalityOSMDetectionStrategy.R || strategy == MunicipalityOSMDetectionStrategy.R_AND_N_CITY_VILLAGE_TOWN){
return true;
}
}
else if ("N".equalsIgnoreCase(nodeType) ){
if ( strategy == MunicipalityOSMDetectionStrategy.N){
return true;
}
if ( strategy == MunicipalityOSMDetectionStrategy.N_CITY_VILLAGE_TOWN || strategy == MunicipalityOSMDetectionStrategy.R_AND_N_CITY_VILLAGE_TOWN){
if ("city".equalsIgnoreCase(placetype) || "village".equalsIgnoreCase(placetype) || "town".equalsIgnoreCase(placetype)){
return true;
}
}
if (strategy == MunicipalityOSMDetectionStrategy.N_CITY_TOWN){
if ("city".equalsIgnoreCase(placetype) || "town".equalsIgnoreCase(placetype)){
return true;
}
}
}
}
return false;
}
/*---------------------------------------------GEONAMES ALGORYTHME--(Obsolete should be replaced by OSM ONE--------------------------*/
public final static Map<String, MunicipalityDetectionStrategy> countrycodeToCityDetectionStrategy = new HashMap<String, MunicipalityDetector.MunicipalityDetectionStrategy>(){
{
put("IT",MunicipalityDetectionStrategy.POPULATION);
put("DE",MunicipalityDetectionStrategy.ADM2CODE);
put("FR",MunicipalityDetectionStrategy.POPULATION_OR_ADM4CODE);
put("US",MunicipalityDetectionStrategy.POPULATION);
put("AR",MunicipalityDetectionStrategy.POPULATION);
put("BE",MunicipalityDetectionStrategy.POPULATION);
put("VN",MunicipalityDetectionStrategy.POPULATION_OR_ADM1CODE);
put("UK",MunicipalityDetectionStrategy.POPULATION);
put("TW",MunicipalityDetectionStrategy.POPULATION_OR_ADM2CODE);//maybe we should take all
put("RO",MunicipalityDetectionStrategy.POPULATION);
put("AU",MunicipalityDetectionStrategy.POPULATION);
/*put("",cityDetectionStrategy.POPULATION);
put("",cityDetectionStrategy.POPULATION);
put("",cityDetectionStrategy.POPULATION);
put("",cityDetectionStrategy.POPULATION);
put("",cityDetectionStrategy.POPULATION);
put("",cityDetectionStrategy.POPULATION);*/
}
};
/* (non-Javadoc)
* @see com.gisgraphy.importer.IMunicipalityDetector#isMunicipality(java.lang.String, com.gisgraphy.domain.geoloc.entity.GisFeature)
*/
public boolean isMunicipalityByGisFeature(String countrycode,GisFeature gisFeature ){
if (countrycode==null || "".equals(countrycode) || gisFeature ==null){
return false;
}
MunicipalityDetectionStrategy strategy = countrycodeToCityDetectionStrategy.get(countrycode.toUpperCase());
if (strategy == null){
return false;
}
else {
return isMunicipality_internal(strategy, gisFeature.getPopulation(), gisFeature.getAdm1Code(), gisFeature.getAdm2Code(), gisFeature.getAdm3Code(), gisFeature.getAdm4Code(), gisFeature.getAdm5Code());
}
}
public enum MunicipalityDetectionStrategy{
//0
NO_STRATEGY,
//1
POPULATION,
//2
ADM1CODE,
ADM2CODE,
ADM3CODE,
ADM4CODE,
ADM5CODE,
//3
POPULATION_OR_ADM1CODE,
POPULATION_OR_ADM2CODE,
POPULATION_OR_ADM3CODE,
POPULATION_OR_ADM4CODE,
POPULATION_OR_ADM5CODE,
//4
POPULATION_AND_ADM1CODE,
POPULATION_AND_ADM2CODE,
POPULATION_AND_ADM3CODE,
POPULATION_AND_ADM4CODE,
POPULATION_AND_ADM5CODE,
}
protected boolean isMunicipality_internal(MunicipalityDetectionStrategy strategy, Integer population, String adm1code, String adm2code, String adm3code, String adm4code, String adm5code) {
if (population != null && population!=0){//population is not null
if (strategy==MunicipalityDetectionStrategy.POPULATION || strategy ==POPULATION_OR_ADM1CODE || strategy == POPULATION_OR_ADM2CODE || strategy == POPULATION_OR_ADM3CODE || strategy == POPULATION_OR_ADM4CODE || strategy == POPULATION_OR_ADM5CODE){
return true;
} else if ((strategy== POPULATION_AND_ADM1CODE || strategy== MunicipalityDetectionStrategy.ADM1CODE ) && !isNullOrEmpty(adm1code)){
return true;
}
else if ((strategy== POPULATION_AND_ADM2CODE || strategy== MunicipalityDetectionStrategy.ADM2CODE ) && !isNullOrEmpty(adm2code)){
return true;
}
else if ((strategy== POPULATION_AND_ADM3CODE || strategy== MunicipalityDetectionStrategy.ADM3CODE ) && !isNullOrEmpty(adm3code)){
return true;
}
else if ((strategy== POPULATION_AND_ADM4CODE || strategy== MunicipalityDetectionStrategy.ADM4CODE ) && !isNullOrEmpty(adm4code)){
return true;
}
else if ((strategy== POPULATION_AND_ADM5CODE || strategy== MunicipalityDetectionStrategy.ADM5CODE ) && !isNullOrEmpty(adm5code)){
return true;
}
} else {//population is null
if (strategy==POPULATION_AND_ADM1CODE || strategy ==POPULATION_AND_ADM2CODE || strategy== POPULATION_AND_ADM3CODE ||strategy==POPULATION_AND_ADM4CODE || strategy ==POPULATION_AND_ADM5CODE){
return false;
} else if ((strategy== POPULATION_OR_ADM1CODE || strategy== MunicipalityDetectionStrategy.ADM1CODE )&& !isNullOrEmpty(adm1code)){
return true;
}
else if ((strategy== POPULATION_OR_ADM2CODE || strategy== MunicipalityDetectionStrategy.ADM2CODE ) && !isNullOrEmpty(adm2code)){
return true;
}
else if ((strategy== POPULATION_OR_ADM3CODE || strategy== MunicipalityDetectionStrategy.ADM3CODE ) && !isNullOrEmpty(adm3code)){
return true;
}
else if ((strategy== POPULATION_OR_ADM4CODE || strategy== MunicipalityDetectionStrategy.ADM4CODE )&& !isNullOrEmpty(adm4code)){
return true;
}
else if ((strategy== POPULATION_OR_ADM5CODE|| strategy== MunicipalityDetectionStrategy.ADM5CODE ) && !isNullOrEmpty(adm5code)){
return true;
}
}
return false;
}
private boolean isNullOrEmpty(String str){
return str==null || "".equals(str);
}
public boolean isCitySubdivision(String countryCode,int osmAdmLevel){
if (countryCode !=null){
countryCode = countryCode.toUpperCase();
} else {
return false;
}
if (osmAdmLevel<0 || osmAdmLevel >11){
return false;
}
//specific for id
return false;
}
}