net.agmodel.metbroker.driver.impl.JmaGsmGl.java Source code

Java tutorial

Introduction

Here is the source code for net.agmodel.metbroker.driver.impl.JmaGsmGl.java

Source

/**
 * This file is part of MetBroker.
 *
 * MetBroker is free software: you can redistribute it and/or modify it under the terms
 * of the GNU Lesser General Public License as published by the Free Software Foundation,
 * either version 3 of the License, or (at your option) any later version. MetBroker
 * is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
 * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details. You should have received a copy of the GNU
 * Lesser General Public License along with <SoftwareName>. If not, see <http://www.gnu.org/licenses/>.
 * How to use GNU licenses for your own software - GNU Project - Free Software Foundation (FSF)
 * 
 */
package net.agmodel.metbroker.driver.impl;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.PreparedStatement;
//import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import java.util.TimeZone;

import javax.sql.DataSource;

import net.agmodel.metbroker.driver.DriverConfig;
import net.agmodel.metbroker.driver.DriverException;
import net.agmodel.metbroker.driver.MetDriver;
import net.agmodel.metbroker.driver.StationDataSetProxy;
import net.agmodel.physical.Duration;
import net.agmodel.physical.MutableInterval;
import net.agmodel.physical.SummaryHistory;
import net.agmodel.physical.SummaryHistoryElement;
import net.agmodel.physical.SummaryKind;
import net.agmodel.weatherData.AirTempMaxMinMeanImpl;
//import net.agmodel.weatherData.AirTempSingleImpl;
import net.agmodel.weatherData.AirTemperature;
import net.agmodel.weatherData.Humidity;
import net.agmodel.weatherData.MetDuration;
import net.agmodel.weatherData.MetElement;
import net.agmodel.weatherData.MetRequest;
import net.agmodel.weatherData.RHImpl;
import net.agmodel.weatherData.Rain;
import net.agmodel.weatherData.RainImpl;
import net.agmodel.weatherData.StationDataSet;
import net.agmodel.weatherData.StationMetRequest;
import net.agmodel.weatherData.Wind;
import net.agmodel.weatherData.Wind2DImpl;
//import net.agmodel.weatherData.WindImpl;

import org.apache.commons.dbcp.ConnectionFactory;
import org.apache.commons.dbcp.DriverManagerConnectionFactory;
import org.apache.commons.dbcp.PoolableConnectionFactory;
import org.apache.commons.dbcp.PoolingDataSource;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
import org.apache.log4j.Logger;

/**
 * Data Driver for jma GSM Global Data source.
 * <PRE>
 * JMA GSM Global Data are stored in "jma-gsm-gl" Postgresql database.
 * The schema are:
 * create table data (
 * station_id integer not null references stations( station_id ),
 * "date" timestamp not null,
 * end_date timestamp not null,
 * initial_date timestamp not null references initial_dates( initial_date ),
 * pressure float,
 * pressure_msl float,
 * u_wind float,
 * v_wind float,
 * temperature float,
 * relative_humidity float,
 * primary key ( station_id, end_date, initial_date )
 *);
 * where: 
 * date, end_date, initial_date are represented with UTC.
 * if date equals initial_date, the values is observed one.
 * Unit of pressure and pressure_msl is [P]
 * Unit of u_wind and w_wind is [m/s]
 * Unit of temperature is [K]
 * Unit of relative_humidity is [%]
 * </PRE>
 * In this driver, retrieve observed values for time series between start time and the latest initial_date, 
 * and simulated values for time series between latest initial_date and end time.
 * 
 * @version 0.0
 * @author Shigehiro Honda
 * @copyright LGPL
 */

public class JmaGsmGl implements MetDriver {
    private static Logger logger = Logger.getLogger(JmaGsmGl.class);

