Newer
Older
osmCoverage / src / osm / jp / postgis / Kml.java
package osm.jp.postgis;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PipedWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonNumber;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import jp.co.areaweb.tools.database.DatabaseTool;
import osm.jp.api.Coverage;
import osm.jp.api.Japan;
import osm.jp.api.RectArea;

public class Kml implements Runnable {
    private ToPostgis type;
    private final String name;
    private final double lat;
    private final double lon;
    private final double km;
    
    PipedWriter pipeOut;

    public static final int MAX_DATA_COUNT = 1000;

    /**
     * 
     * @param pipeOut
     * @param dbname
     * @param name
     * @param lat
     * @param lon
     * @param km 
     * @throws java.io.IOException 
     */
    public Kml(PipedWriter pipeOut, String dbname, String name, double lat, double lon, double km) throws IOException {
        this.name = name;
        this.lat = lat;
        this.lon = lon;
        this.km = km;
        
        this.type = null;
        if (dbname.equals(osm.jp.coverage.busstop.DbBusstop.TABLE_NAME)) {
            this.type = new osm.jp.coverage.busstop.ToPostgis();
        }
        else if (dbname.equals(osm.jp.coverage.fuel.DbFuel.TABLE_NAME)) {
            this.type = new osm.jp.coverage.fuel.ToPostgis();
        }
        else if (dbname.equals(osm.jp.coverage.police.DbPolice.TABLE_NAME)) {
            this.type = new osm.jp.coverage.police.ToPostgis();
        }
        else if (dbname.equals(osm.jp.coverage.postoffice.DbPostoffice.TABLE_NAME)) {
            this.type = new osm.jp.coverage.postoffice.ToPostgis();
        }
        
        this.pipeOut = pipeOut;
    }

