Java tutorial
/** * 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.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.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 Japan Data source. * <PRE> * JMA GSM Japan Data are stored in "jma-gsm-jp" 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, * total_preciptasion 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 [%] and total_preciptation 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 JmaGsmJp implements MetDriver { private static Logger logger = Logger.getLogger(JmaGsmJp.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 JmaGsmJp() { } /** * <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() { } /** * set up JDBC parameter. * This driver uses postgresql's JDBC driver. * * (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 JP 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 JP 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 }