Newer
Older
osmCoverage / src / osm / jp / api / HttpPOST.java
@hayashi hayashi on 7 Oct 2017 21 KB busstop完成
  1. package osm.jp.api;
  2.  
  3. import java.net.*;
  4. import java.util.List;
  5. import java.util.Map;
  6. import java.util.concurrent.TimeUnit;
  7. import java.io.*;
  8. import java.sql.Connection;
  9. import java.sql.PreparedStatement;
  10. import java.sql.ResultSet;
  11. import java.sql.SQLException;
  12. import java.sql.SQLIntegrityConstraintViolationException;
  13. import java.sql.SQLSyntaxErrorException;
  14. import javax.xml.parsers.DocumentBuilder;
  15. import javax.xml.parsers.DocumentBuilderFactory;
  16. import javax.xml.parsers.ParserConfigurationException;
  17. import org.hsqldb.HsqlException;
  18. import org.w3c.dom.NamedNodeMap;
  19. import org.w3c.dom.Node;
  20. import org.w3c.dom.NodeList;
  21. import org.xml.sax.SAXException;
  22.  
  23. /**
  24. * Java HTTP クライアントサンプル - HttpURLConnection 版 -
  25. *
  26. * @author 68user http://X68000.q-e-d.net/~68user/
  27. */
  28. public class HttpPOST {
  29. //public static String host = "http://api06.dev.openstreetmap.org";
  30. //public static String host = "http://api.openstreetmap.org";
  31. public static String host = "http://overpass-api.de";
  32. public static final String EXIST_FILE = "exist.osm.xml";
  33. public static final String TABLE_NAME = "OSM_EXIST";
  34.  
  35. public static void main(String[] args) throws MalformedURLException, ProtocolException, IOException {
  36. double minlat = 35.13d;
  37. double maxlat = 35.66d;
  38. double minlon = 138.99d;
  39. double maxlon = 139.79d;
  40. //getCapabilities(new File("output.xml"), "highway", "bus_stop", minlat, maxlat, minlon, maxlon);
  41. //getCapabilities(new File("output.xml"), "highway", "disused:bus_stop", minlat, maxlat, minlon, maxlon);
  42. //getCapabilities(new File("output.xml"), "amenity", "bus_station", minlat, maxlat, minlon, maxlon);
  43. //getCapabilities(new File("output.xml"), "public_transport", "platform", minlat, maxlat, minlon, maxlon);
  44. getCapabilities("public_transport", "stop_position", minlat, maxlat, minlon, maxlon, "node");
  45. getCapabilities("amenity", "fuel", minlat, maxlat, minlon, maxlon, "way");
  46. }
  47. /**
  48. * 'HSQLDB.table.OSM_EXIST'を新規に作る
  49. * 'HSQLDB.table.AREA_NODE'を新規に作る
  50. * 既にテーブルが存在する時にはERROR
  51. * @param con
  52. * @throws SQLException
  53. */
  54. public static void create(Connection con) throws SQLException {
  55. String createSt;
  56. sql(con, "DROP TABLE IF EXISTS "+ HttpPOST.TABLE_NAME +" CASCADE");
  57. //sql(con, "DROP INDEX "+ HttpPOST.TABLE_NAME +"_index;");
  58. sql(con, "DROP TABLE IF EXISTS AREA_NODE CASCADE");
  59.  
  60. // 'table.FUEL_EXIST'を新規に作る
  61. createSt = "CREATE TABLE "+ HttpPOST.TABLE_NAME +" (idref VARCHAR(12) NOT NULL, name VARCHAR(128), lat DOUBLE, lon DOUBLE, score INT, PRIMARY KEY(idref));";
  62. Db.updateSQL(con, createSt);
  63. createSt = "CREATE INDEX "+ HttpPOST.TABLE_NAME +"_index ON "+ HttpPOST.TABLE_NAME +" (lat, lon);";
  64. Db.updateSQL(con, createSt);
  65.  
  66. // 'table.AREA_NODE'を新規に作る
  67. createSt = "CREATE TABLE AREA_NODE (idref VARCHAR(12) NOT NULL, pid VARCHAR(12), lat DOUBLE, lon DOUBLE);";
  68. Db.updateSQL(con, createSt);
  69. }
  70. public static void sql(Connection con, String sql) throws SQLException {
  71. System.out.println(sql);
  72. try (PreparedStatement ps = con.prepareStatement(sql)) {
  73. ps.executeUpdate();
  74. }
  75. catch (SQLSyntaxErrorException e) {
  76. System.out.println("107:"+ e.toString());
  77. if (!(e.toString().startsWith("java.sql.SQLSyntaxErrorException: user lacks privilege or object not found:"))) {
  78. throw e;
  79. }
  80. }
  81. }
  82.  
  83. public static void getCapabilities(String key, String value, double minLat, double maxLat, double minLon, double maxLon) throws MalformedURLException, ProtocolException, IOException {
  84. getCapabilities(key, value, minLat, maxLat, minLon, maxLon, "node");
  85. }
  86.  
  87. public static void getCapabilities(String key, String value, double minLat, double maxLat, double minLon, double maxLon, String type) throws MalformedURLException, ProtocolException, IOException {
  88. StringBuilder queryText = new StringBuilder();
  89. queryText.append("<osm-script timeout=\"900\" element-limit=\"1073741824\">");
  90. queryText.append(" <union>");
  91. queryText.append(" <query type=\""+ type +"\">");
  92. queryText.append(" <has-kv k=\""+ key +"\" v=\""+ value +"\"/>");
  93. queryText.append(" <bbox-query s=\"" + minLat + "\" n=\"" + maxLat + "\" w=\"" + minLon + "\" e=\"" + maxLon + "\"/>");
  94. queryText.append(" </query>");
  95. queryText.append(" </union>");
  96. queryText.append(" <print/>");
  97. queryText.append("</osm-script>");
  98. getQuery(queryText.toString());
  99. }
  100.  
  101. /**
  102. *
  103. * @param queryText クエリテキスト(Overpass_API/Overpass_QL)
  104. * @throws MalformedURLException
  105. * @throws ProtocolException
  106. * @throws IOException
  107. */
  108. public static void getQuery(String queryText) throws MalformedURLException, ProtocolException, IOException {
  109. System.out.println(host + "/api/interpreter");
  110. URL url = new URL(host + "/api/interpreter");
  111. int responsecode = 0;
  112.  
  113. do {
  114. HttpURLConnection urlconn = (HttpURLConnection)url.openConnection();
  115. try {
  116. urlconn.setRequestMethod("POST");
  117. urlconn.setDoOutput(true); // POSTのデータを後ろに付ける
  118. urlconn.setInstanceFollowRedirects(false); // 勝手にリダイレクトさせない
  119. urlconn.setRequestProperty("Accept-Language", "ja;q=0.7,en;q=0.3");
  120. urlconn.setRequestProperty("Content-Type","text/xml;charset=utf-8");
  121. urlconn.connect();
  122.  
  123. try (PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(urlconn.getOutputStream(), "utf-8")))) {
  124. outputWriter(pw, queryText);
  125. pw.flush();
  126. }
  127.  
  128. try {
  129. TimeUnit.SECONDS.sleep(1);
  130. } catch (InterruptedException e) {}
  131.  
  132. responsecode = urlconn.getResponseCode();
  133. System.out.println("レスポンスコード[" + responsecode + "] " +
  134. "レスポンスメッセージ[" + urlconn.getResponseMessage() + "]");
  135. Map<String,List<String>> headers = urlconn.getHeaderFields();
  136. for (Map.Entry<String, List<String>> bar : headers.entrySet()) {
  137. System.out.print("\t" + bar.getKey() +"\t: "); // キーを取得
  138. List<String> vals = bar.getValue(); // 値を取得
  139. for(String str : vals) {
  140. System.out.print("["+ str +"],");
  141. }
  142. System.out.println();
  143. }
  144. if ((responsecode == 429) || (responsecode == 504) || (responsecode == 500)) {
  145. // レスポンスコード[429] レスポンスメッセージ[Too Many Requests]
  146. // レスポンスコード[500] レスポンスメッセージ[Internal server error]
  147. // レスポンスコード[504] レスポンスメッセージ[Gateway Timeout]
  148. try {
  149. TimeUnit.MINUTES.sleep(5);
  150. } catch (InterruptedException e) {}
  151. }
  152. else {
  153. System.out.println("\n---- ボディ ----");
  154.  
  155. File oFile = new File(HttpPOST.EXIST_FILE);
  156. oFile.deleteOnExit();
  157. try (
  158. BufferedWriter hw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(oFile), "UTF-8"));
  159. BufferedReader reader = new BufferedReader(new InputStreamReader(urlconn.getInputStream(), "UTF-8"))
  160. ) {
  161. while (true) {
  162. String line = reader.readLine();
  163. if (line == null) {
  164. break;
  165. }
  166. hw.write(line);
  167. hw.newLine();
  168. }
  169. hw.flush();
  170. }
  171. }
  172. }
  173. catch (java.net.ConnectException e) {
  174. // レスポンスコード[600] レスポンスメッセージ[接続がタイムアウトしました (Connection timed out)]
  175. responsecode = 600;
  176. }
  177. finally {
  178. urlconn.disconnect();
  179. }
  180. try {
  181. TimeUnit.SECONDS.sleep(5);
  182. } catch (InterruptedException e) {}
  183. }
  184. while ((responsecode == 429) || (responsecode == 504) || (responsecode == 600));
  185. }
  186. public static void outputWriter(PrintWriter pw, String text) {
  187. System.out.println("\t" + text);
  188. pw.print(text);
  189. }
  190. /**
  191. *
  192. * @param con
  193. * @param point 1: 'brand' 2:'name'
  194. * @throws FileNotFoundException
  195. * @throws ClassNotFoundException
  196. * @throws SQLException
  197. * @throws IOException
  198. * @throws ParserConfigurationException
  199. * @throws SAXException
  200. */
  201. public static void readExistingFile (Connection con, int point) throws FileNotFoundException, ClassNotFoundException, SQLException, IOException, ParserConfigurationException, SAXException {
  202. int iCounter = 0;
  203.  
  204. DocumentBuilderFactory factory;
  205. DocumentBuilder builder;
  206.  
  207. iCounter = 0;
  208. factory = DocumentBuilderFactory.newInstance();
  209. builder = factory.newDocumentBuilder();
  210. factory.setIgnoringElementContentWhitespace(true);
  211. factory.setIgnoringComments(true);
  212. factory.setValidating(true);
  213.  
  214. Node root = builder.parse(new File(HttpPOST.EXIST_FILE));
  215.  
  216. readAreaNodes(con, root);
  217. iCounter += readExistingNodes(con, root, point);
  218. System.out.println("既存ノード数["+ iCounter +"]");
  219. }
  220. static int readAreaNodes(Connection con, Node node) throws IOException, SQLException {
  221. int iCounter = 0;
  222.  
  223. NodeList nodes = node.getChildNodes();
  224. for (int i = 0; i < nodes.getLength(); i++) {
  225. Node node2 = nodes.item(i);
  226. switch (node2.getNodeName()) {
  227. case "node":
  228. iCounter++;
  229. importAreaNode(con, node2);
  230. break;
  231. default:
  232. iCounter += readAreaNodes(con, node2);
  233. break;
  234. }
  235. }
  236. return iCounter;
  237. }
  238. static void importAreaNode(Connection con, Node node) throws IOException, SQLException {
  239. String idrefStr = "";
  240. String latStr = "";
  241. String lonStr = "";
  242.  
  243. NodeList nodes = node.getChildNodes();
  244. if (nodes.getLength() > 0) {
  245. return;
  246. }
  247.  
  248. NamedNodeMap nodeMap = node.getAttributes();
  249. if (nodeMap != null) {
  250. for (int j=0; j < nodeMap.getLength(); j++) {
  251. switch (nodeMap.item(j).getNodeName()) {
  252. case "id":
  253. idrefStr = nodeMap.item(j).getNodeValue();
  254. break;
  255. case "lat":
  256. latStr = nodeMap.item(j).getNodeValue();
  257. break;
  258. case "lon":
  259. lonStr = nodeMap.item(j).getNodeValue();
  260. break;
  261. default:
  262. break;
  263. }
  264. }
  265. // idref と brandStr をデータベースに格納する
  266. System.out.println("insert into AREA_NODE(idref,lat,lon) values("+ idrefStr +","+ latStr +","+ lonStr+")");
  267. try (PreparedStatement ps5 = con.prepareStatement("INSERT INTO AREA_NODE (idref,lat,lon) VALUES (?,?,?)")) {
  268. ps5.setString(1, idrefStr);
  269. ps5.setDouble(2, Double.parseDouble(latStr));
  270. ps5.setDouble(3, Double.parseDouble(lonStr));
  271. ps5.executeUpdate();
  272. }
  273. }
  274. }
  275.  
  276. static int readExistingNodes(Connection con, Node node, int point) throws IOException, SQLException {
  277. int iCounter = 0;
  278.  
  279. NodeList nodes = node.getChildNodes();
  280. for (int i = 0; i < nodes.getLength(); i++) {
  281. Node node2 = nodes.item(i);
  282. switch (node2.getNodeName()) {
  283. case "node":
  284. iCounter++;
  285. importExistingNode(con, node2, point);
  286. break;
  287. case "way":
  288. iCounter++;
  289. importExistingArea(con, node2, point);
  290. break;
  291. default:
  292. iCounter += readExistingNodes(con, node2, point);
  293. break;
  294. }
  295. }
  296. return iCounter;
  297. }
  298.  
  299. static void importExistingArea(Connection con, Node node, int point) throws IOException, SQLException {
  300. String idrefStr = "";
  301. double maxlat = -90.0D;
  302. double maxlon = -180.0D;
  303. double minlat = 90.0D;
  304. double minlon = 180.0D;
  305. String nameStr = "";
  306. String brandStr = "";
  307. String fixmeStr = "";
  308. int score = 0;
  309.  
  310. NamedNodeMap nodeMap = node.getAttributes();
  311. if (nodeMap != null) {
  312. for (int j=0; j < nodeMap.getLength(); j++) {
  313. switch (nodeMap.item(j).getNodeName()) {
  314. case "id":
  315. idrefStr = nodeMap.item(j).getNodeValue();
  316. break;
  317. default:
  318. break;
  319. }
  320. }
  321.  
  322. NodeList nodes = node.getChildNodes();
  323. for (int i = 0; i < nodes.getLength(); i++) {
  324. Node node2 = nodes.item(i);
  325. if (node2.getNodeName().equals("tag")) {
  326. OsmnodeTag tagnode = new OsmnodeTag(node2);
  327. String value = null;
  328. value = tagnode.getValue("brand");
  329. if (value != null) {
  330. brandStr = value;
  331. }
  332. value = tagnode.getValue("name:ja");
  333. if (value != null) {
  334. nameStr = value;
  335. }
  336. value = tagnode.getValue("name");
  337. if (value != null) {
  338. nameStr = value;
  339. }
  340. value = tagnode.getValue("fixme");
  341. if (value != null) {
  342. fixmeStr = value;
  343. }
  344. }
  345. else if (node2.getNodeName().equals("nd")) {
  346. OsmnodeNd ndnode = new OsmnodeNd(node2);
  347. String ref = ndnode.getRef();
  348. Position pos = getNdPosition(con, ref);
  349. if (pos != null) {
  350. minlat = (pos.lat < minlat ? pos.lat : minlat);
  351. minlon = (pos.lon < minlon ? pos.lon : minlon);
  352. maxlat = (pos.lat > maxlat ? pos.lat : maxlat);
  353. maxlon = (pos.lon > maxlon ? pos.lon : maxlon);
  354. }
  355. }
  356. }
  357. if ((maxlat != -90.0D) && (maxlon != -180.0D) && (minlon != 180.0D) && (minlat != 90.0D)) {
  358. double lat = (maxlat + minlat) / 2;
  359. double lon = (maxlon + minlon) / 2;
  360.  
  361. score = 50;
  362. if ((point == 2) && nameStr.equals("")) {
  363. score = 1;
  364. }
  365. if ((point == 1) && brandStr.equals("")) {
  366. score = 1;
  367. }
  368. if (!fixmeStr.equals("")) {
  369. score = 1;
  370. }
  371.  
  372. // idref と nameStr をデータベースに格納する
  373. System.out.println("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES("+ idrefStr +","+ lat +","+ lon+","+ Integer.toString(score) +",'"+ nameStr +"');");
  374. try (PreparedStatement ps5 = con.prepareStatement("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES (?,?,?,?,?)")) {
  375. ps5.setString(1, idrefStr);
  376. ps5.setDouble(2, lat);
  377. ps5.setDouble(3, lon);
  378. ps5.setInt(4, score);
  379. ps5.setString(5, nameStr);
  380. ps5.executeUpdate();
  381. }
  382. catch (HsqlException | SQLIntegrityConstraintViolationException e) {
  383. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  384. // [HsqlException]は、無視する
  385. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  386. // [SQLIntegrityConstraintViolationException]は、無視する
  387. }
  388. }
  389. }
  390. }
  391.  
  392. static void importExistingNode(Connection con, Node node, int point) throws IOException, SQLException {
  393. String idrefStr = "";
  394. String latStr = "";
  395. String lonStr = "";
  396. String brandStr = "";
  397. String nameStr = "";
  398. String fixmeStr = "";
  399. int score = 0;
  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.  
  419. NodeList nodes = node.getChildNodes();
  420. if (nodes.getLength() == 0) {
  421. return;
  422. }
  423. for (int i = 0; i < nodes.getLength(); i++) {
  424. Node node2 = nodes.item(i);
  425. if (node2.getNodeName().equals("tag")) {
  426. OsmnodeTag tagnode = new OsmnodeTag(node2);
  427. String value = null;
  428. value = tagnode.getValue("brand");
  429. if (value != null) {
  430. brandStr = value;
  431. }
  432. value = tagnode.getValue("name");
  433. if (value != null) {
  434. nameStr = value;
  435. }
  436. value = tagnode.getValue("name:ja");
  437. if (value != null) {
  438. nameStr = value;
  439. }
  440. value = tagnode.getValue("fixme");
  441. if (value != null) {
  442. fixmeStr = value;
  443. }
  444. }
  445. }
  446.  
  447. score = 50;
  448. if ((point == 2) && nameStr.equals("")) {
  449. score = 1;
  450. }
  451. if ((point == 1) && brandStr.equals("")) {
  452. score = 1;
  453. }
  454. if (!fixmeStr.equals("")) {
  455. score = 1;
  456. }
  457. // idref と brandStr をデータベースに格納する
  458. System.out.println("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES ("+ idrefStr +","+ latStr +","+ lonStr+","+ Integer.toString(score) +",'"+ nameStr +"')N");
  459. try (PreparedStatement ps5 = con.prepareStatement("INSERT INTO "+ TABLE_NAME +" (idref,lat,lon,score,name) VALUES (?,?,?,?,?)")) {
  460. ps5.setString(1, idrefStr);
  461. ps5.setDouble(2, Double.parseDouble(latStr));
  462. ps5.setDouble(3, Double.parseDouble(lonStr));
  463. ps5.setInt(4, score);
  464. ps5.setString(5, nameStr);
  465. ps5.executeUpdate();
  466. }
  467. catch (HsqlException | SQLIntegrityConstraintViolationException e) {
  468. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  469. // [HsqlException]は、無視する
  470. // integrity constraint violation: unique constraint or index violation; SYS_PK_10069 table: FUEL_EXIST
  471. // [SQLIntegrityConstraintViolationException]は、無視する
  472. }
  473. }
  474. }
  475. public static Position getNdPosition(Connection con, String idref) throws SQLException {
  476. PreparedStatement ps8 = con.prepareStatement("SELECT lat,lon FROM AREA_NODE where idref=?");
  477. ps8.setString(1, idref);
  478. try (ResultSet rset8 = ps8.executeQuery()) {
  479. while (rset8.next()) {
  480. Double lat = rset8.getDouble(1);
  481. Double lon = rset8.getDouble(2);
  482. return new Position(lat,lon);
  483. }
  484. }
  485. return null;
  486. }
  487. }