package de.komoot.photon.nominatim.model; import com.google.common.base.Objects; import lombok.Data; import lombok.Getter; import lombok.Setter; import java.util.Arrays; import java.util.Map; import static de.komoot.photon.Constants.STATE; /** * representation of an address as returned by nominatim's get_addressdata PL/pgSQL function * * @author christoph */ @Data public class AddressRow { final private long placeId; final private Map<String, String> name; final private String osmKey; final private String osmValue; final private int rankAddress; final Integer adminLevel; final private String postcode; final private String place; final private String osmType; final private long osmId; static private final String[] CITY_PLACE_VALUES = new String[]{"city", "hamlet", "town", "village"}; // must be in alphabetic order to speed up lookup static private final String[] USEFUL_CONTEXT_KEYS = new String[]{"boundary", "landuse", "place"}; // must be in alphabetic order to speed up lookup // relation ids that are known to be cities, but cannot be deduced by mapping as they are mapped in a special way // see https://github.com/komoot/photon/issues/138 static private final long[] CURATED_CITY_RELATION_IDS; static { long[] ids = new long[]{62772l, 62654l, 62532l, 62407l, 62340l, 62525l, 62640l, 62646l, 62644l, 62508l, 62634l, 62470l, 62531l, 62658l, 62594l, 62717l, 62430l, 62581l, 62414l, 62526l, 1829065l, 191645l, 62456l, 62539l, 62370l, 62562l, 62745l, 62403l, 62713l, 62675l, 62573l, 62523l, 62400l, 62768l, 62374l, 62522l, 62671l, 1800297l, 62638l, 62499l, 285864l, 62751l, 62396l, 62589l, 62381l, 62693l, 62652l, 62518l, 62598l, 62349l, 62701l, 27021l, 62512l, 62578l, 62748l, 62391l, 62484l, 62649l, 62449l, 27027l, 62347l, 62481l, 62630l, 62691l, 62590l, 62410l, 62385l, 62428l, 62591l, 62528l, 62724l, 62780l, 62734l, 62695l, 62409l, 62631l, 62629l, 62471l, 62642l, 62369l, 62411l, 62455l, 2168233l, 62405l, 62659l, 62720l, 62534l, 62685l, 62699l, 62352l, 62636l, 2793104l, 62450l, 172679l, 62495l, 62554l, 62493l, 62496l, 62444l, 62418l, 62453l, 62478l, 62464l, 62719l, 62422l, 62559l, 62782l}; Arrays.sort(ids); CURATED_CITY_RELATION_IDS = ids; } public boolean isStreet() { return 26 <= rankAddress && rankAddress < 28; } public boolean isCity() { if("place".equals(osmKey) && Arrays.binarySearch(CITY_PLACE_VALUES, osmValue) >= 0) { return true; } if(place != null && Arrays.binarySearch(CITY_PLACE_VALUES, place) >= 0) { return true; } if(adminLevel != null && adminLevel == 8 && "boundary".equals(osmKey) && "administrative".equals(osmValue)) { return true; } return false; } /** * whether address row was manually marked as city * * @return */ public boolean isCuratedCity() { if("R".equals(osmType) && Arrays.binarySearch(CURATED_CITY_RELATION_IDS, osmId) >= 0) { return true; } return false; } public boolean isPostcode() { if("place".equals(osmKey) && "postcode".equals(osmValue)) { return true; } if("boundary".equals(osmKey) && "postal_code".equals(osmValue)) { return true; } return false; } public boolean hasPostcode() { return postcode != null; // TODO really null? } public boolean hasPlace() { return place != null; } public boolean isUsefulForContext() { if(name.isEmpty()) { return false; } if(isPostcode()) { return false; } if(isCuratedCity()) { // was already added to city return false; } if(rankAddress < 4) { // continent, sea, ... return false; } if(Arrays.binarySearch(USEFUL_CONTEXT_KEYS, osmKey) >= 0) { return true; } return false; } public boolean isCountry() { if(adminLevel != null && adminLevel == 2 && "boundary".equals(osmKey) && "administrative".equals(osmValue)) { return true; } if("place".equals(osmKey) && "country".equals(osmValue)) { return true; } return false; } public boolean isState() { if("place".equals(osmKey) && STATE.equals(osmValue)) { return true; } if(adminLevel != null && adminLevel == 4 && "boundary".equals(osmKey) && "administrative".equals(osmValue)) { return true; } return false; } @Override public String toString() { return Objects.toStringHelper(this) .add("placeId", placeId) .add("name", name) .add("osmKey", osmKey) .add("osmValue", osmValue) .toString(); } }