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