/DataExtractionOSM/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java
Java | 505 lines | 470 code | 31 blank | 4 comment | 99 complexity | 3dbcbd6325e3a849cfdf85e2ebe603e1 MD5 | raw file
- package net.osmand.binary;
- import java.io.IOException;
- import java.util.List;
- import net.osmand.StringMatcher;
- import net.osmand.data.Building;
- import net.osmand.data.City;
- import net.osmand.data.PostCode;
- import net.osmand.data.Street;
- import net.osmand.data.City.CityType;
- import net.osmand.osm.LatLon;
- import net.osmand.osm.MapUtils;
- import net.sf.junidecode.Junidecode;
- import com.google.protobuf.CodedInputStreamRAF;
- import com.google.protobuf.WireFormat;
- public class BinaryMapAddressReaderAdapter {
-
- public static class AddressRegion extends BinaryIndexPart {
- String enName;
-
- int postcodesOffset = -1;
- int villagesOffset = -1;
- int citiesOffset = -1;
- }
-
- private CodedInputStreamRAF codedIS;
- private final BinaryMapIndexReader map;
-
- protected BinaryMapAddressReaderAdapter(BinaryMapIndexReader map){
- this.codedIS = map.codedIS;
- this.map = map;
- }
- private void skipUnknownField(int t) throws IOException {
- map.skipUnknownField(t);
- }
-
- private int readInt() throws IOException {
- return map.readInt();
- }
-
- protected void readAddressIndex(AddressRegion region) throws IOException {
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- if(region.enName == null || region.enName.length() == 0){
- region.enName = Junidecode.unidecode(region.name);
- }
- return;
- case OsmandOdb.OsmAndAddressIndex.NAME_FIELD_NUMBER :
- region.name = codedIS.readString();
- break;
- case OsmandOdb.OsmAndAddressIndex.NAME_EN_FIELD_NUMBER :
- region.enName = codedIS.readString();
- break;
- case OsmandOdb.OsmAndAddressIndex.CITIES_FIELD_NUMBER :
- region.citiesOffset = codedIS.getTotalBytesRead();
- int length = readInt();
- codedIS.seek(region.citiesOffset + length + 4);
- break;
- case OsmandOdb.OsmAndAddressIndex.VILLAGES_FIELD_NUMBER :
- region.villagesOffset = codedIS.getTotalBytesRead();
- length = readInt();
- codedIS.seek(region.villagesOffset + length + 4);
- break;
- case OsmandOdb.OsmAndAddressIndex.POSTCODES_FIELD_NUMBER :
- region.postcodesOffset = codedIS.getTotalBytesRead();
- length = readInt();
- codedIS.seek(region.postcodesOffset + length + 4);
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
- protected void readCities(List<City> cities, StringMatcher matcher, boolean useEn) throws IOException {
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- return;
- case OsmandOdb.CitiesIndex.CITIES_FIELD_NUMBER :
- int offset = codedIS.getTotalBytesRead();
- int length = codedIS.readRawVarint32();
-
- int oldLimit = codedIS.pushLimit(length);
- City c = readCity(null, offset, false, matcher, useEn);
- if(c != null){
- cities.add(c);
- }
- codedIS.popLimit(oldLimit);
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
- protected PostCode readPostcode(PostCode p, int fileOffset, boolean loadStreets, String postcodeFilter) throws IOException{
- int x = 0;
- int y = 0;
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- p.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
- p.setFileOffset(fileOffset);
- return p;
- case OsmandOdb.PostcodeIndex.POSTCODE_FIELD_NUMBER :
- String name = codedIS.readString();
- if(postcodeFilter != null && !postcodeFilter.equalsIgnoreCase(name)){
- codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
- return null;
- }
- if(p == null){
- p = new PostCode(name);
- }
- p.setName(name);
- break;
- case OsmandOdb.PostcodeIndex.X_FIELD_NUMBER :
- x = codedIS.readFixed32();
- break;
- case OsmandOdb.PostcodeIndex.Y_FIELD_NUMBER :
- y = codedIS.readFixed32();
- break;
- case OsmandOdb.PostcodeIndex.STREETS_FIELD_NUMBER :
- int offset = codedIS.getTotalBytesRead();
- int length = codedIS.readRawVarint32();
- if(loadStreets){
- Street s = new Street(null);
- int oldLimit = codedIS.pushLimit(length);
- s.setFileOffset(offset);
- readStreet(s, true, x >> 7, y >> 7, p.getName());
- p.registerStreet(s, false);
- codedIS.popLimit(oldLimit);
- } else {
- codedIS.skipRawBytes(length);
- }
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
-
- protected City readCity(City c, int fileOffset, boolean loadStreets, StringMatcher nameMatcher, boolean useEn) throws IOException{
- int x = 0;
- int y = 0;
- int streetInd = 0;
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- boolean englishNameMatched = false;
- switch (tag) {
- case 0:
- c.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
- if(c.getEnName().length() == 0){
- c.setEnName(Junidecode.unidecode(c.getName()));
- }
- return c;
- case OsmandOdb.CityIndex.CITY_TYPE_FIELD_NUMBER :
- int type = codedIS.readUInt32();
- if(c == null){
- c = new City(CityType.values()[type]);
- c.setFileOffset(fileOffset);
- }
- break;
- case OsmandOdb.CityIndex.ID_FIELD_NUMBER :
- c.setId(codedIS.readUInt64());
- if(nameMatcher != null && useEn && !englishNameMatched){
- codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
- return null;
- }
- break;
- case OsmandOdb.CityIndex.NAME_EN_FIELD_NUMBER :
- String enName = codedIS.readString();
- if (nameMatcher != null && enName.length() > 0) {
- if(!nameMatcher.matches(enName)){
- codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
- return null;
- } else {
- englishNameMatched = true;
- }
- }
- c.setEnName(enName);
- break;
- case OsmandOdb.CityIndex.NAME_FIELD_NUMBER :
- String name = codedIS.readString();
- c.setName(name);
- if(nameMatcher != null){
- if(!useEn){
- if(!nameMatcher.matches(name)) {
- codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
- return null;
- }
- } else {
- if(nameMatcher.matches(Junidecode.unidecode(name))){
- englishNameMatched = true;
- }
- }
- }
- break;
- case OsmandOdb.CityIndex.X_FIELD_NUMBER :
- x = codedIS.readFixed32();
- break;
- case OsmandOdb.CityIndex.Y_FIELD_NUMBER :
- y = codedIS.readFixed32();
- break;
- case OsmandOdb.CityIndex.INTERSECTIONS_FIELD_NUMBER :
- codedIS.skipRawBytes(codedIS.readRawVarint32());
- break;
- case OsmandOdb.CityIndex.STREETS_FIELD_NUMBER :
- int offset = codedIS.getTotalBytesRead();
- int length = codedIS.readRawVarint32();
- if(loadStreets){
- Street s = new Street(c);
- int oldLimit = codedIS.pushLimit(length);
- s.setFileOffset(offset);
- s.setIndexInCity(streetInd++);
- readStreet(s, false, x >> 7, y >> 7, null);
- c.registerStreet(s);
- codedIS.popLimit(oldLimit);
- } else {
- codedIS.skipRawBytes(length);
- }
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
- protected Street readStreet(Street s, boolean loadBuildings, int city24X, int city24Y, String postcodeFilter) throws IOException{
- int x = 0;
- int y = 0;
- boolean loadLocation = city24X != 0 || city24Y != 0;
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- if(loadLocation){
- s.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
- }
- if(s.getEnName().length() == 0){
- s.setEnName(Junidecode.unidecode(s.getName()));
- }
- return s;
- case OsmandOdb.StreetIndex.ID_FIELD_NUMBER :
- s.setId(codedIS.readUInt64());
- break;
- case OsmandOdb.StreetIndex.NAME_EN_FIELD_NUMBER :
- s.setEnName(codedIS.readString());
- break;
- case OsmandOdb.StreetIndex.NAME_FIELD_NUMBER :
- s.setName(codedIS.readString());
- break;
- case OsmandOdb.StreetIndex.X_FIELD_NUMBER :
- int sx = codedIS.readSInt32();
- if(loadLocation){
- x = sx + city24X;
- } else {
- x = (int) MapUtils.getTileNumberX(24, s.getLocation().getLongitude());
- }
- break;
- case OsmandOdb.StreetIndex.Y_FIELD_NUMBER :
- int sy = codedIS.readSInt32();
- if(loadLocation){
- y = sy + city24Y;
- } else {
- y = (int) MapUtils.getTileNumberY(24, s.getLocation().getLatitude());
- }
- break;
- case OsmandOdb.StreetIndex.BUILDINGS_FIELD_NUMBER :
- int offset = codedIS.getTotalBytesRead();
- int length = codedIS.readRawVarint32();
- if(loadBuildings){
- int oldLimit = codedIS.pushLimit(length);
- Building b = readBuilding(offset, x, y);
- if (postcodeFilter == null || postcodeFilter.equalsIgnoreCase(b.getPostcode())) {
- s.registerBuilding(b);
- }
- codedIS.popLimit(oldLimit);
- } else {
- codedIS.skipRawBytes(length);
- }
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
- protected Building readBuilding(int fileOffset, int street24X, int street24Y) throws IOException{
- int x = 0;
- int y = 0;
- Building b = new Building();
- b.setFileOffset(fileOffset);
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- b.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
- if(b.getEnName().length() == 0){
- b.setEnName(Junidecode.unidecode(b.getName()));
- }
- return b;
- case OsmandOdb.BuildingIndex.ID_FIELD_NUMBER :
- b.setId(codedIS.readUInt64());
- break;
- case OsmandOdb.BuildingIndex.NAME_EN_FIELD_NUMBER :
- b.setEnName(codedIS.readString());
- break;
- case OsmandOdb.BuildingIndex.NAME_FIELD_NUMBER :
- b.setName(codedIS.readString());
- break;
- case OsmandOdb.BuildingIndex.X_FIELD_NUMBER :
- x = codedIS.readSInt32() + street24X;
- break;
- case OsmandOdb.BuildingIndex.Y_FIELD_NUMBER :
- y = codedIS.readSInt32() + street24Y;
- break;
- case OsmandOdb.BuildingIndex.POSTCODE_FIELD_NUMBER :
- b.setPostcode(codedIS.readString());
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
- // 2 different quires : s2 == null -> fill possible streets, s2 != null return LatLon intersection
- private LatLon readIntersectedStreets(Street[] cityStreets, Street s, Street s2, LatLon parent, List<Street> streets) throws IOException {
- int size = codedIS.readRawVarint32();
- int old = codedIS.pushLimit(size);
- boolean e = false;
- while(!e){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- e = true;
- break;
- case OsmandOdb.InteresectedStreets.INTERSECTIONS_FIELD_NUMBER:
- int nsize = codedIS.readRawVarint32();
- int nold = codedIS.pushLimit(nsize);
- int st1 = -1;
- int st2 = -1;
- int cx = 0;
- int cy = 0;
- boolean end = false;
- while (!end) {
- int nt = codedIS.readTag();
- int ntag = WireFormat.getTagFieldNumber(nt);
- switch (ntag) {
- case 0:
- end = true;
- break;
- case OsmandOdb.StreetIntersection.INTERSECTEDSTREET1_FIELD_NUMBER:
- st1 = codedIS.readUInt32();
- break;
- case OsmandOdb.StreetIntersection.INTERSECTEDSTREET2_FIELD_NUMBER:
- st2 = codedIS.readUInt32();
- break;
- case OsmandOdb.StreetIntersection.INTERSECTEDX_FIELD_NUMBER:
- cx = codedIS.readSInt32();
- break;
- case OsmandOdb.StreetIntersection.INTERSECTEDY_FIELD_NUMBER:
- cy = codedIS.readSInt32();
- break;
- default:
- skipUnknownField(nt);
- }
- }
- codedIS.popLimit(nold);
- if (s2 == null) {
- // find all intersections
- if (st1 == s.getIndexInCity() && st2 != -1 && st2 < cityStreets.length && cityStreets[st2] != null) {
- streets.add(cityStreets[st2]);
- } else if (st2 == s.getIndexInCity() && st1 != -1 && st1 < cityStreets.length && cityStreets[st1] != null) {
- streets.add(cityStreets[st1]);
- }
- } else {
- if((st1 == s.getIndexInCity() && st2 == s2.getIndexInCity() ) ||
- (st2 == s.getIndexInCity() && st1 == s2.getIndexInCity())) {
- int x = (int) (MapUtils.getTileNumberX(24, parent.getLongitude()) + cx);
- int y = (int) (MapUtils.getTileNumberY(24, parent.getLatitude()) + cy);
- codedIS.popLimit(old);
- return new LatLon(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
- }
- }
-
- break;
- default:
- skipUnknownField(t);
- }
- }
- codedIS.popLimit(old);
- return null;
- }
-
- // do not preload streets in city
- protected LatLon findIntersectedStreets(City c, Street s, Street s2, List<Street> streets) throws IOException {
- if(s.getIndexInCity() == -1){
- return null;
- }
- codedIS.seek(c.getFileOffset());
- int size = codedIS.readRawVarint32();
- int old = codedIS.pushLimit(size);
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- codedIS.popLimit(old);
- return null;
- case OsmandOdb.CityIndex.INTERSECTIONS_FIELD_NUMBER :
- Street[] cityStreets = new Street[c.getStreets().size()];
- for(Street st : c.getStreets()){
- if(st.getIndexInCity() >= 0 && st.getIndexInCity() < cityStreets.length){
- cityStreets[st.getIndexInCity()] = st;
- }
- }
- LatLon ret = readIntersectedStreets(cityStreets, s, s2, c.getLocation(), streets);
- codedIS.popLimit(old);
- return ret;
- default:
- skipUnknownField(t);
- }
- }
-
- }
-
-
-
- void readPostcodes(List<PostCode> postcodes, StringMatcher nameMatcher) throws IOException{
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- return;
- case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
- int offset = codedIS.getTotalBytesRead();
- int length = codedIS.readRawVarint32();
- int oldLimit = codedIS.pushLimit(length);
- final PostCode postCode = readPostcode(null, offset, false, null);
- //TODO support getEnName??
- if (nameMatcher == null || nameMatcher.matches(postCode.getName())) {
- postcodes.add(postCode);
- }
- codedIS.popLimit(oldLimit);
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
- PostCode findPostcode(String name) throws IOException{
- while(true){
- int t = codedIS.readTag();
- int tag = WireFormat.getTagFieldNumber(t);
- switch (tag) {
- case 0:
- return null;
- case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
- int offset = codedIS.getTotalBytesRead();
- int length = codedIS.readRawVarint32();
- int oldLimit = codedIS.pushLimit(length);
- PostCode p = readPostcode(null, offset, true, name);
- codedIS.popLimit(oldLimit);
- if(p != null){
- return p;
- }
- break;
- default:
- skipUnknownField(t);
- break;
- }
- }
- }
-
-
- }