Add postcode search

git-svn-id: https://osmand.googlecode.com/svn/trunk@165 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
andrei.adamian 2010-06-15 18:54:50 +00:00
parent d9286a9c71
commit 42426f041f
8 changed files with 110 additions and 9 deletions

View file

@ -1,13 +1,26 @@
package com.osmand.data; package com.osmand.data;
import com.osmand.osm.Entity; import com.osmand.osm.Entity;
import com.osmand.osm.OSMSettings.OSMTagKey;
public class Building extends MapObject { public class Building extends MapObject {
private String postcode;
public Building(Entity e){ public Building(Entity e){
super(e); super(e);
// try to extract postcode
postcode = e.getTag(OSMTagKey.ADDR_POSTCODE);
} }
public Building(){} public Building(){}
public String getPostcode() {
return postcode;
}
public void setPostcode(String postcode) {
this.postcode = postcode;
}
} }

View file

@ -3,7 +3,9 @@ package com.osmand.data;
import java.text.Collator; import java.text.Collator;
import java.util.Collection; import java.util.Collection;
import java.util.Map; import java.util.Map;
import java.util.SortedSet;
import java.util.TreeMap; import java.util.TreeMap;
import java.util.TreeSet;
import com.osmand.Algoritms; import com.osmand.Algoritms;
import com.osmand.osm.Entity; import com.osmand.osm.Entity;
@ -46,6 +48,7 @@ public class City extends MapObject {
private CityType type = null; private CityType type = null;
// Be attentive ! Working with street names ignoring case // Be attentive ! Working with street names ignoring case
private Map<String, Street> streets = new TreeMap<String, Street>(Collator.getInstance()); private Map<String, Street> streets = new TreeMap<String, Street>(Collator.getInstance());
private SortedSet<String> postcodes = new TreeSet<String>();
public City(Node el){ public City(Node el){
super(el); super(el);
@ -100,7 +103,10 @@ public class City extends MapObject {
String number = e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER); String number = e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER);
String street = e.getTag(OSMTagKey.ADDR_STREET); String street = e.getTag(OSMTagKey.ADDR_STREET);
if( street != null && number != null){ if( street != null && number != null){
registerStreet(street).registerBuilding(e); Building building = registerStreet(street).registerBuilding(e);
if (building.getPostcode() != null) {
postcodes.add(building.getPostcode());
}
return streets.get(street.toLowerCase()); return streets.get(street.toLowerCase());
} }
return null; return null;
@ -110,6 +116,10 @@ public class City extends MapObject {
return type; return type;
} }
public SortedSet<String> getPostcodes() {
return postcodes;
}
public Collection<Street> getStreets(){ public Collection<Street> getStreets(){
return streets.values(); return streets.values();
} }

View file

@ -0,0 +1,14 @@
package com.osmand.data;
public class PostcodeBasedStreet extends Street {
public PostcodeBasedStreet(City city, String postcode) {
super(city, postcode);
}
@Override
public Long getId() {
return -1l;
}
}

View file

@ -28,10 +28,11 @@ public class Street extends MapObject {
this.city = city; this.city = city;
} }
public void registerBuilding(Entity e){ public Building registerBuilding(Entity e){
Building building = new Building(e); Building building = new Building(e);
building.setName(e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER)); building.setName(e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER));
buildings.add(building); buildings.add(building);
return building;
} }
public void registerBuilding(Building building){ public void registerBuilding(Building building){

View file

@ -140,7 +140,7 @@ public class DataIndexWriter {
PreparedStatement prepStreet = conn.prepareStatement( PreparedStatement prepStreet = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexStreetTable.getTable(), 6)); IndexConstants.generatePrepareStatementToInsert(IndexStreetTable.getTable(), 6));
PreparedStatement prepBuilding = conn.prepareStatement( PreparedStatement prepBuilding = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexBuildingTable.getTable(), 6)); IndexConstants.generatePrepareStatementToInsert(IndexBuildingTable.getTable(), 7));
PreparedStatement prepStreetNode = conn.prepareStatement( PreparedStatement prepStreetNode = conn.prepareStatement(
IndexConstants.generatePrepareStatementToInsert(IndexStreetNodeTable.getTable(), 5)); IndexConstants.generatePrepareStatementToInsert(IndexStreetNodeTable.getTable(), 5));
Map<PreparedStatement, Integer> count = new HashMap<PreparedStatement, Integer>(); Map<PreparedStatement, Integer> count = new HashMap<PreparedStatement, Integer>();
@ -199,6 +199,8 @@ public class DataIndexWriter {
prepBuilding.setString(IndexBuildingTable.NAME.ordinal() + 1, building.getName()); prepBuilding.setString(IndexBuildingTable.NAME.ordinal() + 1, building.getName());
prepBuilding.setString(IndexBuildingTable.NAME_EN.ordinal() + 1, building.getEnName()); prepBuilding.setString(IndexBuildingTable.NAME_EN.ordinal() + 1, building.getEnName());
prepBuilding.setLong(IndexBuildingTable.STREET.ordinal() + 1, street.getId()); prepBuilding.setLong(IndexBuildingTable.STREET.ordinal() + 1, street.getId());
prepBuilding.setString(IndexBuildingTable.POSTCODE.ordinal()+1, building.getPostcode() == null ? null : building.getPostcode().toUpperCase());
addBatch(count, prepBuilding); addBatch(count, prepBuilding);
} }
} }

