diff --git a/DataExtractionOSM/src/com/osmand/data/Building.java b/DataExtractionOSM/src/com/osmand/data/Building.java index 2a9e630fd1..cead1188c8 100644 --- a/DataExtractionOSM/src/com/osmand/data/Building.java +++ b/DataExtractionOSM/src/com/osmand/data/Building.java @@ -1,13 +1,26 @@ package com.osmand.data; import com.osmand.osm.Entity; +import com.osmand.osm.OSMSettings.OSMTagKey; public class Building extends MapObject { + + private String postcode; public Building(Entity e){ super(e); + // try to extract postcode + postcode = e.getTag(OSMTagKey.ADDR_POSTCODE); } public Building(){} + + public String getPostcode() { + return postcode; + } + + public void setPostcode(String postcode) { + this.postcode = postcode; + } } diff --git a/DataExtractionOSM/src/com/osmand/data/City.java b/DataExtractionOSM/src/com/osmand/data/City.java index 7a9f50d2f8..597e9be68d 100644 --- a/DataExtractionOSM/src/com/osmand/data/City.java +++ b/DataExtractionOSM/src/com/osmand/data/City.java @@ -3,7 +3,9 @@ package com.osmand.data; import java.text.Collator; import java.util.Collection; import java.util.Map; +import java.util.SortedSet; import java.util.TreeMap; +import java.util.TreeSet; import com.osmand.Algoritms; import com.osmand.osm.Entity; @@ -46,7 +48,8 @@ public class City extends MapObject { private CityType type = null; // Be attentive ! Working with street names ignoring case private Map streets = new TreeMap(Collator.getInstance()); - + private SortedSet postcodes = new TreeSet(); + public City(Node el){ super(el); type = CityType.valueFromString(el.getTag(OSMTagKey.PLACE)); @@ -100,7 +103,10 @@ public class City extends MapObject { String number = e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER); String street = e.getTag(OSMTagKey.ADDR_STREET); 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 null; @@ -110,6 +116,10 @@ public class City extends MapObject { return type; } + public SortedSet getPostcodes() { + return postcodes; + } + public Collection getStreets(){ return streets.values(); } diff --git a/DataExtractionOSM/src/com/osmand/data/PostcodeBasedStreet.java b/DataExtractionOSM/src/com/osmand/data/PostcodeBasedStreet.java new file mode 100644 index 0000000000..d205d95b59 --- /dev/null +++ b/DataExtractionOSM/src/com/osmand/data/PostcodeBasedStreet.java @@ -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; + } + +} diff --git a/DataExtractionOSM/src/com/osmand/data/Street.java b/DataExtractionOSM/src/com/osmand/data/Street.java index b4d97b7682..ae285ee472 100644 --- a/DataExtractionOSM/src/com/osmand/data/Street.java +++ b/DataExtractionOSM/src/com/osmand/data/Street.java @@ -28,10 +28,11 @@ public class Street extends MapObject { this.city = city; } - public void registerBuilding(Entity e){ + public Building registerBuilding(Entity e){ Building building = new Building(e); building.setName(e.getTag(OSMTagKey.ADDR_HOUSE_NUMBER)); buildings.add(building); + return building; } public void registerBuilding(Building building){ diff --git a/DataExtractionOSM/src/com/osmand/data/index/DataIndexWriter.java b/DataExtractionOSM/src/com/osmand/data/index/DataIndexWriter.java index 8b3880d1f7..44ae1202fb 100644 --- a/DataExtractionOSM/src/com/osmand/data/index/DataIndexWriter.java +++ b/DataExtractionOSM/src/com/osmand/data/index/DataIndexWriter.java @@ -140,7 +140,7 @@ public class DataIndexWriter { PreparedStatement prepStreet = conn.prepareStatement( IndexConstants.generatePrepareStatementToInsert(IndexStreetTable.getTable(), 6)); PreparedStatement prepBuilding = conn.prepareStatement( - IndexConstants.generatePrepareStatementToInsert(IndexBuildingTable.getTable(), 6)); + IndexConstants.generatePrepareStatementToInsert(IndexBuildingTable.getTable(), 7)); PreparedStatement prepStreetNode = conn.prepareStatement( IndexConstants.generatePrepareStatementToInsert(IndexStreetNodeTable.getTable(), 5)); Map count = new HashMap(); @@ -199,6 +199,8 @@ public class DataIndexWriter { prepBuilding.setString(IndexBuildingTable.NAME.ordinal() + 1, building.getName()); prepBuilding.setString(IndexBuildingTable.NAME_EN.ordinal() + 1, building.getEnName()); prepBuilding.setLong(IndexBuildingTable.STREET.ordinal() + 1, street.getId()); + prepBuilding.setString(IndexBuildingTable.POSTCODE.ordinal()+1, building.getPostcode() == null ? null : building.getPostcode().toUpperCase()); + addBatch(count, prepBuilding); } } diff --git a/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java b/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java index c21ea18b3c..2d7d97a120 100644 --- a/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java +++ b/DataExtractionOSM/src/com/osmand/data/index/IndexConstants.java @@ -246,7 +246,7 @@ public class IndexConstants { } 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; String type = null; diff --git a/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java b/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java index 723dc8ae0a..7e91465216 100644 --- a/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java +++ b/DataExtractionOSM/src/com/osmand/osm/OSMSettings.java @@ -17,6 +17,7 @@ public class OSMSettings { PLACE("place"), ADDR_HOUSE_NUMBER("addr:housenumber"), ADDR_STREET("addr:street"), + ADDR_POSTCODE("addr:postcode"), // POI AMENITY("amenity"), diff --git a/OsmAnd/src/com/osmand/RegionAddressRepository.java b/OsmAnd/src/com/osmand/RegionAddressRepository.java index b87636602b..8aee18c525 100644 --- a/OsmAnd/src/com/osmand/RegionAddressRepository.java +++ b/OsmAnd/src/com/osmand/RegionAddressRepository.java @@ -1,6 +1,7 @@ package com.osmand; import java.io.File; +import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -19,6 +20,7 @@ import android.database.sqlite.SQLiteDatabase; import com.osmand.data.Building; import com.osmand.data.City; +import com.osmand.data.PostcodeBasedStreet; import com.osmand.data.Region; import com.osmand.data.Street; import com.osmand.data.City.CityType; @@ -91,7 +93,14 @@ public class RegionAddressRepository { if(city.isEmptyWithStreets()){ 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){ @@ -180,12 +189,27 @@ public class RegionAddressRepository { public void fillWithSuggestedStreets(City c, String name, List streetsToFill){ preloadStreets(c); + preloadPostcodes(c); name = name.toLowerCase(); + int ind = 0; if(name.length() == 0){ streetsToFill.addAll(c.getStreets()); 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()) { String sName = useEnglishNames ? s.getEnName() : s.getName(); String lowerCase = sName.toLowerCase(); @@ -204,7 +228,10 @@ public class RegionAddressRepository { EnumSet set = EnumSet.of(CityType.CITY, CityType.TOWN); for(CityType t : set){ if(name.length() == 0){ - citiesToFill.addAll(cityTypes.get(t)); + List list = cityTypes.get(t); + if (list != null) { + citiesToFill.addAll(list); + } } else { name = name.toLowerCase(); for (City c : cityTypes.get(t)) { @@ -281,11 +308,44 @@ 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){ if (street.getBuildings().isEmpty()) { - Cursor query = db.query(IndexBuildingTable.getTable(), IndexConstants.generateColumnNames(IndexBuildingTable.values()), "? = street", - new String[] { street.getId() + "" }, null, null, null); + 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); + } log.debug("Start loading buildings for " + street.getName()); if (query.moveToFirst()) { do {