org.n52.ifgicopter.spf.input.PostgisInputPlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.n52.ifgicopter.spf.input.PostgisInputPlugin.java

Source

/**
 * Copyright (C) 2012
 * by 52 North Initiative for Geospatial Open Source Software GmbH
 *
 * Contact: Andreas Wytzisk
 * 52 North Initiative for Geospatial Open Source Software GmbH
 * Martin-Luther-King-Weg 24
 * 48155 Muenster, Germany
 * info@52north.org
 *
 * This program is free software; you can redistribute and/or modify it under
 * the terms of the GNU General Public License version 2 as published by the
 * Free Software Foundation.
 *
 * This program is distributed WITHOUT ANY WARRANTY; even without the implied
 * WARRANTY OF MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program (see gnu-gpl v2.txt). If not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA or
 * visit the Free Software Foundation web page, http://www.fsf.org.
 */
/**
 * 
 */

package org.n52.ifgicopter.spf.input;

import java.awt.BorderLayout;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.text.DefaultCaret;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.n52.ifgicopter.spf.gui.ModuleGUI;
import org.n52.ifgicopter.spf.input.IInputPlugin;
import org.postgis.Geometry;
import org.postgis.PGgeometry;
import org.postgis.Point;

/**
 * 
 * 
 * @author Daniel Nst (d.nuest@52north.org)
 * 
 */
public abstract class PostgisInputPlugin implements IInputPlugin {

    private static class Connector implements Callable<Connection> {

        private Log logger = LogFactory.getLog(Connector.class);

        private PostgisInputPlugin plugin;

        /**
         * 
         * @param postgisInputPlugin
         */
        public Connector(PostgisInputPlugin postgisInputPlugin) {
            this.plugin = postgisInputPlugin;
        }

        /*
         * (non-Javadoc)
         * 
         * @see java.util.concurrent.Callable#call()
         */
        @Override
        public Connection call() throws Exception {
            Connection c = null;

            try {
                String connectionUrl = "jdbc:postgresql:" + (this.plugin.host != null
                        ? ("//" + this.plugin.host) + (this.plugin.port != null ? ":" + this.plugin.port : "") + "/"
                        : "") + this.plugin.databaseName;
                c = DriverManager.getConnection(connectionUrl, this.plugin.user, this.plugin.password);

                this.logger.debug("Database connection established!");
            } catch (SQLException e) {
                this.logger.error(e);
                List<Map<String, Object>> currentNewData = new ArrayList<Map<String, Object>>();
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("ERROR", e.getMessage());
                map.put("", e.toString());
                currentNewData.add(map);
                this.plugin.appendToDataDisplay(currentNewData);
            }

            return c;
        }

    }

    private static final String CONFIG_FILE = "D:/workspace/SensorVis/config/spf/input-noise.xml";

    private static Log log = LogFactory.getLog(PostgisInputPlugin.class);

    private static final String PLUGIN_NAME = "PostGIS Input Plugin";

    private Connection connection = null;

    protected String databaseName = "postgis";

    protected String driver = "org.postgresql.Driver";

    protected boolean extensiveLog = false;

    private Future<Connection> futureConnection;

    protected ModuleGUI gui;

    protected String host = "localhost";

    protected Timestamp lastDataTimestamp;

    protected JPanel panel;

    protected String password = "postgres";

    protected String port = "5432";

    protected int status = STATUS_NOT_RUNNING;

    protected JLabel statusLabel;

    protected String statusString = "...";

    protected String tableName;

    private JTextArea textArea;

    protected String timeColumnName;

    protected String user = "postgres";

    protected String where = null;

    /**
     * 
     * @param driver
     * @param host
     * @param port
     * @param database
     * @param user
     * @param password
     */
    @ConstructorParameters({ "host", "port", "database", "user", "password", "table", "timeColumn" })
    public PostgisInputPlugin(String host, String port, String database, String user, String password, String table,
            String timeColumn) {
        this(host, port, database, user, password, table, timeColumn, null);
    }

    /**
     * 
     * @param host
     * @param port
     * @param database
     * @param user
     * @param password
     * @param table
     * @param timeColumn
     * @param where
     */
    @ConstructorParameters({ "host", "port", "database", "user", "password", "table", "timeColumn",
            "where clause" })
    public PostgisInputPlugin(String host, String port, String database, String user, String password, String table,
            String timeColumn, String where) {
        this.host = host;
        this.port = port;
        this.databaseName = database;
        this.user = user;
        this.password = password;
        this.tableName = table;
        this.timeColumnName = timeColumn;
        this.where = where;
    }

    /**
     * 
     * @param currentNewData
     */
    protected void appendToDataDisplay(List<Map<String, Object>> currentNewData) {
        String s = this.textArea.getText();

        StringBuilder sb = new StringBuilder();
        sb.append(s);
        for (Map<String, Object> map : currentNewData) {
            sb.append(Arrays.toString(map.entrySet().toArray()));
            sb.append("\n");
        }

        this.textArea.setText(sb.toString());
    }

    /**
     * 
     */
    protected void clearDataDisplay() {
        this.textArea.setText("");
    }