View file

@ -246,7 +246,7 @@ public class IndexConstants {
} }
public enum IndexBuildingTable implements IndexColumn { public enum IndexBuildingTable implements IndexColumn {
ID("long"), LATITUDE("double"), LONGITUDE("double"), NAME, NAME_EN, STREET("long", true); ID("long"), LATITUDE("double"), LONGITUDE("double"), NAME, NAME_EN, STREET("long", true), POSTCODE;
boolean index = false; boolean index = false;
String type = null; String type = null;

View file

@ -17,6 +17,7 @@ public class OSMSettings {
PLACE("place"), PLACE("place"),
ADDR_HOUSE_NUMBER("addr:housenumber"), ADDR_HOUSE_NUMBER("addr:housenumber"),
ADDR_STREET("addr:street"), ADDR_STREET("addr:street"),
ADDR_POSTCODE("addr:postcode"),
// POI // POI
AMENITY("amenity"), AMENITY("amenity"),

View file

@ -1,6 +1,7 @@
package com.osmand; package com.osmand;
import java.io.File; import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -19,6 +20,7 @@ import android.database.sqlite.SQLiteDatabase;
import com.osmand.data.Building; import com.osmand.data.Building;
import com.osmand.data.City; import com.osmand.data.City;
import com.osmand.data.PostcodeBasedStreet;
import com.osmand.data.Region; import com.osmand.data.Region;
import com.osmand.data.Street; import com.osmand.data.Street;
import com.osmand.data.City.CityType; import com.osmand.data.City.CityType;
@ -91,7 +93,14 @@ public class RegionAddressRepository {
if(city.isEmptyWithStreets()){ if(city.isEmptyWithStreets()){
preloadStreets(city); preloadStreets(city);
} }
return city.getStreet(name); if (city.getPostcodes().isEmpty()) {
preloadPostcodes(city);
}
Street street = city.getStreet(name);
if (street == null) {
street = city.getPostcodes().contains(name.toUpperCase()) ? new PostcodeBasedStreet(city, name) : null;
}
return street;
} }
public Building getBuildingByName(Street street, String name){ public Building getBuildingByName(Street street, String name){
@ -180,12 +189,27 @@ public class RegionAddressRepository {
public void fillWithSuggestedStreets(City c, String name, List<Street> streetsToFill){ public void fillWithSuggestedStreets(City c, String name, List<Street> streetsToFill){
preloadStreets(c); preloadStreets(c);
preloadPostcodes(c);
name = name.toLowerCase(); name = name.toLowerCase();
int ind = 0; int ind = 0;
if(name.length() == 0){ if(name.length() == 0){
streetsToFill.addAll(c.getStreets()); streetsToFill.addAll(c.getStreets());
return; return;
} else if (name.length() >= 2 &&
Character.isDigit(name.charAt(0)) &&
Character.isDigit(name.charAt(1))) {
// also try to identify postcodes
for (String code:c.getPostcodes()) {
code = code.toLowerCase();
if (code.startsWith(name)) {
streetsToFill.add(ind++,new PostcodeBasedStreet(c, code));
} else {
streetsToFill.add(new PostcodeBasedStreet(c, code));
} }
}
}
ind = 0;
for (Street s : c.getStreets()) { for (Street s : c.getStreets()) {
String sName = useEnglishNames ? s.getEnName() : s.getName(); String sName = useEnglishNames ? s.getEnName() : s.getName();
String lowerCase = sName.toLowerCase(); String lowerCase = sName.toLowerCase();
@ -204,7 +228,10 @@ public class RegionAddressRepository {
EnumSet<CityType> set = EnumSet.of(CityType.CITY, CityType.TOWN); EnumSet<CityType> set = EnumSet.of(CityType.CITY, CityType.TOWN);
for(CityType t : set){ for(CityType t : set){
if(name.length() == 0){ if(name.length() == 0){
citiesToFill.addAll(cityTypes.get(t)); List<City> list = cityTypes.get(t);
if (list != null) {
citiesToFill.addAll(list);
}
} else { } else {
name = name.toLowerCase(); name = name.toLowerCase();
for (City c : cityTypes.get(t)) { for (City c : cityTypes.get(t)) {
@ -282,10 +309,43 @@ public class RegionAddressRepository {
} }
public void preloadPostcodes(City city) {
if (city.getPostcodes().isEmpty()) {
// check if it possible to load postcodes
try {
Cursor query = db.query(true, IndexBuildingTable.getTable(), new String[]{IndexBuildingTable.POSTCODE.toString()},null,null,null,null,null,null);
log.debug("Start loading postcodes for " + city.getName());
if (query.moveToFirst()) {
do {
String postcode = query.getString(0);
if (postcode != null) {
city.getPostcodes().add(postcode);
}
} while (query.moveToNext());
}
query.close();
log.debug("Loaded " + city.getPostcodes().size() + " buildings");
} catch (Throwable t) {
log.warn("Can't load postcodes information. It might be that you are using old version of index.", t);
}
}
}
public void preloadBuildings(Street street){ public void preloadBuildings(Street street){
if (street.getBuildings().isEmpty()) { if (street.getBuildings().isEmpty()) {
Cursor query = db.query(IndexBuildingTable.getTable(), IndexConstants.generateColumnNames(IndexBuildingTable.values()), "? = street", Cursor query = null;
if (street instanceof PostcodeBasedStreet) {
// this is postcode
query = db.query(IndexBuildingTable.getTable(), IndexConstants.generateColumnNames(IndexBuildingTable.values()), "? = postcode",
new String[] { street.getName().toUpperCase()}, null, null, null);
} else {
IndexBuildingTable[] columns = IndexBuildingTable.values();
IndexBuildingTable[] columnsWithoutPostcode = new IndexBuildingTable[columns.length-1];
// we don't need postcode information here
System.arraycopy(columns, 0, columnsWithoutPostcode, 0, columnsWithoutPostcode.length);
query = db.query(IndexBuildingTable.getTable(), IndexConstants.generateColumnNames(columnsWithoutPostcode), "? = street",
new String[] { street.getId() + "" }, null, null, null); new String[] { street.getId() + "" }, null, null, null);
}
log.debug("Start loading buildings for " + street.getName()); log.debug("Start loading buildings for " + street.getName());
if (query.moveToFirst()) { if (query.moveToFirst()) {
do { do {