    private final String QUERY1 = "select station_id, date, end_date, initial_date ";
    private final String QUERY2 = " FROM data WHERE station_id = ? AND ?<=end_date AND end_date<?";
    private final String QUERY3 = " AND end_date <= (select max(initial_date) from initial_dates)";
    private final String QUERY4 = " AND initial_date = date";
    private final String QUERY5 = " UNION SELECT station_id, date, end_date, initial_date ";
    private final String QUERY6 = " FROM data where station_id = ? AND ?<=end_date AND end_date<?";
    private final String QUERY7 = "AND end_date > (select max(initial_date) from initial_dates)";
    private final String QUERY8 = "AND initial_date = (select max(initial_date) from initial_dates)";
    private final String QUERY9 = "ORDER BY end_date";

    private DataSource dataSource;

    /**
     * null constructor
     */
    public JmaGsmGl() {
    }

    /** 
     * <PRE>
     * if request's resolution are small or equal to SUBDAILY, set 
     * SIX_HOURS(Minimum Resolution of this database.
     * extract start date, end date, and station id from Request and then make up SQL command from them
     * call queryTable with these information
     * </PRE> 
     * @see net.agmodel.metbroker.driver.MetDriver#queryForStation(net.agmodel.weatherData.StationMetRequest, net.agmodel.metbroker.driver.StationDataSetProxy)
     */
    public void queryForStation(StationMetRequest request, StationDataSetProxy result) throws DriverException {
        boolean hourly = request.getResolution().compareTo(MetDuration.DAILY) <= 0;

        Date start = request.getDateExtremes().getStart();
        Date end = request.getDateExtremes().getEnd();

        logger.debug(request.getResolution());

        String stationID = request.getStationID();

        String query = createQueryString(request, stationID, start, end);

        logger.debug("excute query-->" + query);

        queryTable(result, stationID, query, start, end, hourly);

    }

    /** 
     * Nothing to do
     * @see net.agmodel.metbroker.driver.MetDriver#destroy()
     */
    public void destroy() {
    }

    /** 
     * <PRE>
     * set up JDBC parameter.
     * This driver uses postgresql's JDBC driver.
     * </PRE>
     * (non-Javadoc)
     * @see net.agmodel.metbroker.driver.MetDriver#init(net.agmodel.metbroker.driver.DriverConfig)
     */
    public void init(DriverConfig driverConfig) throws DriverException {
        logger.debug("initialize JMA GSM GLobal data source");
        try {
            Class.forName("org.postgresql.Driver");

            int maxActive = Integer.parseInt(driverConfig.getParam("maxactive"));
            int maxWait = Integer.parseInt(driverConfig.getParam("maxwait"));
            int maxIdle = Integer.parseInt(driverConfig.getParam("maxidle"));
            String user = driverConfig.getParam("user");
            String password = driverConfig.getParam("password");
            String host = driverConfig.getParam("host");
            int port = Integer.parseInt(driverConfig.getParam("port"));
            String db = driverConfig.getParam("db");

            ObjectPool connectionPool = new GenericObjectPool(null, maxActive,
                    GenericObjectPool.WHEN_EXHAUSTED_BLOCK, maxWait, maxIdle, false, false, 60000, 3, 10000, false);

            Properties p = new Properties();
            p.put("user", user);
            p.put("password", password);
            ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
                    "jdbc:postgresql://" + host + ":" + port + "/" + db, p);
            PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,
                    connectionPool, null, null, false, true);
            dataSource = new PoolingDataSource(connectionPool);

