PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/DataExtractionOSM/src/net/osmand/binary/BinaryMapAddressReaderAdapter.java

https://github.com/arlas/Osmand
Java | 505 lines | 470 code | 31 blank | 4 comment | 99 complexity | 3dbcbd6325e3a849cfdf85e2ebe603e1 MD5 | raw file
  1. package net.osmand.binary;
  2. import java.io.IOException;
  3. import java.util.List;
  4. import net.osmand.StringMatcher;
  5. import net.osmand.data.Building;
  6. import net.osmand.data.City;
  7. import net.osmand.data.PostCode;
  8. import net.osmand.data.Street;
  9. import net.osmand.data.City.CityType;
  10. import net.osmand.osm.LatLon;
  11. import net.osmand.osm.MapUtils;
  12. import net.sf.junidecode.Junidecode;
  13. import com.google.protobuf.CodedInputStreamRAF;
  14. import com.google.protobuf.WireFormat;
  15. public class BinaryMapAddressReaderAdapter {
  16. public static class AddressRegion extends BinaryIndexPart {
  17. String enName;
  18. int postcodesOffset = -1;
  19. int villagesOffset = -1;
  20. int citiesOffset = -1;
  21. }
  22. private CodedInputStreamRAF codedIS;
  23. private final BinaryMapIndexReader map;
  24. protected BinaryMapAddressReaderAdapter(BinaryMapIndexReader map){
  25. this.codedIS = map.codedIS;
  26. this.map = map;
  27. }
  28. private void skipUnknownField(int t) throws IOException {
  29. map.skipUnknownField(t);
  30. }
  31. private int readInt() throws IOException {
  32. return map.readInt();
  33. }
  34. protected void readAddressIndex(AddressRegion region) throws IOException {
  35. while(true){
  36. int t = codedIS.readTag();
  37. int tag = WireFormat.getTagFieldNumber(t);
  38. switch (tag) {
  39. case 0:
  40. if(region.enName == null || region.enName.length() == 0){
  41. region.enName = Junidecode.unidecode(region.name);
  42. }
  43. return;
  44. case OsmandOdb.OsmAndAddressIndex.NAME_FIELD_NUMBER :
  45. region.name = codedIS.readString();
  46. break;
  47. case OsmandOdb.OsmAndAddressIndex.NAME_EN_FIELD_NUMBER :
  48. region.enName = codedIS.readString();
  49. break;
  50. case OsmandOdb.OsmAndAddressIndex.CITIES_FIELD_NUMBER :
  51. region.citiesOffset = codedIS.getTotalBytesRead();
  52. int length = readInt();
  53. codedIS.seek(region.citiesOffset + length + 4);
  54. break;
  55. case OsmandOdb.OsmAndAddressIndex.VILLAGES_FIELD_NUMBER :
  56. region.villagesOffset = codedIS.getTotalBytesRead();
  57. length = readInt();
  58. codedIS.seek(region.villagesOffset + length + 4);
  59. break;
  60. case OsmandOdb.OsmAndAddressIndex.POSTCODES_FIELD_NUMBER :
  61. region.postcodesOffset = codedIS.getTotalBytesRead();
  62. length = readInt();
  63. codedIS.seek(region.postcodesOffset + length + 4);
  64. break;
  65. default:
  66. skipUnknownField(t);
  67. break;
  68. }
  69. }
  70. }
  71. protected void readCities(List<City> cities, StringMatcher matcher, boolean useEn) throws IOException {
  72. while(true){
  73. int t = codedIS.readTag();
  74. int tag = WireFormat.getTagFieldNumber(t);
  75. switch (tag) {
  76. case 0:
  77. return;
  78. case OsmandOdb.CitiesIndex.CITIES_FIELD_NUMBER :
  79. int offset = codedIS.getTotalBytesRead();
  80. int length = codedIS.readRawVarint32();
  81. int oldLimit = codedIS.pushLimit(length);
  82. City c = readCity(null, offset, false, matcher, useEn);
  83. if(c != null){
  84. cities.add(c);
  85. }
  86. codedIS.popLimit(oldLimit);
  87. break;
  88. default:
  89. skipUnknownField(t);
  90. break;
  91. }
  92. }
  93. }
  94. protected PostCode readPostcode(PostCode p, int fileOffset, boolean loadStreets, String postcodeFilter) throws IOException{
  95. int x = 0;
  96. int y = 0;
  97. while(true){
  98. int t = codedIS.readTag();
  99. int tag = WireFormat.getTagFieldNumber(t);
  100. switch (tag) {
  101. case 0:
  102. p.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
  103. p.setFileOffset(fileOffset);
  104. return p;
  105. case OsmandOdb.PostcodeIndex.POSTCODE_FIELD_NUMBER :
  106. String name = codedIS.readString();
  107. if(postcodeFilter != null && !postcodeFilter.equalsIgnoreCase(name)){
  108. codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
  109. return null;
  110. }
  111. if(p == null){
  112. p = new PostCode(name);
  113. }
  114. p.setName(name);
  115. break;
  116. case OsmandOdb.PostcodeIndex.X_FIELD_NUMBER :
  117. x = codedIS.readFixed32();
  118. break;
  119. case OsmandOdb.PostcodeIndex.Y_FIELD_NUMBER :
  120. y = codedIS.readFixed32();
  121. break;
  122. case OsmandOdb.PostcodeIndex.STREETS_FIELD_NUMBER :
  123. int offset = codedIS.getTotalBytesRead();
  124. int length = codedIS.readRawVarint32();
  125. if(loadStreets){
  126. Street s = new Street(null);
  127. int oldLimit = codedIS.pushLimit(length);
  128. s.setFileOffset(offset);
  129. readStreet(s, true, x >> 7, y >> 7, p.getName());
  130. p.registerStreet(s, false);
  131. codedIS.popLimit(oldLimit);
  132. } else {
  133. codedIS.skipRawBytes(length);
  134. }
  135. break;
  136. default:
  137. skipUnknownField(t);
  138. break;
  139. }
  140. }
  141. }
  142. protected City readCity(City c, int fileOffset, boolean loadStreets, StringMatcher nameMatcher, boolean useEn) throws IOException{
  143. int x = 0;
  144. int y = 0;
  145. int streetInd = 0;
  146. while(true){
  147. int t = codedIS.readTag();
  148. int tag = WireFormat.getTagFieldNumber(t);
  149. boolean englishNameMatched = false;
  150. switch (tag) {
  151. case 0:
  152. c.setLocation(MapUtils.get31LatitudeY(y), MapUtils.get31LongitudeX(x));
  153. if(c.getEnName().length() == 0){
  154. c.setEnName(Junidecode.unidecode(c.getName()));
  155. }
  156. return c;
  157. case OsmandOdb.CityIndex.CITY_TYPE_FIELD_NUMBER :
  158. int type = codedIS.readUInt32();
  159. if(c == null){
  160. c = new City(CityType.values()[type]);
  161. c.setFileOffset(fileOffset);
  162. }
  163. break;
  164. case OsmandOdb.CityIndex.ID_FIELD_NUMBER :
  165. c.setId(codedIS.readUInt64());
  166. if(nameMatcher != null && useEn && !englishNameMatched){
  167. codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
  168. return null;
  169. }
  170. break;
  171. case OsmandOdb.CityIndex.NAME_EN_FIELD_NUMBER :
  172. String enName = codedIS.readString();
  173. if (nameMatcher != null && enName.length() > 0) {
  174. if(!nameMatcher.matches(enName)){
  175. codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
  176. return null;
  177. } else {
  178. englishNameMatched = true;
  179. }
  180. }
  181. c.setEnName(enName);
  182. break;
  183. case OsmandOdb.CityIndex.NAME_FIELD_NUMBER :
  184. String name = codedIS.readString();
  185. c.setName(name);
  186. if(nameMatcher != null){
  187. if(!useEn){
  188. if(!nameMatcher.matches(name)) {
  189. codedIS.skipRawBytes(codedIS.getBytesUntilLimit());
  190. return null;
  191. }
  192. } else {
  193. if(nameMatcher.matches(Junidecode.unidecode(name))){
  194. englishNameMatched = true;
  195. }
  196. }
  197. }
  198. break;
  199. case OsmandOdb.CityIndex.X_FIELD_NUMBER :
  200. x = codedIS.readFixed32();
  201. break;
  202. case OsmandOdb.CityIndex.Y_FIELD_NUMBER :
  203. y = codedIS.readFixed32();
  204. break;
  205. case OsmandOdb.CityIndex.INTERSECTIONS_FIELD_NUMBER :
  206. codedIS.skipRawBytes(codedIS.readRawVarint32());
  207. break;
  208. case OsmandOdb.CityIndex.STREETS_FIELD_NUMBER :
  209. int offset = codedIS.getTotalBytesRead();
  210. int length = codedIS.readRawVarint32();
  211. if(loadStreets){
  212. Street s = new Street(c);
  213. int oldLimit = codedIS.pushLimit(length);
  214. s.setFileOffset(offset);
  215. s.setIndexInCity(streetInd++);
  216. readStreet(s, false, x >> 7, y >> 7, null);
  217. c.registerStreet(s);
  218. codedIS.popLimit(oldLimit);
  219. } else {
  220. codedIS.skipRawBytes(length);
  221. }
  222. break;
  223. default:
  224. skipUnknownField(t);
  225. break;
  226. }
  227. }
  228. }
  229. protected Street readStreet(Street s, boolean loadBuildings, int city24X, int city24Y, String postcodeFilter) throws IOException{
  230. int x = 0;
  231. int y = 0;
  232. boolean loadLocation = city24X != 0 || city24Y != 0;
  233. while(true){
  234. int t = codedIS.readTag();
  235. int tag = WireFormat.getTagFieldNumber(t);
  236. switch (tag) {
  237. case 0:
  238. if(loadLocation){
  239. s.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
  240. }
  241. if(s.getEnName().length() == 0){
  242. s.setEnName(Junidecode.unidecode(s.getName()));
  243. }
  244. return s;
  245. case OsmandOdb.StreetIndex.ID_FIELD_NUMBER :
  246. s.setId(codedIS.readUInt64());
  247. break;
  248. case OsmandOdb.StreetIndex.NAME_EN_FIELD_NUMBER :
  249. s.setEnName(codedIS.readString());
  250. break;
  251. case OsmandOdb.StreetIndex.NAME_FIELD_NUMBER :
  252. s.setName(codedIS.readString());
  253. break;
  254. case OsmandOdb.StreetIndex.X_FIELD_NUMBER :
  255. int sx = codedIS.readSInt32();
  256. if(loadLocation){
  257. x = sx + city24X;
  258. } else {
  259. x = (int) MapUtils.getTileNumberX(24, s.getLocation().getLongitude());
  260. }
  261. break;
  262. case OsmandOdb.StreetIndex.Y_FIELD_NUMBER :
  263. int sy = codedIS.readSInt32();
  264. if(loadLocation){
  265. y = sy + city24Y;
  266. } else {
  267. y = (int) MapUtils.getTileNumberY(24, s.getLocation().getLatitude());
  268. }
  269. break;
  270. case OsmandOdb.StreetIndex.BUILDINGS_FIELD_NUMBER :
  271. int offset = codedIS.getTotalBytesRead();
  272. int length = codedIS.readRawVarint32();
  273. if(loadBuildings){
  274. int oldLimit = codedIS.pushLimit(length);
  275. Building b = readBuilding(offset, x, y);
  276. if (postcodeFilter == null || postcodeFilter.equalsIgnoreCase(b.getPostcode())) {
  277. s.registerBuilding(b);
  278. }
  279. codedIS.popLimit(oldLimit);
  280. } else {
  281. codedIS.skipRawBytes(length);
  282. }
  283. break;
  284. default:
  285. skipUnknownField(t);
  286. break;
  287. }
  288. }
  289. }
  290. protected Building readBuilding(int fileOffset, int street24X, int street24Y) throws IOException{
  291. int x = 0;
  292. int y = 0;
  293. Building b = new Building();
  294. b.setFileOffset(fileOffset);
  295. while(true){
  296. int t = codedIS.readTag();
  297. int tag = WireFormat.getTagFieldNumber(t);
  298. switch (tag) {
  299. case 0:
  300. b.setLocation(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
  301. if(b.getEnName().length() == 0){
  302. b.setEnName(Junidecode.unidecode(b.getName()));
  303. }
  304. return b;
  305. case OsmandOdb.BuildingIndex.ID_FIELD_NUMBER :
  306. b.setId(codedIS.readUInt64());
  307. break;
  308. case OsmandOdb.BuildingIndex.NAME_EN_FIELD_NUMBER :
  309. b.setEnName(codedIS.readString());
  310. break;
  311. case OsmandOdb.BuildingIndex.NAME_FIELD_NUMBER :
  312. b.setName(codedIS.readString());
  313. break;
  314. case OsmandOdb.BuildingIndex.X_FIELD_NUMBER :
  315. x = codedIS.readSInt32() + street24X;
  316. break;
  317. case OsmandOdb.BuildingIndex.Y_FIELD_NUMBER :
  318. y = codedIS.readSInt32() + street24Y;
  319. break;
  320. case OsmandOdb.BuildingIndex.POSTCODE_FIELD_NUMBER :
  321. b.setPostcode(codedIS.readString());
  322. break;
  323. default:
  324. skipUnknownField(t);
  325. break;
  326. }
  327. }
  328. }
  329. // 2 different quires : s2 == null -> fill possible streets, s2 != null return LatLon intersection
  330. private LatLon readIntersectedStreets(Street[] cityStreets, Street s, Street s2, LatLon parent, List<Street> streets) throws IOException {
  331. int size = codedIS.readRawVarint32();
  332. int old = codedIS.pushLimit(size);
  333. boolean e = false;
  334. while(!e){
  335. int t = codedIS.readTag();
  336. int tag = WireFormat.getTagFieldNumber(t);
  337. switch (tag) {
  338. case 0:
  339. e = true;
  340. break;
  341. case OsmandOdb.InteresectedStreets.INTERSECTIONS_FIELD_NUMBER:
  342. int nsize = codedIS.readRawVarint32();
  343. int nold = codedIS.pushLimit(nsize);
  344. int st1 = -1;
  345. int st2 = -1;
  346. int cx = 0;
  347. int cy = 0;
  348. boolean end = false;
  349. while (!end) {
  350. int nt = codedIS.readTag();
  351. int ntag = WireFormat.getTagFieldNumber(nt);
  352. switch (ntag) {
  353. case 0:
  354. end = true;
  355. break;
  356. case OsmandOdb.StreetIntersection.INTERSECTEDSTREET1_FIELD_NUMBER:
  357. st1 = codedIS.readUInt32();
  358. break;
  359. case OsmandOdb.StreetIntersection.INTERSECTEDSTREET2_FIELD_NUMBER:
  360. st2 = codedIS.readUInt32();
  361. break;
  362. case OsmandOdb.StreetIntersection.INTERSECTEDX_FIELD_NUMBER:
  363. cx = codedIS.readSInt32();
  364. break;
  365. case OsmandOdb.StreetIntersection.INTERSECTEDY_FIELD_NUMBER:
  366. cy = codedIS.readSInt32();
  367. break;
  368. default:
  369. skipUnknownField(nt);
  370. }
  371. }
  372. codedIS.popLimit(nold);
  373. if (s2 == null) {
  374. // find all intersections
  375. if (st1 == s.getIndexInCity() && st2 != -1 && st2 < cityStreets.length && cityStreets[st2] != null) {
  376. streets.add(cityStreets[st2]);
  377. } else if (st2 == s.getIndexInCity() && st1 != -1 && st1 < cityStreets.length && cityStreets[st1] != null) {
  378. streets.add(cityStreets[st1]);
  379. }
  380. } else {
  381. if((st1 == s.getIndexInCity() && st2 == s2.getIndexInCity() ) ||
  382. (st2 == s.getIndexInCity() && st1 == s2.getIndexInCity())) {
  383. int x = (int) (MapUtils.getTileNumberX(24, parent.getLongitude()) + cx);
  384. int y = (int) (MapUtils.getTileNumberY(24, parent.getLatitude()) + cy);
  385. codedIS.popLimit(old);
  386. return new LatLon(MapUtils.getLatitudeFromTile(24, y), MapUtils.getLongitudeFromTile(24, x));
  387. }
  388. }
  389. break;
  390. default:
  391. skipUnknownField(t);
  392. }
  393. }
  394. codedIS.popLimit(old);
  395. return null;
  396. }
  397. // do not preload streets in city
  398. protected LatLon findIntersectedStreets(City c, Street s, Street s2, List<Street> streets) throws IOException {
  399. if(s.getIndexInCity() == -1){
  400. return null;
  401. }
  402. codedIS.seek(c.getFileOffset());
  403. int size = codedIS.readRawVarint32();
  404. int old = codedIS.pushLimit(size);
  405. while(true){
  406. int t = codedIS.readTag();
  407. int tag = WireFormat.getTagFieldNumber(t);
  408. switch (tag) {
  409. case 0:
  410. codedIS.popLimit(old);
  411. return null;
  412. case OsmandOdb.CityIndex.INTERSECTIONS_FIELD_NUMBER :
  413. Street[] cityStreets = new Street[c.getStreets().size()];
  414. for(Street st : c.getStreets()){
  415. if(st.getIndexInCity() >= 0 && st.getIndexInCity() < cityStreets.length){
  416. cityStreets[st.getIndexInCity()] = st;
  417. }
  418. }
  419. LatLon ret = readIntersectedStreets(cityStreets, s, s2, c.getLocation(), streets);
  420. codedIS.popLimit(old);
  421. return ret;
  422. default:
  423. skipUnknownField(t);
  424. }
  425. }
  426. }
  427. void readPostcodes(List<PostCode> postcodes, StringMatcher nameMatcher) throws IOException{
  428. while(true){
  429. int t = codedIS.readTag();
  430. int tag = WireFormat.getTagFieldNumber(t);
  431. switch (tag) {
  432. case 0:
  433. return;
  434. case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
  435. int offset = codedIS.getTotalBytesRead();
  436. int length = codedIS.readRawVarint32();
  437. int oldLimit = codedIS.pushLimit(length);
  438. final PostCode postCode = readPostcode(null, offset, false, null);
  439. //TODO support getEnName??
  440. if (nameMatcher == null || nameMatcher.matches(postCode.getName())) {
  441. postcodes.add(postCode);
  442. }
  443. codedIS.popLimit(oldLimit);
  444. break;
  445. default:
  446. skipUnknownField(t);
  447. break;
  448. }
  449. }
  450. }
  451. PostCode findPostcode(String name) throws IOException{
  452. while(true){
  453. int t = codedIS.readTag();
  454. int tag = WireFormat.getTagFieldNumber(t);
  455. switch (tag) {
  456. case 0:
  457. return null;
  458. case OsmandOdb.PostcodesIndex.POSTCODES_FIELD_NUMBER :
  459. int offset = codedIS.getTotalBytesRead();
  460. int length = codedIS.readRawVarint32();
  461. int oldLimit = codedIS.pushLimit(length);
  462. PostCode p = readPostcode(null, offset, true, name);
  463. codedIS.popLimit(oldLimit);
  464. if(p != null){
  465. return p;
  466. }
  467. break;
  468. default:
  469. skipUnknownField(t);
  470. break;
  471. }
  472. }
  473. }
  474. }