Newer
Older
osmCoverage / src / osm / jp / api / Osmdb.java
@hayashi hayashi on 3 May 2018 22 KB fixed: Police
  1. package osm.jp.api;
  2.  
  3. import java.io.*;
  4. import java.sql.Connection;
  5. import java.sql.PreparedStatement;
  6. import java.sql.ResultSet;
  7. import java.sql.SQLException;
  8. import java.sql.SQLIntegrityConstraintViolationException;
  9. import java.sql.SQLSyntaxErrorException;
  10. import jp.co.areaweb.tools.csv.CsvRecord;
  11. import jp.co.areaweb.tools.database.DatabaseTool;
  12. import org.hsqldb.HsqlException;
  13. import org.w3c.dom.NamedNodeMap;
  14. import org.w3c.dom.Node;
  15. import org.w3c.dom.NodeList;
  16.  
  17. public abstract class Osmdb {
  18. public static final String TABLE_NAME = "OSM_EXIST";
  19.  
  20. /*
  21. public static void main(String[] args) throws MalformedURLException, ProtocolException, IOException {
  22. double minlat = 35.13d;
  23. double maxlat = 35.66d;
  24. double minlon = 138.99d;
  25. double maxlon = 139.79d;
  26. //getCapabilities(new File("output.xml"), "highway", "bus_stop", minlat, maxlat, minlon, maxlon);
  27. //getCapabilities(new File("output.xml"), "highway", "disused:bus_stop", minlat, maxlat, minlon, maxlon);
  28. //getCapabilities(new File("output.xml"), "amenity", "bus_station", minlat, maxlat, minlon, maxlon);
  29. //getCapabilities(new File("output.xml"), "public_transport", "platform", minlat, maxlat, minlon, maxlon);
  30. getCapabilities("public_transport", "stop_position", minlat, maxlat, minlon, maxlon, "node");
  31. getCapabilities("amenity", "fuel", minlat, maxlat, minlon, maxlon, "way");
  32. }
  33. */
  34. /**
  35. * 'HSQLDB.table.OSM_EXIST'を新規に作る
  36. * 'HSQLDB.table.AREA_NODE'を新規に作る
  37. * 既にテーブルが存在する時にはERROR
  38. * @param con
  39. * @throws SQLException
  40. */
  41. public static void create(Connection con) throws SQLException {
  42. String createSt;
  43. sql(con, "DROP TABLE IF EXISTS "+ Osmdb.TABLE_NAME +" CASCADE");
  44. sql(con, "DROP INDEX IF EXISTS "+ Osmdb.TABLE_NAME +"_index;");
  45. sql(con, "DROP TABLE IF EXISTS AREA_NODE CASCADE");
  46.  
  47. // 'table.OSM_EXIST'を新規に作る
  48. createSt = "CREATE TABLE "+ Osmdb.TABLE_NAME +" (idref VARCHAR(12) NOT NULL, name VARCHAR(128), lat DOUBLE, lon DOUBLE, score INT, PRIMARY KEY(idref));";
  49. Db.updateSQL(con, createSt);
  50. createSt = "CREATE INDEX "+ Osmdb.TABLE_NAME +"_index ON "+ Osmdb.TABLE_NAME +" (lat, lon);";
  51. Db.updateSQL(con, createSt);
  52.  
  53. // 'table.AREA_NODE'を新規に作る
  54. createSt = "CREATE TABLE AREA_NODE (idref VARCHAR(12) NOT NULL, pid VARCHAR(12), lat DOUBLE, lon DOUBLE);";
  55. Db.updateSQL(con, createSt);
  56. }
  57. static void sql(Connection con, String sql) throws SQLException {
  58. System.out.println(sql);
  59. try (PreparedStatement ps = con.prepareStatement(sql)) {
  60. ps.executeUpdate();
  61. }
  62. catch (SQLSyntaxErrorException e) {
  63. System.out.println("107:"+ e.toString());
  64. if (!(e.toString().startsWith("java.sql.SQLSyntaxErrorException: user lacks privilege or object not found:"))) {
  65. throw e;
  66. }
  67. }
  68. }
  69.  
  70. public static void outputWriter(PrintWriter pw, String text) {
  71. System.out.println("\t" + text);
  72. pw.print(text);
  73. }
  74. public static final int POINT_NO = 0; // 評価ポイント無し→ score=50
  75. public static final int POINT_FIXME = 1; // 評価ポイント|!(fixme=null) → score=1
  76. public static final int POINT_NO_BRAND = 2; // 評価ポイント|brand=null → score=1
  77. public static final int POINT_NO_NAME = 4; // 評価ポイント|name=null → score=1
  78. public static final int POINT_BUS_NO = 8; // 評価ポイント|!(bus=yes) → score=0
  79. /**
  80. * 'table.OSM_EXIST'の内容をCSV形式にして標準出力に出力する
  81. * @param hsqldb
  82. * @throws java.sql.SQLException
  83. */
  84. public static void export(Connection hsqldb) throws SQLException {
  85. String header = "idref,lat,lon,score";
  86. System.out.println("TABLE: "+ TABLE_NAME);
  87. System.out.println(header);
  88. PreparedStatement ps8 = hsqldb.prepareStatement("SELECT idref,lat,lon,score FROM "+ TABLE_NAME);
  89. try (ResultSet rset8 = ps8.executeQuery()) {
  90. while (rset8.next()) {
  91. String idcode = rset8.getString(1);
  92. Double lat = rset8.getDouble(2);
  93. Double lon = rset8.getDouble(3);
  94. int score = rset8.getInt(4);
  95. System.out.println("OSM: "+ idcode +","+ lat +","+ lon +","+ score);
  96. }
  97. }
  98. }
  99.  
  100. public int importExistingNode(Connection hsqldb, Connection osmdb, ResultSet rset, int point) throws IOException, SQLException {
  101. String osmidStr = rset.getString("osm_id");
  102. String latStr = rset.getString("lat");
  103. String lonStr = rset.getString("lon");
  104. String brandStr = rset.getString("brand");
  105. String nameStr = rset.getString("name");
  106. String fixmeStr = "";
  107.  
  108. int score = 50;
  109. if (((point & POINT_NO_BRAND) != 0) && isNull(brandStr)) {
  110. score = 1;
  111. }
  112. if (((point & POINT_NO_NAME) != 0) && isNull(nameStr)) {
  113. score = 1;
  114. }
  115. boolean fixme = false;
  116. boolean busYes = false;
  117. if (((point & (POINT_FIXME | POINT_BUS_NO)) != 0)) {
  118. PreparedStatement ps8 = osmdb.prepareStatement("SELECT * FROM planet_osm_nodes where id='"+ osmidStr +"'");
  119. try (ResultSet rset8 = ps8.executeQuery()) {
  120. while (rset8.next()) {
  121. String tags = rset8.getString("tags");
  122. if (tags != null) {
  123. tags = tags.substring(1);
  124. tags = tags.substring(0, tags.length()-1);
  125. CsvRecord csv = new CsvRecord();
  126. csv.analizeRecord(tags);
  127. boolean key = true;
  128. boolean bus = false;
  129. for (String str : csv) {
  130. if (key) {
  131. if (str.startsWith("fixme")) {
  132. fixme = true;
  133. }
  134. if (str.equals("bus")) {
  135. bus = true;
  136. }
  137. key = false;
  138. }
  139. else {
  140. if (bus) {
  141. if (str.equals("yes")) {
  142. busYes = true;
  143. }
  144. bus = false;
  145. }
  146. key = true;
  147. }
  148. }
  149. System.out.println(tags);
  150. }
  151. }
  152. }
  153. if (((point & POINT_FIXME) != 0) && fixme) {
  154. score = 1;
  155. }
  156. if (((point & POINT_BUS_NO) != 0) && !busYes) {
  157. score = 0;
  158. }
  159. }
  160. if (score > 0) {
  161. // idref と brandStr をデータベースに格納する
  162. System.out.println("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES ("+ osmidStr +","+ latStr +","+ lonStr+","+ Integer.toString(score) +",'"+ nameStr +"')N");
  163. try (PreparedStatement ps5 = hsqldb.prepareStatement("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES (?,?,?,?,?)")) {
  164. ps5.setString(1, osmidStr);
  165. ps5.setDouble(2, Double.parseDouble(latStr));
  166. ps5.setDouble(3, Double.parseDouble(lonStr));
  167. ps5.setInt(4, score);
  168. ps5.setString(5, nameStr);
  169. ps5.executeUpdate();
  170. return 1;
  171. }
  172. catch (HsqlException | SQLIntegrityConstraintViolationException e) {
  173. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  174. // [HsqlException]は、無視する
  175. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  176. // [SQLIntegrityConstraintViolationException]は、無視する
  177. }
  178. }
  179.  
  180. return 0;
  181. }
  182.  
  183. /**
  184. * File(HttpPOST.EXIST_FILE)を読み取って、データベースに反映させる。<br>
  185. * その際に、OSMノードを評価し、scoreを算定する
  186. *
  187. * @param hsqldb 反映先のデータベースコネクタ(HSQLDB)
  188. * @param sqlWhere POI条件
  189. * @param point 評価ポイント[POINT_NO|POINT_BRAND|POINT_NAME] 1: 'brand' 2:'name'
  190. * @throws Exception エラー
  191. */
  192. public void readExisting(Connection hsqldb, String sqlWhere, int point) throws Exception {
  193. Connection osmdb = null;
  194. long counter = 0L;
  195. try {
  196. osmdb = DatabaseTool.openDb("osmdb");
  197. String sqlSelect = "osm_id,brand,disused,name,ST_Y(ST_Transform(way,4326)) as lat,ST_X(ST_Transform(way,4326)) as lon";
  198. String sqlNode = String.format("SELECT %s FROM planet_osm_point %s", sqlSelect, sqlWhere);
  199. System.out.println(sqlNode);
  200. PreparedStatement ps1 = osmdb.prepareStatement(sqlNode);
  201. try (ResultSet rset1 = ps1.executeQuery()) {
  202. while (rset1.next()) {
  203. counter += importExistingNode(hsqldb, osmdb, rset1, point);
  204. }
  205. }
  206. sqlSelect = "osm_id,brand,disused,name,ST_Y(ST_Transform(ST_Centroid(way),4326)) as lat,ST_X(ST_Transform(ST_Centroid(way),4326)) as lon";
  207. String sqlArea = String.format("SELECT %s FROM planet_osm_polygon %s", sqlSelect, sqlWhere);
  208. System.out.println(sqlArea);
  209.  
  210. PreparedStatement ps2 = osmdb.prepareStatement(sqlArea);
  211. try (ResultSet rset2 = ps2.executeQuery()) {
  212. while (rset2.next()) {
  213. counter += importExistingNode(hsqldb, osmdb, rset2, point);
  214. }
  215. }
  216.  
  217. System.out.println("Exists Node count = " + counter);
  218. }
  219. finally {
  220. DatabaseTool.closeDb(osmdb);
  221. }
  222. }
  223.  
  224. /**
  225. *
  226. * SELECT
  227. * planet_osm_nodes.id,
  228. * planet_osm_nodes.tags
  229. * planet_osm_nodes.way --> lat & lon
  230. * FROM
  231. * public.planet_osm_point,
  232. * public.planet_osm_nodes
  233. * WHERE (
  234. * planet_osm_point.osm_id = planet_osm_nodes.id
  235. * and 'disused:amenity'=ANY(planet_osm_nodes.tags)
  236. * and 'fuel'=ANY(planet_osm_nodes.tags)
  237. * )
  238. *
  239. * @param hsqldb
  240. * @param kStr
  241. * @param vStr
  242. * @param point
  243. * @throws Exception
  244. */
  245. public void readExistingSub(Connection hsqldb, String kStr, String vStr, int point) throws Exception {
  246. Connection osmdb = null;
  247. long counter = 0L;
  248. try {
  249. osmdb = DatabaseTool.openDb("osmdb");
  250. String sqlSelect = "SELECT tags,id,ST_Y(ST_Transform(way,4326)) as lat,ST_X(ST_Transform(way,4326)) as lon";
  251. String sqlWhere = String.format("WHERE (osm_id=id AND '%s'=ANY(tags) AND '%s'=ANY(tags))", kStr, vStr);
  252. String sql = String.format("%s FROM planet_osm_point,planet_osm_nodes %s", sqlSelect, sqlWhere);
  253. System.out.println(sql);
  254. PreparedStatement ps1 = osmdb.prepareStatement(sql);
  255. try (ResultSet rset1 = ps1.executeQuery()) {
  256. while (rset1.next()) {
  257. String tags = rset1.getString("tags");
  258. String idref = rset1.getString("id");
  259. String latStr = rset1.getString("lat");
  260. String lonStr = rset1.getString("lon");
  261. double lat = Double.valueOf(latStr);
  262. double lon = Double.valueOf(lonStr);
  263. int score = score(point, tags);
  264. //counter += importExistingNode(hsqldb, osmdb, rset1, point);
  265. counter += insertExistingNode(hsqldb, idref, lat, lon, score, "");
  266. }
  267. }
  268. System.out.println("Exists Node count = " + counter);
  269. }
  270. finally {
  271. DatabaseTool.closeDb(osmdb);
  272. }
  273. }
  274. int score(int point, String tags) {
  275. int score = 50;
  276. if (tags == null) {
  277. return score;
  278. }
  279. boolean brandYes = false;
  280. boolean busYes = false;
  281. boolean fixmeYes = false;
  282. boolean nameYes = false;
  283. tags = tags.substring(1);
  284. tags = tags.substring(0, tags.length()-1);
  285. CsvRecord csv = new CsvRecord();
  286. csv.analizeRecord(tags);
  287.  
  288. boolean key = true;
  289. boolean bus = false;
  290. for (String str : csv) {
  291. if (key) {
  292. if (str.startsWith("fixme")) {
  293. fixmeYes = true;
  294. }
  295. else if (str.equals("bus")) {
  296. bus = true;
  297. }
  298. else if (str.equals("brand")) {
  299. brandYes = true;
  300. }
  301. else if (str.startsWith("name")) {
  302. nameYes = true;
  303. }
  304. key = false;
  305. }
  306. else {
  307. if (bus) {
  308. if (str.equals("yes")) {
  309. busYes = true;
  310. }
  311. bus = false;
  312. }
  313. key = true;
  314. }
  315. }
  316. if (((point & POINT_NO_BRAND) != 0) && !brandYes) {
  317. score = 1;
  318. }
  319. if (((point & POINT_NO_NAME) != 0) && !nameYes) {
  320. score = 1;
  321. }
  322. if (((point & POINT_FIXME) != 0) && fixmeYes) {
  323. score = 1;
  324. }
  325. if (((point & POINT_BUS_NO) != 0) && !busYes) {
  326. score = 0;
  327. }
  328. return score;
  329. }
  330.  
  331. /**
  332. *
  333. * @param hsqldb
  334. * @param idref
  335. * @param lat
  336. * @param lon
  337. * @param score
  338. * @param name
  339. * @return
  340. * @throws IOException
  341. * @throws SQLException
  342. */
  343. public int insertExistingNode(Connection hsqldb, String idref, double lat, double lon, int score, String name) throws IOException, SQLException {
  344. // idref と brandStr をデータベースに格納する
  345. String sql = String.format("INSERT INTO %s (idref,lat,lon,score,name) VALUES (%s,%2.7f,%3.7f,%d,%s)",
  346. TABLE_NAME,
  347. idref, lat, lon, score, name);
  348. System.out.println(sql);
  349. sql = String.format("INSERT INTO %s (idref,lat,lon,score,name) VALUES (?,?,?,?,?)", TABLE_NAME);
  350. try (PreparedStatement ps5 = hsqldb.prepareStatement(sql)) {
  351. ps5.setString(1, idref);
  352. ps5.setDouble(2, lat);
  353. ps5.setDouble(3, lon);
  354. ps5.setInt(4, score);
  355. ps5.setString(5, name);
  356. ps5.executeUpdate();
  357. return 1;
  358. }
  359. catch (HsqlException | SQLIntegrityConstraintViolationException e) {
  360. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  361. // [HsqlException]は、無視する
  362. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  363. // [SQLIntegrityConstraintViolationException]は、無視する
  364. }
  365. return 0;
  366. }
  367. boolean isNull(String vstr) {
  368. if (vstr == null) {
  369. return true;
  370. }
  371. return (vstr.trim().length() < 1);
  372. }
  373. int readAreaNodes(Connection con, Node node) throws IOException, SQLException {
  374. int iCounter = 0;
  375.  
  376. NodeList nodes = node.getChildNodes();
  377. for (int i = 0; i < nodes.getLength(); i++) {
  378. Node node2 = nodes.item(i);
  379. switch (node2.getNodeName()) {
  380. case "node":
  381. iCounter++;
  382. importAreaNode(con, node2);
  383. break;
  384. default:
  385. iCounter += readAreaNodes(con, node2);
  386. break;
  387. }
  388. }
  389. return iCounter;
  390. }
  391. void importAreaNode(Connection con, Node node) throws IOException, SQLException {
  392. String idrefStr = "";
  393. String latStr = "";
  394. String lonStr = "";
  395.  
  396. NodeList nodes = node.getChildNodes();
  397. if (nodes.getLength() > 0) {
  398. return;
  399. }
  400.  
  401. NamedNodeMap nodeMap = node.getAttributes();
  402. if (nodeMap != null) {
  403. for (int j=0; j < nodeMap.getLength(); j++) {
  404. switch (nodeMap.item(j).getNodeName()) {
  405. case "id":
  406. idrefStr = nodeMap.item(j).getNodeValue();
  407. break;
  408. case "lat":
  409. latStr = nodeMap.item(j).getNodeValue();
  410. break;
  411. case "lon":
  412. lonStr = nodeMap.item(j).getNodeValue();
  413. break;
  414. default:
  415. break;
  416. }
  417. }
  418. // idref と brandStr をデータベースに格納する
  419. System.out.println("insert into AREA_NODE(idref,lat,lon) values("+ idrefStr +","+ latStr +","+ lonStr+")");
  420. try (PreparedStatement ps5 = con.prepareStatement("INSERT INTO AREA_NODE (idref,lat,lon) VALUES (?,?,?)")) {
  421. ps5.setString(1, idrefStr);
  422. ps5.setDouble(2, Double.parseDouble(latStr));
  423. ps5.setDouble(3, Double.parseDouble(lonStr));
  424. ps5.executeUpdate();
  425. }
  426. }
  427. }
  428.  
  429.  
  430.  
  431. void importExistingArea(Connection con, Node node, int point) throws IOException, SQLException {
  432. String idrefStr = "";
  433. double maxlat = -90.0D;
  434. double maxlon = -180.0D;
  435. double minlat = 90.0D;
  436. double minlon = 180.0D;
  437. String nameStr = "";
  438. String brandStr = "";
  439. String fixmeStr = "";
  440.  
  441. NamedNodeMap nodeMap = node.getAttributes();
  442. if (nodeMap != null) {
  443. for (int j=0; j < nodeMap.getLength(); j++) {
  444. switch (nodeMap.item(j).getNodeName()) {
  445. case "id":
  446. idrefStr = nodeMap.item(j).getNodeValue();
  447. break;
  448. default:
  449. break;
  450. }
  451. }
  452.  
  453. NodeList nodes = node.getChildNodes();
  454. for (int i = 0; i < nodes.getLength(); i++) {
  455. Node node2 = nodes.item(i);
  456. if (node2.getNodeName().equals("tag")) {
  457. OsmnodeTag tagnode = new OsmnodeTag(node2);
  458. String value = tagnode.getValue("brand");
  459. if (value != null) {
  460. brandStr = value;
  461. }
  462. value = tagnode.getValue("name:ja");
  463. if (value != null) {
  464. nameStr = value;
  465. }
  466. value = tagnode.getValue("name");
  467. if (value != null) {
  468. nameStr = value;
  469. }
  470. value = tagnode.getValue("fixme");
  471. if (value != null) {
  472. fixmeStr = value;
  473. }
  474. }
  475. else if (node2.getNodeName().equals("nd")) {
  476. OsmnodeNd ndnode = new OsmnodeNd(node2);
  477. String ref = ndnode.getRef();
  478. Position pos = getNdPosition(con, ref);
  479. if (pos != null) {
  480. minlat = (pos.lat < minlat ? pos.lat : minlat);
  481. minlon = (pos.lon < minlon ? pos.lon : minlon);
  482. maxlat = (pos.lat > maxlat ? pos.lat : maxlat);
  483. maxlon = (pos.lon > maxlon ? pos.lon : maxlon);
  484. }
  485. }
  486. }
  487. if ((maxlat != -90.0D) && (maxlon != -180.0D) && (minlon != 180.0D) && (minlat != 90.0D)) {
  488. double lat = (maxlat + minlat) / 2;
  489. double lon = (maxlon + minlon) / 2;
  490. int score = 50;
  491.  
  492. if (((point & POINT_NO_BRAND) != 0) && brandStr.equals("")) {
  493. score = 1;
  494. }
  495. if (((point & POINT_NO_NAME) != 0) && nameStr.equals("")) {
  496. score = 1;
  497. }
  498. if (((point & POINT_FIXME) != 0) && !fixmeStr.equals("")) {
  499. score = 1;
  500. }
  501.  
  502. // idref と nameStr をデータベースに格納する
  503. System.out.println("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES("+ idrefStr +","+ lat +","+ lon+","+ Integer.toString(score) +",'"+ nameStr +"');");
  504. try (PreparedStatement ps5 = con.prepareStatement("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES (?,?,?,?,?)")) {
  505. ps5.setString(1, idrefStr);
  506. ps5.setDouble(2, lat);
  507. ps5.setDouble(3, lon);
  508. ps5.setInt(4, score);
  509. ps5.setString(5, nameStr);
  510. ps5.executeUpdate();
  511. }
  512. catch (HsqlException | SQLIntegrityConstraintViolationException e) {
  513. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  514. // [HsqlException]は、無視する
  515. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  516. // [SQLIntegrityConstraintViolationException]は、無視する
  517. }
  518. }
  519. }
  520. }
  521. static Position getNdPosition(Connection con, String idref) throws SQLException {
  522. PreparedStatement ps8 = con.prepareStatement("SELECT lat,lon FROM AREA_NODE where idref=?");
  523. ps8.setString(1, idref);
  524. try (ResultSet rset8 = ps8.executeQuery()) {
  525. while (rset8.next()) {
  526. Double lat = rset8.getDouble(1);
  527. Double lon = rset8.getDouble(2);
  528. return new Position(lat,lon);
  529. }
  530. }
  531. return null;
  532. }
  533. }