    @Override
    @SuppressWarnings({"CallToPrintStackTrace", "SleepWhileInLoop"})
    public void run() {
        BufferedWriter bw = new BufferedWriter(pipeOut);
        try (PrintWriter ow = new PrintWriter(bw))
        {
            ow.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            ow.println("<kml xmlns=\"http://www.opengis.net/kml/2.2\">");
            ow.println("<Document>");
            ow.flush();
            try {
                Thread.sleep(0);
            }
            catch (InterruptedException ex) {
                ex.printStackTrace();
            }
            
            int count = 0;
            try (Connection conPost = DatabaseTool.openDb(Coverage.DB_PORP_GISDB))
            {
                ow.println(getStringStyle());
                
                ow.println("<name>"+ name +"</name>");
                ow.println("<visibility>1</visibility>");
                ow.println(getStringExtendedData(name));
                ow.flush();
                try {
                    Thread.sleep(0);
                }
                catch(InterruptedException ex) {
                    ex.printStackTrace();
                }
                
                String sql = "SELECT area,gmlid,fixed,ST_Y(geom) AS lat, ST_X(geom) AS lon, ST_AsGeoJSON(ST_Transform(t_%s.geom,4326))::json As geometry "
                        + "FROM t_%s "
                        + "WHERE (ST_Y(geom) > ?) and (ST_Y(geom) < ?) and (ST_X(geom) > ?) and (ST_X(geom) < ?)";
                sql = String.format(sql, type.tableName, type.tableName);
                try (PreparedStatement ps8 = conPost.prepareStatement(sql)) {
                    RectArea rect = new RectArea(lat, lon, (int)(km * 2000));
                    ps8.setDouble(1, rect.minlat);
                    ps8.setDouble(2, rect.maxlat);
                    ps8.setDouble(3, rect.minlon);
                    ps8.setDouble(4, rect.maxlon);
                    try (ResultSet rset8 = ps8.executeQuery()) {
                        while (rset8.next()) {
                            String gmlid = rset8.getString("gmlid");
                            int area = rset8.getInt("area");
                            int fixed = rset8.getInt("fixed");
                            
                            // geom: {"type":"Point","coordinates":[143.3147749,42.2984888]}
                            String geom = rset8.getString("geometry");
                            String lonStr = null;
                            String latStr = null;
                            try (JsonReader reader = Json.createReader(new StringReader(geom))) {
                                JsonObject geojson = reader.readObject();
                                JsonArray coordinates = geojson.getJsonArray("coordinates");
                                for (JsonValue v1 : coordinates) {
                                    if (v1.getValueType() == JsonValue.ValueType.NUMBER) {
                                        JsonNumber num = (JsonNumber)v1;
                                        if (lonStr == null) {
                                            lonStr = num.toString();
                                        }
                                        else {
                                            latStr = num.toString();
                                        }
                                    }
                                }
                            }
                            if ((lonStr != null) && (latStr != null)) {
                                double lat0 = Double.parseDouble(latStr);
                                double lon0 = Double.parseDouble(lonStr);
                                double dd = Japan.distanceKm(lat,lon,lat0,lon0);
                                if (dd < km) {
                                    count++;
                                    if (count <= MAX_DATA_COUNT) {
                                        String poiname = String.format("%02d - %s", area, gmlid);
                                        String color = decideColor(fixed);
                                        String str = getStringPlacemark(poiname, latStr, lonStr, color);
                                        ow.println(str);
                                        ow.flush();
                                        try {
                                            Thread.sleep(0);
                                        }
                                        catch(InterruptedException ex) {
                                            ex.printStackTrace();
                                        }
                                    }
                                    else {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            ow.println("</Document>");
            ow.println("</kml>");
            ow.flush();
        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
    String decideColor(int fixed) {
        if (this.type instanceof osm.jp.coverage.busstop.ToPostgis) {
            if (fixed == 0) {
                return "red";
            }
            else if (fixed < 100) {
                return "orange";
            }
            else {
                return "green";
            }
        }
        else if (this.type instanceof osm.jp.coverage.fuel.ToPostgis) {
            if (fixed == 0) {
                return "red";
            }
            else if (fixed < 50) {
                return "orange";
            }
            else {
                return "green";
            }
        }
        else if (this.type instanceof osm.jp.coverage.police.ToPostgis) {
            if (fixed == 0) {
                return "red";
            }
            else {
                return "green";
            }
        }
        else if (this.type instanceof osm.jp.coverage.postoffice.ToPostgis) {
            if (fixed == 0) {
                return "red";
            }
            else {
                return "green";
            }
        }
        return "brown";
    }
    
    String getStringStyle() {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append(icon("red"));
        sbuf.append(icon("orange"));
        sbuf.append(icon("green"));
        sbuf.append(icon("brown"));
        return sbuf.toString();
    }
    
    /**
     * 
     * @param color ["red"|"blue"|"purple"|"yellow"|"pink"|"brown"|"green"|"orange"]
     * @return 
     */
    String icon(String color) {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append(String.format("<Style id=\"placemark-%s\">", color));
        sbuf.append("<IconStyle>");
        sbuf.append("<Icon>");
        sbuf.append(String.format("<href>http://maps.me/placemarks/placemark-%s.png</href>", color));
        sbuf.append("</Icon>");
        sbuf.append("</IconStyle>");
        sbuf.append("</Style>");
        return sbuf.toString();
    }
    
    /**
     * 
        <ExtendedData xmlns:mwm="https://maps.me">
          <mwm:name>
            <mwm:lang code="default">poi</mwm:lang>
          </mwm:name>
          <mwm:annotation></mwm:annotation>
          <mwm:description></mwm:description>
          <mwm:lastModified>2018-12-23T01:50:40Z</mwm:lastModified>
          <mwm:accessRules>Local</mwm:accessRules>
        </ExtendedData>
    * 
    * 
    */
    String getStringExtendedData(String name) {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append("<ExtendedData xmlns:mwm=\"https://maps.me\">");
        sbuf.append("<mwm:name><mwm:lang code=\"default\">");
        sbuf.append(name);
        sbuf.append("</mwm:lang></mwm:name>");
        sbuf.append("<mwm:annotation></mwm:annotation>");
        sbuf.append("<mwm:description></mwm:description>");
        
        sbuf.append("<mwm:lastModified>");
        sbuf.append((new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")).format(new Date()));
        sbuf.append("</mwm:lastModified>");
        
        sbuf.append("<mwm:accessRules>Local</mwm:accessRules>");        
        sbuf.append("</ExtendedData>");
        return sbuf.toString();
    }
    
    /**
     * 
        <Placemark>
          <name>新日本海フェリー 苫小牧東港ターミナル</name>
          <TimeStamp><when>2017-12-28T11:15:56Z</when></TimeStamp>
          <styleUrl>#placemark-blue</styleUrl>
          <Point><coordinates>141.81955,42.610008</coordinates></Point>
          <ExtendedData xmlns:mwm="https://maps.me">
            <mwm:name>
              <mwm:lang code="default">新日本海フェリー 苫小牧東港ターミナル</mwm:lang>
            </mwm:name>
            <mwm:description>
            </mwm:description>
            <mwm:customName>
              <mwm:lang code="default">新日本海フェリー 苫小牧東港ターミナル</mwm:lang>
            </mwm:customName>
            <mwm:scale>13</mwm:scale>
          </ExtendedData>
        </Placemark>
     * 
     */
    String getStringPlacemark(String name, String latStr, String lonStr, String color) {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append("<Placemark>");
        sbuf.append("<name>");
        sbuf.append(name);
        sbuf.append("</name>");
        sbuf.append("<TimeStamp><when>");
        sbuf.append((new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")).format(new Date()));
        sbuf.append("</when></TimeStamp>");
        sbuf.append(String.format("<styleUrl>#placemark-%s</styleUrl>", color));
        sbuf.append("<Point><coordinates>");
        sbuf.append(String.format("%s,%s", lonStr, latStr));
        sbuf.append("</coordinates></Point>");
        sbuf.append(getStringPlacemarkExtendedData(name));
        sbuf.append("</Placemark>");
        return sbuf.toString();
    }
    
    /**
     * 
        <ExtendedData xmlns:mwm="https://maps.me">
          <mwm:name>
            <mwm:lang code="default">新日本海フェリー 苫小牧東港ターミナル</mwm:lang>
          </mwm:name>
          <mwm:description>
          </mwm:description>
          <mwm:customName>
            <mwm:lang code="default">新日本海フェリー 苫小牧東港ターミナル</mwm:lang>
          </mwm:customName>
          <mwm:scale>13</mwm:scale>
        </ExtendedData>
    * 
    */
    String getStringPlacemarkExtendedData(String name) {
        StringBuilder sbuf = new StringBuilder();
        sbuf.append("<ExtendedData xmlns:mwm=\"https://maps.me\">");
        sbuf.append("<mwm:name><mwm:lang code=\"default\">");
        sbuf.append(name);
        sbuf.append("</mwm:lang></mwm:name>");
        sbuf.append("<mwm:description></mwm:description>");
        sbuf.append("<mwm:customName><mwm:lang code=\"default\">");
        sbuf.append(name);
        sbuf.append("</mwm:lang></mwm:customName>");
        sbuf.append("<mwm:scale>13</mwm:scale>");
        sbuf.append("</ExtendedData>");
        return sbuf.toString();
    }
}