Newer
Older
osmCoverage / src / osm / jp / coverage / busstop / DbBusstop.java
package osm.jp.coverage.busstop;

import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLSyntaxErrorException;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import jp.co.areaweb.tools.database.*;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class DbBusstop {
    public static final String TABLE_NAME = "bus_stop";
    public static boolean DROP = false;

    File inputFile;
    String filter = "";
    int iCounter = 0;
    String urlStr = "";
    Connection con;
    String timeStampStr = null;
    File dir = null;

    /** メイン  
     * 動作条件; HSQLDBのフォルダを削除した状態で実行すること。  
     *         フォルダを削除しないで実行する場合は「-DROP」オプションを使うこと  
     * @param args
     * @throws IOException
     * @throws SQLException
     * @throws ClassNotFoundException
     * @throws FileNotFoundException
     * @throws javax.xml.parsers.ParserConfigurationException
     * @throws org.xml.sax.SAXException */
    public static void main(String[] args) throws FileNotFoundException, ClassNotFoundException, IOException, SQLException, ParserConfigurationException, SAXException 
    {
        for (String arg : args) {
            if (arg.toUpperCase().equals("-DROP")) {
                DROP = true;
            }
        }
        
        // HSQLディレクトリがなければエラー
        File dbdir = new File("database");
        if (!dbdir.isDirectory()) {
            throw new FileNotFoundException("Directory 'database' is not found.");
        }
        
        Connection conHsql = null;
        try {
            conHsql = DatabaseTool.openDb("database");
            if (DROP) {
                dropTable(conHsql);
            }
            create(conHsql);
            try (PreparedStatement ps = conHsql.prepareStatement("DELETE FROM "+ TABLE_NAME)) {
                ps.executeUpdate();
            }
            
            /**
             * 都道府県ごとのGMLディレクトリの処理
             */
            int fcounter = 0;
            File dir = new File("GML_BUSSTOP");
            for (File gmldir : dir.listFiles()) {
                if (checkGMLdir(gmldir)) {
                    // GMLディレクトリを処理する
                    int areacode = Integer.parseInt(gmldir.getName().substring(GML_DIR_PREFIX.length(), GML_DIR_PREFIX.length()+2));
                    File[] files = gmldir.listFiles();
                    for (File iFile : files) {
                        // 対象のファイルが「数値地図情報のGMLデータファイル」の時のみ処理を行う。
                        if (checkFile(iFile, areacode)) {
                            importBusstop(conHsql, iFile, areacode);
                            fcounter++;
                        }
                    }
                }
            }
            System.out.println("["+ fcounter +"]つのGMLファイルをインポートしました。");

            DbBusstop.export(conHsql);
        }
        finally {
            if (conHsql != null) {
                DatabaseTool.closeDb(conHsql);
            }
        }
    }
    
    /**
     * 数値地図情報のGMLデータファイルを読み取ってローカルベータベースへ記録する
     * @param conHsql
     * @param iFile
     * @param areacode
     * @throws FileNotFoundException
     * @throws ClassNotFoundException
     * @throws SQLException
     * @throws IOException
     * @throws ParserConfigurationException 
     * @throws SAXException 
     */
    public static void importBusstop (Connection conHsql, File iFile, int areacode) throws FileNotFoundException, ClassNotFoundException, SQLException, IOException, ParserConfigurationException, SAXException {
        int iCounter = 0;
        String timeStampStr = null;

        String iStr = iFile.getName();

        DocumentBuilderFactory factory;
        DocumentBuilder        builder;
        Node root;

        factory = DocumentBuilderFactory.newInstance();
        builder = factory.newDocumentBuilder();
        factory.setIgnoringElementContentWhitespace(true);
        factory.setIgnoringComments(true);
        factory.setValidating(true);
        root    = builder.parse(iFile);

        iCounter += showNodes(conHsql, root, iStr.substring(0, iStr.length() - 4), areacode);
        System.out.println("("+ areacode +") バス停数["+ iCounter +"]");
    }
    
    /**
     *
     * @param con
     * @param node
     * @param iFileName		// ソースファイル名(拡張子を含まない)
     * @param areacode
     * @return
     * @throws IOException
     * @throws SQLException
     */
    public static int showNodes(Connection con, Node node, String iFileName, int areacode) throws IOException, SQLException {
        int iCounter = 0;
        NodeList nodes = node.getChildNodes();
        for (int i=0; i<nodes.getLength(); i++) {
            Node node2 = nodes.item(i);
            switch (node2.getNodeName()) {
                case "gml:Point":
                    showGmlPoint(con, node2, areacode);
                    break;
                case "ksj:BusStop":
                    iCounter++;
                    showBusStop(con, node2, iFileName);
                    break;
                default:
                    iCounter += showNodes(con, node2, iFileName, areacode);
                    break;
            }
        }
        return iCounter;
    }

    /*
    public static void showGmPoint(Connection con, Node node) throws IOException, SQLException {
        String positionStr = "";
        String latStr = "";
        String lonStr = "";
        String idStr = "";

        NamedNodeMap nodeMap = node.getAttributes();
        if ( null != nodeMap ) {
            for ( int j=0; j<nodeMap.getLength(); j++ ) {
                if (nodeMap.item(j).getNodeName().equals("id")) {
                    idStr = nodeMap.item(j).getNodeValue();
                }
            }
        }

        NodeList nodes = node.getChildNodes();
        for (int i=0; i < nodes.getLength(); i++) {
            Node node2 = nodes.item(i);
            if (node2.getNodeName().equals("jps:GM_Point.position")) {
                NodeList nodes3 = node2.getChildNodes();
                for (int j=0; j < nodes3.getLength(); j++) {
                    Node node3 = nodes3.item(j);
                    if (node3.getNodeName().equals("jps:DirectPosition")) {
                        NodeList nodes4 = node3.getChildNodes();
                        for (int k=0; k < nodes4.getLength(); k++) {
                            Node node4 = nodes4.item(k);
                            if (node4.getNodeName().equals("DirectPosition.coordinate")) {
                                positionStr = node4.getTextContent();
                                String[] str4Ary = positionStr.split(" ");
                                latStr = str4Ary[0];
                                lonStr = str4Ary[1];
                                break;
                            }
                        }
                        break;
                    }
                }

                try (PreparedStatement ps6 = con.prepareStatement("UPDATE bus_stop SET lat=?,lon=?,fixed=? WHERE gmlid=?")) {
                    double lat = Double.parseDouble(latStr);
                    double lon = Double.parseDouble(lonStr);
                    ps6.setDouble(1, lat);
                    ps6.setDouble(2, lon);
                    // ps6.setInt(3, (ConvBusstop.nocheck ? 0 : HttpGET.getMap(lat, lon, NEER)));
                    ps6.setInt(3, 0);
                    ps6.setString(4, idStr);
                    System.out.println("UPDATE bus_stop("+ idStr +") lat="+ lat +", lon="+ lon +", fixed=0");
                    ps6.executeUpdate();
                }
            }
        }
    }
    */

    /**
     * <gml:Point gml:id="n1">
     * 	<gml:pos>35.14591397 139.10569573</gml:pos>
     * </gml:Point>
     *
     * @param con
     * @param node
     * @param areacode
     * @throws IOException
     * @throws SQLException
     */
    public static void showGmlPoint(Connection con, Node node, int areacode) throws IOException, SQLException {
        String positionStr = "";
        String latStr = "";
        String lonStr = "";
        String idStr = "";

        NamedNodeMap nodeMap = node.getAttributes();
        if ( null != nodeMap ) {
            for ( int j=0; j<nodeMap.getLength(); j++ ) {
                if (nodeMap.item(j).getNodeName().equals("gml:id")) {
                    idStr = nodeMap.item(j).getNodeValue();
                }
            }
        }

        NodeList nodes = node.getChildNodes();
        for (int i=0; i < nodes.getLength(); i++) {
            Node node2 = nodes.item(i);
            if (node2.getNodeName().equals("gml:pos")) {
                positionStr = node2.getTextContent().trim();
                String[] str4Ary = positionStr.split(" ");
                latStr = str4Ary[0];
                lonStr = str4Ary[1];

                try (PreparedStatement ps6 = con.prepareStatement("INSERT INTO bus_stop (lat,lon,fixed,area,gmlid) VALUES (?,?,?,?,?)")) {
                    double lat = Double.parseDouble(latStr);
                    double lon = Double.parseDouble(lonStr);
                    System.out.println("INSERT INTO bus_stop (lat,lon,fixed,area, gmlid) VALUES ('"+ latStr +"','"+ lonStr +"','0',"+ areacode +",'"+ idStr +"')");
                    
                    ps6.setDouble(1, lat);
                    ps6.setDouble(2, lon);
                    ps6.setInt(3, 0);
                    ps6.setInt(4, areacode);
                    ps6.setString(5, idStr);
                    ps6.executeUpdate();
                }
            }
        }
    }
    
    /**
     *
     * @param con
     * @param node
     * @param iFileName		// ソースファイル名(拡張子を含まない)
     * @throws IOException
     * @throws SQLException
     */
    /*
    public static void showED01(Connection con, Node node, String iFileName) throws IOException, SQLException {
        String gmlidStr = "";
        String nameStr = "";
        PreparedStatement ps1 = con.prepareStatement("SELECT gmlid FROM bus_stop WHERE gmlid=?");
        PreparedStatement ps2 = con.prepareStatement("INSERT INTO bus_stop (gmlid,name,ifile) VALUES (?,?,?)");
        try {
            ArrayList<String[]> bris = new ArrayList<>();
            NodeList nodes = node.getChildNodes();
            for (int i=0; i < nodes.getLength(); i++) {
                Node node2 = nodes.item(i);
                switch (node2.getNodeName()) {
                    case "ksj:POS":
                        NamedNodeMap nodeMap = node2.getAttributes();
                        if (null != nodeMap) {
                            for ( int j=0; j < nodeMap.getLength(); j++ ) {
                                if (nodeMap.item(j).getNodeName().equals("gmlid")) {
                                    gmlidStr = nodeMap.item(j).getNodeValue();
                                    System.out.println("found gmlid='"+ gmlidStr +"'");
                                    break;
                                }
                            }
                        }   break;
                    case "ksj:BSN":
                        nameStr = node2.getTextContent();
                        break;
                    case "ksj:BRI":
                        String[] rtn = anaComm(node2);
                        if (rtn != null) {
                            bris.add(rtn);
                        }   break;
                    default:
                        break;
                }
            }

            // gmlid と nameStr をデータベースに格納する
            boolean insert = true;
            ps1.setString(1, gmlidStr);
            try (ResultSet rset = ps1.executeQuery()) {
                if (rset.next()) {
                    insert = false;
                }
            }

            if (insert) {
                ps2.setString(1, gmlidStr);
                ps2.setString(2, nameStr);
                ps2.setString(3, iFileName);
                System.out.println("INSERT INTO bus_stop (gmlid,name,ifile) VALUES ('"+ gmlidStr +"','"+ nameStr +"','"+ iFileName +"')");
                ps2.executeUpdate();
            }
        }
        finally {
            ps1.close();
            ps2.close();
        }
    }
    */

    /**
     * <ksj:BusStop gml:id="ED01_1">
     * 	<ksj:position xlink:href="#n1"/>
     * 	<ksj:busStopName>城堀</ksj:busStopName>
     * 	<ksj:busRouteInformation>
     * 		<ksj:BusRouteInformation>
     * 			<ksj:busType>1</ksj:busType>
     * 			<ksj:busOperationCompany>箱根登山バス</ksj:busOperationCompany>
     * 			<ksj:busLineName>小01</ksj:busLineName>
     * 		</ksj:BusRouteInformation>
     * 	</ksj:busRouteInformation>
     * 	<ksj:busRouteInformation>
     * 		<ksj:BusRouteInformation>
     * 			<ksj:busType>1</ksj:busType>
     * 			<ksj:busOperationCompany>箱根登山バス</ksj:busOperationCompany>
     * 			<ksj:busLineName>湯07</ksj:busLineName>
     * 		</ksj:BusRouteInformation>
     * 	</ksj:busRouteInformation>
     * 	<ksj:busRouteInformation>
     * 		<ksj:BusRouteInformation>
     * 			<ksj:busType>1</ksj:busType>
     * 			<ksj:busOperationCompany>箱根登山バス</ksj:busOperationCompany>
     * 			<ksj:busLineName>湯11</ksj:busLineName>
     * 		</ksj:BusRouteInformation>
     * 	</ksj:busRouteInformation>
     * </ksj:BusStop>
     *
     * @param con
     * @param node
     * @param iFileName		// ソースファイル名(拡張子を含まない)
     * @throws IOException
     * @throws SQLException
     */
    public static void showBusStop(Connection con, Node node, String iFileName) throws IOException, SQLException {
        String gmlidStr = "";
        String nameStr = "";
        try (PreparedStatement ps2 = con.prepareStatement("UPDATE bus_stop SET name=?,ifile=? WHERE gmlid=?")) {
            ArrayList<String[]> bris = new ArrayList<>();
            NodeList nodes = node.getChildNodes();
            for (int i=0; i < nodes.getLength(); i++) {
                Node node2 = nodes.item(i);
                switch (node2.getNodeName()) {
                    case "ksj:position":
                        NamedNodeMap nodeMap = node2.getAttributes();
                        if (null != nodeMap) {
                            for ( int j=0; j < nodeMap.getLength(); j++ ) {
                                if (nodeMap.item(j).getNodeName().equals("xlink:href")) {
                                    gmlidStr = nodeMap.item(j).getNodeValue();
                                    gmlidStr = gmlidStr.substring(1);
                                    System.out.println("found gmlid='"+ gmlidStr +"'");
                                    break;
                                }
                            }
                        }   break;
                    case "ksj:busStopName":
                        nameStr = node2.getTextContent();
                        break;
                    case "ksj:busRouteInformation":
                        String[] rtn = anaCommJGD(node2);
                        if (rtn != null) {
                            bris.add(rtn);
                        }   break;
                    default:
                        break;
                }
            }
            
            // gmlid と nameStr をデータベースに格納する
            ps2.setString(1, nameStr);
            ps2.setString(2, iFileName);
            ps2.setString(3, gmlidStr);
            ps2.executeUpdate();
        }
    }

    public static String[] anaComm(Node briNode) {
        String[] rtn = new String[3];
        rtn[0] = "";	// corp type
        rtn[1] = "";	// course name
        rtn[2] = "";	// corp name

        NodeList nodes = briNode.getChildNodes();
        for (int i=0; i < nodes.getLength(); i++) {
            Node node2 = nodes.item(i);
            switch (node2.getNodeName()) {
                case "ksj:BSC":
                    rtn[0] = node2.getTextContent();
                    break;
                case "ksj:BLN":
                    rtn[1] = node2.getTextContent();
                    break;
                case "ksj:BOC":
                    rtn[2] = node2.getTextContent();
                    break;
                default:
                    break;
            }
        }
        return rtn;
    }

    /**
     *
     * 	<ksj:busRouteInformation>
     * 		<ksj:BusRouteInformation>
     * 			<ksj:busType>1</ksj:busType>
     * 			<ksj:busOperationCompany>箱根登山バス</ksj:busOperationCompany>
     * 			<ksj:busLineName>小01</ksj:busLineName>
     * 		</ksj:BusRouteInformation>
     * 	</ksj:busRouteInformation>
     *
     * @param briNode
     * @return
     */
    public static String[] anaCommJGD(Node briNode) {
        String[] rtn = new String[3];
        int vcnt = 0;

        NodeList nodes2 = briNode.getChildNodes();
        for (int i=0; i < nodes2.getLength(); i++) {
            Node node2 = nodes2.item(i);
            if (node2.getNodeName().equals("ksj:BusRouteInformation")) {
                NodeList nodes3 = node2.getChildNodes();
                for (int j=0; j < nodes3.getLength(); j++) {
                    Node node3 = nodes3.item(j);
                    switch (node3.getNodeName()) {
                        case "ksj:busType":
                            rtn[0] = node3.getTextContent();
                            vcnt++;
                            break;
                        case "ksj:busLineName":
                            rtn[1] = node3.getTextContent();
                            vcnt++;
                            break;
                        case "ksj:busOperationCompany":
                            rtn[2] = node3.getTextContent();
                            vcnt++;
                            break;
                        default:
                            break;
                    }
                }
            }
        }

        if (vcnt > 0) {
            return rtn;
        }
        return null;
    }

    /**
     * 'table.BUS_STOP'を新規に作る
     * 既にテーブルが存在する時には何もしない
     * @param conHsql
     * @throws SQLException
     */
    public static void create(Connection conHsql) throws SQLException {
        String createSt;

        // 'table.BUS_STOP'を新規に作る
        createSt = "CREATE TABLE bus_stop (gmlid VARCHAR(12) NOT NULL, gid LONG, name VARCHAR(128), kana VARCHAR(128), lat DOUBLE, lon DOUBLE, fixed INT, area INT, ifile VARCHAR(128), up INT, CONSTRAINT bus_stop_pk PRIMARY KEY(gmlid));";
        create(conHsql, createSt);

        //createSt = "CREATE TABLE existing_data (gmlid VARCHAR(12) NOT NULL, name VARCHAR(128), lat DOUBLE, lon DOUBLE, score INT, CONSTRAINT existing_pk PRIMARY KEY(gmlid, lat, lon));";
        //create(conHsql, createSt);

        //createSt = "CREATE TABLE coverage (area INT, name VARCHAR(128), denominator BIGINT, lv1 BIGINT, lv2 BIGINT, lv3 BIGINT);";
        //create(conHsql, createSt);
    }

    static void create(Connection con, String createsql) throws SQLException {
        System.out.println(createsql);
        try (PreparedStatement ps = con.prepareStatement(createsql)) {
            ps.executeUpdate();
        }
        catch (SQLSyntaxErrorException e) {
            System.out.println("83:"+ e.toString());
            if (!(e.toString().startsWith("java.sql.SQLSyntaxErrorException: object name already exists:"))) {
                throw e;
            }
        }
    }

    /**
     * 'table.BUS_STOP'を削除する
     * @param conHsql
     * @throws java.io.FileNotFoundException
     * @throws java.lang.ClassNotFoundException
     * @throws SQLException
     * @throws javax.xml.parsers.ParserConfigurationException
     * @throws org.xml.sax.SAXException
     */
    public static void dropTable (Connection conHsql) throws FileNotFoundException, ClassNotFoundException, SQLException, IOException, ParserConfigurationException, SAXException {
        drop(conHsql, "bus_stop");
        //drop(conHsql, "existing_data");
        //drop(conHsql, "coverage");
    }

    public static void drop(Connection con, String tableName) throws SQLException {
        String createSt = "DROP TABLE "+ tableName +";";
        System.out.println(createSt);
        try (PreparedStatement ps = con.prepareStatement(createSt)) {
            ps.executeUpdate();
        }
        catch (SQLSyntaxErrorException e) {
            System.out.println("107:"+ e.toString());
            if (!(e.toString().startsWith("java.sql.SQLSyntaxErrorException: user lacks privilege or object not found:"))) {
                throw e;
            }
        }
    }
    
    /**
     * 'table.BUS_STOP'の内容をCSV形式にして標準出力に出力する
     * @param con
     */
    public static void export(Connection con) {
        try {
            System.out.println("TABLE: BUS_STOP");
            System.out.println("\"name\",\"lat\",\"lon\",\"fixed\",\"ifile\"");
            PreparedStatement ps8 = con.prepareStatement("SELECT name,lat,lon,fixed,ifile FROM bus_stop");
            try (ResultSet rset8 = ps8.executeQuery()) {
                while (rset8.next()) {
                    String name = rset8.getString(1);
                    Double lat = rset8.getDouble(2);
                    Double lon = rset8.getDouble(3);
                    int fixed = rset8.getInt(4);
                    String ifile = rset8.getString(5);
                    System.out.println("\""+ name +"\","+ lat +","+ lon +","+ fixed +",\""+ ifile +"\"");
                }
            }
        }
        catch (SQLException e) {
                e.printStackTrace();
        }
    }

    /**
     * 数値地図情報のGMLデータファイルかどうかを見極める
     * @param f
     * @return
     */
    static boolean checkFile(File f, int areacode) {
        String name = f.getName();
        if (!name.startsWith(GML_DIR_PREFIX)) {
            return false;
        }
        if (!name.toUpperCase().endsWith(".XML")) {
            return false;
        }
        return Integer.parseInt(name.substring(GML_DIR_PREFIX.length(), GML_DIR_PREFIX.length()+2)) == areacode;
    }
    
    /**
     * 数値地図情報のデータディレクトリかどうかを見極める
     * @param f
     * @return
     */
    public static boolean checkGMLdir(File f) {
        if (!f.isDirectory()) {
            return false;
        }
        String name = f.getName();
        if (!name.startsWith(GML_DIR_PREFIX)) {
            return false;
        }
        return name.toUpperCase().endsWith(GML_DIR_PRIFIX);
    }

    public static final String GML_DIR_PREFIX = "P11-10_";
    public static final String GML_DIR_PRIFIX = "_GML";
}