            logger.debug("JMA GSM Global DataSource created");
        } catch (Exception e) {
            e.printStackTrace();
            throw new DriverException(e.getMessage());
        }
    }

    /** 
     * create sequence.
     * <PRE>
     * Available Element are:
     * AIRTEMPERATURE, RAIN, WIND, HUMIDITY
     * </PRE>
     * Depending on the request, create sequences for requested elements.
     * @see net.agmodel.metbroker.driver.MetDriver#createSequence(net.agmodel.weatherData.StationMetRequest, net.agmodel.weatherData.StationDataSet)
     */
    public StationDataSetProxy createSequence(StationMetRequest request, StationDataSet result) {
        boolean hourly = request.getResolution().compareTo(MetDuration.DAILY) <= 0;
        Duration duration = (hourly ? Duration.SIX_HOURS : Duration.ONE_DAY);

        StationDataSetProxy rtn = new StationDataSetProxy(result, duration);

        // Air Temperature, [K]
        AirTemperature tempSequence = null;
        if (request.containsMetElement(MetElement.AIRTEMPERATURE)) {
            SummaryHistory sh = new SummaryHistory();

            sh.addHistoryElement(new SummaryHistoryElement(duration, SummaryKind.EXTREMA));
            tempSequence = new AirTempMaxMinMeanImpl(result.getInterval(), sh);
            rtn.addSequence(MetElement.AIRTEMPERATURE, tempSequence);
        }
        // RAIN, total precipitation [kg/m**2]
        if (request.containsMetElement(MetElement.RAIN)) {
            SummaryHistory sh = new SummaryHistory();
            sh.addHistoryElement(new SummaryHistoryElement(duration, SummaryKind.TOTAL));
            RainImpl rainSequence = new RainImpl(result.getInterval(), sh);
            rtn.addSequence(MetElement.RAIN, rainSequence);
        }

        // WIND u-wind/v-wind [m/s]
        if (request.containsMetElement(MetElement.WIND)) {
            SummaryHistory sh = new SummaryHistory();
            sh.addHistoryElement(new SummaryHistoryElement(duration, SummaryKind.AVERAGE));
            Wind2DImpl windSequence = new Wind2DImpl(result.getInterval(), sh, 10, "m");
            rtn.addSequence(MetElement.WIND, windSequence);
        }
        // HUMIDITY, RH[%]
        if (request.containsMetElement(MetElement.HUMIDITY)) {
            SummaryHistory sh = new SummaryHistory();
            sh.addHistoryElement(new SummaryHistoryElement(duration, SummaryKind.AVERAGE));
            RHImpl wetnessSequence = new RHImpl(result.getInterval(), sh, tempSequence);
            rtn.addSequence(MetElement.HUMIDITY, wetnessSequence);
        }

        return rtn;
    }

    // /////////////////////////////
    // private methods from here //
    // /////////////////////////////

    /**
     * construct SQL statement with user request.
     * @param request user request
     * @param stationId station id 
     * @param start start date
     * @param end end date
     * @return
     */
    private String createQueryString(MetRequest request, String stationId, Date start, Date end) {

        StringBuffer queryBuf1 = new StringBuffer(1024);
        StringBuffer queryBuf5 = new StringBuffer(1024);
        queryBuf1.append(QUERY1);
        queryBuf5.append(QUERY5);
        if (request.containsMetElement(MetElement.AIRTEMPERATURE)) {
            queryBuf1.append(",temperature");
            queryBuf5.append(",temperature");
        }
        if (request.containsMetElement(MetElement.RAIN)) {
            queryBuf1.append(",total_preciptasion");
            queryBuf5.append(",total_preciptasion");
        }
        if (request.containsMetElement(MetElement.HUMIDITY)) {
            queryBuf1.append(",relative_humidity");
            queryBuf5.append(",relative_humidity");
        }
        if (request.containsMetElement(MetElement.WIND)) {
            queryBuf1.append(",u_wind, v_wind");
            queryBuf5.append(",u_wind, v_wind");
        }
        queryBuf1.append(QUERY2);
        queryBuf1.append(QUERY3);
        queryBuf1.append(QUERY4);
        queryBuf1.append(queryBuf5);
        queryBuf1.append(QUERY6);
        queryBuf1.append(QUERY7);
        queryBuf1.append(QUERY8);
        queryBuf1.append(QUERY9);

        return queryBuf1.toString();
    }

    /**
     * get database connection and execute SQL command.
     * And put the result to Sequence Object
     * @param seqMap Sequence Map
     * @param stationId station id
     * @param query SQL statement
     * @param start start date
     * @param end end date
     * @param hourly if true, use SIX_HOURS, else ONE_DAY
     * @throws DriverException something fail.
     */
    private void queryTable(StationDataSetProxy seqMap, String stationId, String query, Date start, Date end,
            boolean hourly) throws DriverException {
        Connection con = null;
        PreparedStatement stmt = null;
        ResultSet rs = null;
        java.sql.Timestamp startDate = new java.sql.Timestamp(start.getTime());

        java.sql.Timestamp endDate = new java.sql.Timestamp(end.getTime());
        Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("UTC"));

        try {
            con = dataSource.getConnection();

            logger.debug("Connection: " + con.toString());

            /*         stmt = con.prepareStatement(query);
                     stmt.setInt(1, new Integer(stationId).intValue());
                     stmt.setTimestamp(2, startDate, cal);
                     stmt.setTimestamp(3, endDate, cal);
                     stmt.setInt(4, new Integer(stationId).intValue());
                     stmt.setTimestamp(5, startDate, cal);
                     stmt.setTimestamp(6, endDate, cal);
            */
            stmt = con.prepareStatement(query);
            stmt.setInt(1, new Integer(stationId).intValue());
            stmt.setTimestamp(2, startDate);
            stmt.setTimestamp(3, endDate);
            stmt.setInt(4, new Integer(stationId).intValue());
            stmt.setTimestamp(5, startDate);
            stmt.setTimestamp(6, endDate);

            rs = stmt.executeQuery();

            logger.debug("ResultSet: " + rs.toString());

            AirTemperature tempSequence = null;
            if (seqMap.containsKey(MetElement.AIRTEMPERATURE)) {
                tempSequence = (AirTemperature) seqMap.getSequence(MetElement.AIRTEMPERATURE);
            }
            Rain rainSequence = null;
            if (seqMap.containsKey(MetElement.RAIN)) {
                rainSequence = (Rain) seqMap.getSequence(MetElement.RAIN);
            }
            Humidity humiditySequence = null;
            if (seqMap.containsKey(MetElement.HUMIDITY)) {
                humiditySequence = (Humidity) seqMap.getSequence(MetElement.HUMIDITY);
            }
            Wind windSequence = null;
            if (seqMap.containsKey(MetElement.WIND)) {
                windSequence = (Wind) seqMap.getSequence(MetElement.WIND);
            }

            while (rs.next()) {
                java.util.Date recordTime = null;
                MutableInterval dataInterval = new MutableInterval();
                recordTime = rs.getTimestamp("end_date");

                if (hourly) {
                    dataInterval.set(Duration.SIX_HOURS, recordTime);
                } else {
                    dataInterval.set(Duration.ONE_DAY, recordTime);
                }
                if (seqMap.containsKey(MetElement.AIRTEMPERATURE)) {
                    float dummy = (float) (rs.getFloat("temperature") - 273.15);
                    if (!rs.wasNull()) {
                        ((AirTempMaxMinMeanImpl) tempSequence).putMeanOverInterval(dataInterval, dummy);
                    }
                }
                if (seqMap.containsKey(MetElement.RAIN)) {
                    float dummy = rs.getFloat("total_preciptasion");
                    if (!rs.wasNull()) {
                        ((RainImpl) rainSequence).putRainfallOverInterval(dataInterval, dummy);
                    }
                }
                if (seqMap.containsKey(MetElement.HUMIDITY)) {
                    float dummy = rs.getFloat("relative_humidity");
                    if (!rs.wasNull()) {
                        ((RHImpl) humiditySequence).putRHOverInterval(dataInterval, dummy);
                    }
                }
                if (seqMap.containsKey(MetElement.WIND)) {
                    float u = rs.getFloat("u_wind");
                    if (!rs.wasNull()) {
                        float v = rs.getFloat("v_wind");
                        if (!rs.wasNull()) {
                            ((Wind2DImpl) windSequence).putSpeedOverInterval(dataInterval, v, u);
                        }
                    }
                }
            }
        } catch (SQLException s) {
            s.printStackTrace();
        } finally {
            try {
                rs.close();
            } catch (Exception s) {
            }
            try {
                stmt.close();
            } catch (Exception s) {
            }
            try {
                con.close();
            } catch (Exception e) {
            }

        }

    } // queryTables

}