    /**
     * @param resultSet
     * @return
     * @throws SQLException
     */
    protected ArrayList<String> getColumnNames(ResultSet resultSet) throws SQLException {
        ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
        int cols = resultSetMetaData.getColumnCount();

        // get the column names
        ArrayList<String> columnNames = new ArrayList<String>();
        for (int i = 1; i <= cols; i++) {
            columnNames.add(resultSetMetaData.getColumnName(i));
        }
        if (log.isDebugEnabled())
            log.debug("Found columns: " + Arrays.toString(columnNames.toArray()));
        return columnNames;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.input.IInputPlugin#getConfigFile()
     */
    @Override
    public InputStream getConfigFile() {
        try {
            return new FileInputStream(new File(CONFIG_FILE));
        } catch (FileNotFoundException e) {
            log.error(e);
        }
        return null;
    }

    /**
     * @return the connection
     */
    protected Connection getConnection() {
        if (this.connection == null) {
            try {
                this.connection = this.futureConnection.get();
            } catch (Exception e) {
                log.fatal(e);
            }
        }

        return this.connection;
    }

    /**
     * 
     * @param resultSet
     * @return
     */
    protected List<Map<String, Object>> getData(ResultSet resultSet) {
        List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();

        try {
            ArrayList<String> columnNames = getColumnNames(resultSet);

            while (resultSet.next()) {
                Map<String, Object> dataElem = getDataElement(resultSet, columnNames);
                data.add(dataElem);
            } // while(resultSet.next())
        } catch (SQLException e) {
            log.error(e);
        }

        return data;
    }

    /**
     * @param resultSet
     * @param columnNames
     * @return
     * @throws SQLException
     */
    protected Map<String, Object> getDataElement(ResultSet resultSet, ArrayList<String> columnNames)
            throws SQLException {
        Map<String, Object> dataElem = new HashMap<String, Object>();

        for (String c : columnNames) {
            Object o = resultSet.getObject(c);
            if (log.isDebugEnabled() && this.extensiveLog)
                log.debug("Adding " + c + " = " + o);

            if (o instanceof Timestamp) {
                Timestamp t = (Timestamp) o;
                this.lastDataTimestamp = t;
                if (log.isDebugEnabled() && this.extensiveLog)
                    log.debug("Latest data as of " + this.lastDataTimestamp);

                // dataElem.put(c, t);
                dataElem.put("time", Long.valueOf(t.getTime()));
            } else if (o instanceof PGgeometry) {
                PGgeometry geom = (PGgeometry) o;
                Geometry geometry = geom.getGeometry();

                if (geometry.getType() == Geometry.POINT) {
                    Point p = (Point) geometry;
                    dataElem.put("x", Double.valueOf(p.getX()));
                    dataElem.put("y", Double.valueOf(p.getY()));
                    dataElem.put("z", Double.valueOf(p.getZ()));
                    dataElem.put("SRID", Integer.valueOf(p.getSrid()));
                } else
                    log.warn("unhandled geometry: " + geom);

                // dataElem.put(c, geometry);
            } else
                dataElem.put(c, o);
        }

        if (log.isDebugEnabled() && this.extensiveLog)
            log.debug("Added new data element: " + Arrays.toString(dataElem.entrySet().toArray()));
        return dataElem;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.input.IInputPlugin#getName()
     */
    @Override
    public String getName() {
        return PLUGIN_NAME;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.input.IInputPlugin#getNewData()
     */
    @Override
    public abstract List<Map<String, Object>> getNewData();

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.input.IInputPlugin#getStatus()
     */
    @Override
    public int getStatus() {
        return this.status;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.input.IInputPlugin#getStatusString()
     */
    @Override
    public String getStatusString() {
        return this.statusString;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.input.IInputPlugin#getUserInterface()
     */
    @Override
    public ModuleGUI getUserInterface() {
        return this.gui;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.input.IInputPlugin#hasNewData()
     */
    @Override
    public abstract boolean hasNewData();

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.common.IModule#init()
     */
    @Override
    public void init() throws Exception {
        log.info("initializing ...");

        // create GUI
        this.gui = new ModuleGUI();
        this.panel = new JPanel();
        this.panel.setLayout(new BorderLayout());
        this.panel.add(makeControlPanel(), BorderLayout.NORTH);
        this.panel.add(makeStatusLabel(), BorderLayout.SOUTH);
        this.textArea = new JTextArea();
        this.textArea.setEditable(false);
        DefaultCaret caret = (DefaultCaret) this.textArea.getCaret();
        caret.setUpdatePolicy(DefaultCaret.ALWAYS_UPDATE);
        JScrollPane scrollPane = new JScrollPane(this.textArea);
        this.panel.add(scrollPane, BorderLayout.CENTER);

        this.gui.setMenu(makeMenu());
        this.gui.setGui(this.panel);

        // try loading the database driver
        try {
            Class.forName(this.driver);
        } catch (ClassNotFoundException e) {
            log.error(e);
        }

        // create database connection
        Connector connector = new Connector(this);
        this.futureConnection = Executors.newSingleThreadExecutor().submit(connector);

        log.info("initialized.");
    }

    /**
     * 
     * @return
     */
    protected abstract JPanel makeControlPanel();

    /**
     * 
     * @return
     */
    protected abstract JMenu makeMenu();

    /**
     * 
     * @return
     */
    protected JLabel makeStatusLabel() {
        if (this.statusLabel == null)
            this.statusLabel = new JLabel();

        StringBuilder sb = new StringBuilder();
        sb.append("<html><p>");
        sb.append("<b>Status: </b>");
        sb.append(this.statusString);
        sb.append("</p><p><b>Database host: </b>");
        sb.append(this.host);
        sb.append("</p><p><b>Database name: </b>");
        sb.append(this.databaseName);
        sb.append("</p><p><b>Table name: </b>");
        sb.append(this.tableName);
        sb.append("</p><p><b>Time column: </b>");
        sb.append(this.timeColumnName);
        sb.append("</p></html>");

        this.statusLabel.setText(sb.toString());
        return this.statusLabel;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.n52.ifgicopter.spf.common.IModule#shutdown()
     */
    @Override
    public void shutdown() throws Exception {
        // close database connection, might block if the connection is not established yet.
        Connection conn = getConnection();
        if (conn != null)
            conn.close();
    }
}