org.deegree.tools.crs.EPSGDBSynchronizer.java Source code

Java tutorial

Introduction

Here is the source code for org.deegree.tools.crs.EPSGDBSynchronizer.java

Source

//$HeadURL: svn+ssh://aionita@svn.wald.intevation.org/deegree/base/trunk/resources/eclipse/files_template.xml $
/*----------------------------------------------------------------------------
 This file is part of deegree, http://deegree.org/
 Copyright (C) 2001-2009 by:
 Department of Geography, University of Bonn
 and
 lat/lon GmbH
    
 This library 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 2.1 of the License, or (at your option)
 any later version.
 This library 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 this library; if not, write to the Free Software Foundation, Inc.,
 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    
 Contact information:
    
 lat/lon GmbH
 Aennchenstr. 19, 53177 Bonn
 Germany
 http://lat-lon.de/
    
 Department of Geography, University of Bonn
 Prof. Dr. Klaus Greve
 Postfach 1147, 53001 Bonn
 Germany
 http://www.geographie.uni-bonn.de/deegree/
    
 e-mail: info@deegree.org
 ----------------------------------------------------------------------------*/

package org.deegree.tools.crs;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import org.deegree.commons.annotations.Tool;
import org.deegree.commons.tools.CommandUtils;
import org.deegree.cs.CRSCodeType;
import org.deegree.cs.coordinatesystems.ICRS;
import org.deegree.cs.coordinatesystems.IProjectedCRS;
import org.deegree.cs.persistence.deegree.db.DBCRSStore;
import org.deegree.cs.projections.IProjection;
import org.deegree.cs.projections.azimuthal.LambertAzimuthalEqualArea;
import org.deegree.cs.projections.azimuthal.StereographicAlternative;
import org.deegree.cs.projections.azimuthal.StereographicAzimuthal;
import org.deegree.cs.projections.conic.LambertConformalConic;
import org.deegree.cs.projections.cylindric.TransverseMercator;
import org.deegree.cs.transformations.TransformationFactory.DSTransform;
import org.deegree.tools.coverage.gridifier.RasterTreeGridifier;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>EPSGDBSynchronizer</code> class sets the Codes for CRS Identifiables that do not have such codes (actually,
 * since these code are required for CRS Identifiables to exist, they are temporary).
 * 
 * The connection parameters used are :
 * <ul>
 * <li>JDBC Driver: org.postgresql.Driver</li>
 * <li>Connection protocol: jdbc:postgresql://hurricane/epsg?user=postgres</li>
 * </ul>
 * 
 * Currently the codes for the projections are set. The Axis element also need codes, but the axis attributes values are
 * quite different in the EPSG database and more work on how to automate this process has to be done.
 * 
 * <b> In order to succeed in changing the codetypes in the CRS database, the user must set the variable CRS_DB_URL with
 * the protocol jdbc:derby:... prior to running this tool. At the moment of writing the database is at
 * d3_core/bin/META-INF/deegreeCRS/</b>
 * 
 * @author <a href="mailto:ionita@lat-lon.de">Andrei Ionita</a>
 * 
 * @author last edited by: $Author: ionita $
 * 
 * @version $Revision: $, $Date: $
 * 
 */
@Tool("Connects to the EPSG database at //hurricane/epsg, and for all projections (other objects to be added!) that have no CRS codetype in the CRS database, the codes are fetched from the EPSG database.")
public class EPSGDBSynchronizer {

    private static Logger LOG = LoggerFactory.getLogger(EPSGDBSynchronizer.class);

    // private static final String CRS_CONFIG = "org.deegree.cs.configuration.deegree.db.DatabaseCRSProvider";

    private static final String JDBC_DRIVER = "org.postgresql.Driver";

    private static final String JDBC_CONNECTION_PATH = "jdbc:postgresql://hurricane/epsg?user=postgres";

    private Connection EPSGdbConn;

    private String epsgPath;

    protected void connectToEPSGdatabase() {
        try {
            Class.forName(JDBC_DRIVER);
            EPSGdbConn = DriverManager.getConnection(epsgPath);
        } catch (ClassNotFoundException e) {
            LOG.error(e.getMessage(), e);
        } catch (SQLException e) {
            LOG.error(e.getMessage(), e);
        }
    }

    protected void getCodesForProjections(DBCRSStore dbSTore) {
        try {
            // select the EPSG code of all ProjectedCRS's, and their projection projection codes and type
            PreparedStatement ps = EPSGdbConn.prepareStatement("SELECT coord_ref_sys_code, "
                    + "coord_op_method_code, " + "coord_op_code " + "FROM epsg_coordinatereferencesystem, "
                    + "epsg_coordoperation " + "WHERE coord_ref_sys_kind = 'projected' AND "
                    + "projection_conv_code = coord_op_code");
            ResultSet largeRs = ps.executeQuery();
            while (largeRs.next()) {
                int projectedCRSCode = largeRs.getInt(1);
                int projectionTypeCode = largeRs.getInt(2);
                int projectionCode = largeRs.getInt(3);

                ICRS crs = dbSTore.getCRSByCode(new CRSCodeType(String.valueOf(projectedCRSCode), "EPSG"));

                if (crs != null && (crs instanceof IProjectedCRS)) {
                    // if the projections are of the known types ( Transverse Mercator, Lambert Azimuthal EA, Lambert
                    // Conic Conformal, Stereographic alternative or Stereografic azimuthal )
                    if (projectionTypeCode == 9807 || projectionTypeCode == 9820 || projectionTypeCode == 9801
                            || projectionTypeCode == 9809 || projectionTypeCode == 9810) {
                        IProjectedCRS projectedCRS = (IProjectedCRS) crs;
                        IProjection projection = projectedCRS.getProjection();

                        ps = EPSGdbConn.prepareStatement(
                                "SELECT parameter_value, parameter_code FROM epsg_coordoperationparamvalue "
                                        + "WHERE coord_op_code = " + projectionCode);
                        ResultSet rs = ps.executeQuery();

                        // initialize the specific projection attributes
                        double latNatOrigin = Double.NaN;
                        double longNatOrigin = Double.NaN;
                        double scale = Double.NaN;
                        double falseEasting = Double.NaN;
                        double falseNorthing = Double.NaN;

                        // get the attributes values according to their codes
                        while (rs.next()) {
                            if (rs.getInt(2) == 8801)
                                latNatOrigin = rs.getDouble(1);
                            else if (rs.getInt(2) == 8802)
                                longNatOrigin = rs.getDouble(1);
                            else if (rs.getInt(2) == 8805)
                                scale = rs.getDouble(1);
                            else if (rs.getInt(2) == 8806)
                                falseEasting = rs.getDouble(1);
                            else if (rs.getInt(2) == 8807)
                                falseNorthing = rs.getDouble(1);
                        }

                        //
                        // TRANSVERSE MERCATOR
                        //
                        if (projectionTypeCode == 9807 && (projection instanceof TransverseMercator)) {
                            TransverseMercator tmProjection = (TransverseMercator) projection;
                            // compare the CRS database projection attributes with the attributes from the EPSG database
                            if (java.lang.Math
                                    .abs(tmProjection.getNaturalOrigin().y - Math.toRadians(latNatOrigin)) < 1e-7
                                    && java.lang.Math.abs(tmProjection.getNaturalOrigin().x
                                            - Math.toRadians(longNatOrigin)) < 1e-7
                                    && tmProjection.getScale() == scale
                                    && tmProjection.getFalseEasting() == falseEasting
                                    && tmProjection.getFalseNorthing() == falseNorthing) {
                                LOG.info(
                                        "The two Transverse Mercator projections attributes match. Updating the projection with Code: "
                                                + projectionCode);

                                // do the UPDATE
                                // int pInternalID = dbProvider.getInternalID( tmProjection );
                                // dbProvider.setCode( pInternalID, String.valueOf( projectionCode ) );
                            }
                        }

                        //
                        // LAMBERT AZIMUTHAL EQUAL AREA
                        //
                        if (projectionTypeCode == 9820 && (projection instanceof LambertAzimuthalEqualArea)) {
                            LambertAzimuthalEqualArea laeaProjection = (LambertAzimuthalEqualArea) projection;
                            // compare the CRS database projection attributes with the attributes from the EPSG database
                            if (java.lang.Math
                                    .abs(laeaProjection.getNaturalOrigin().y - Math.toRadians(latNatOrigin)) < 1e-7
                                    && java.lang.Math.abs(laeaProjection.getNaturalOrigin().x
                                            - Math.toRadians(longNatOrigin)) < 1e-7
                                    && laeaProjection.getFalseEasting() == falseEasting && // no scale comparison since no
                                    // scale attribute
                                    laeaProjection.getFalseNorthing() == falseNorthing) {
                                LOG.info(
                                        "The two Lambert Azimuthal projections attributes match. Updating the projection with Code: "
                                                + projectionCode);

                                // do the UPDATE
                                // int pInternalID = dbProvider.getInternalID( laeaProjection );
                                // dbProvider.setCode( pInternalID, String.valueOf( projectionCode ) );
                            }
                        }

                        //
                        // LAMBERT CONIC CONFORMAL
                        //
                        if (projectionTypeCode == 9801 && (projection instanceof LambertConformalConic)) {
                            LambertConformalConic lccProjection = (LambertConformalConic) projection;
                            // compare the CRS database projection attributes with the attributes from the EPSG database
                            if (java.lang.Math
                                    .abs(lccProjection.getNaturalOrigin().y - Math.toRadians(latNatOrigin)) < 1e-7
                                    && java.lang.Math.abs(lccProjection.getNaturalOrigin().x
                                            - Math.toRadians(longNatOrigin)) < 1e-7
                                    && lccProjection.getScale() == scale
                                    && lccProjection.getFalseEasting() == falseEasting
                                    && lccProjection.getFalseNorthing() == falseNorthing) {
                                LOG.info(
                                        "The two Lambert Conic Conformal projections attributes match. Updating the projection with the Code "
                                                + projectionCode);

                                // do the UPDATE
                                // int pInternalID = dbProvider.getInternalID( lccProjection );
                                // dbProvider.setCode( pInternalID, String.valueOf( projectionCode ) );
                            }
                        }

                        //
                        // STEREOGRAPHIC
                        //
                        if (projectionTypeCode == 9809 || projectionTypeCode == 9810) {
                            if (projection instanceof StereographicAlternative) {
                                StereographicAlternative salProjection = (StereographicAlternative) projection;
                                // compare the CRS database projection attributes with the attributes from the EPSG
                                // database
                                if (java.lang.Math.abs(
                                        salProjection.getNaturalOrigin().y - Math.toRadians(latNatOrigin)) < 0.00001
                                        && java.lang.Math.abs(salProjection.getNaturalOrigin().x
                                                - Math.toRadians(longNatOrigin)) < 0.00001
                                        && salProjection.getScale() == scale
                                        && salProjection.getFalseEasting() == falseEasting
                                        && salProjection.getFalseNorthing() == falseNorthing) {
                                    LOG.info(
                                            "The two StereographicAlternative projections attributes match. Updating the projection with the Code: "
                                                    + projectionCode);

                                    // do the UPDATE
                                    // int pInternalID = dbProvider.getInternalID( salProjection );
                                    // dbProvider.setCode( pInternalID, String.valueOf( projectionCode ) );
                                }
                            } else if (projection instanceof StereographicAzimuthal) {
                                StereographicAzimuthal sazProjection = (StereographicAzimuthal) projection;
                                // compare the CRS database projection attributes with the attributes from the EPSG
                                // database
                                if (java.lang.Math.abs(
                                        sazProjection.getNaturalOrigin().y - Math.toRadians(latNatOrigin)) < 0.00001
                                        && java.lang.Math.abs(sazProjection.getNaturalOrigin().x
                                                - Math.toRadians(longNatOrigin)) < 0.00001
                                        && sazProjection.getScale() == scale
                                        && sazProjection.getFalseEasting() == falseEasting
                                        && sazProjection.getFalseNorthing() == falseNorthing) {
                                    LOG.info(
                                            "The two StereographicAzimuthal projections attributes match. Updating the projectio with the Code: "
                                                    + projectionCode);

                                    // do the UPDATE
                                    // int pInternalID = dbProvider.getInternalID( sazProjection );
                                    // dbProvider.setCode( pInternalID, String.valueOf( projectionCode ) );
                                }
                            }
                        }
                    }
                }
            }
        } catch (SQLException e) {
            LOG.error(e.getMessage());
        }
    }

    // ---------- Still to be worked upon, since the EPSG data for Axis is pretty different in form. Need to make a
    // semantic correspondence in order to automate this.
    // protected void getCodesForAxes( DatabaseCRSProvider dbProvider ) throws SQLException {
    // PreparedStatement ps = EPSGdbConn.prepareStatement(
    // "SELECT coord_sys_code, " +
    // "coord_axis_orientation, " +
    // "coord_axis_name, unit_of_meas_name " +
    // "FROM epsg_coordinateaxisname, epsg_coordinateaxis, epsg_unitofmeasure " +
    // "WHERE epsg_unitofmeasure.uom_code = epsg_coordinateaxis.uom_code " +
    // "AND epsg_coordinateaxis.coord_axis_name_code = epsg_coordinateaxisname.coord_axis_name_code ");
    // ResultSet rs = ps.executeQuery();
    //
    // while ( rs.next() ) {
    // EPSGCode code = new EPSGCode( rs.getInt( 1 ) );
    //
    // String axisOrientation = rs.getString( 2 );
    // // do some adjusting of the string to our in-house names
    // if ( axisOrientation.toLowerCase().contains( "north" ) )
    // axisOrientation = "north";
    // else if ( axisOrientation.toLowerCase().contains( "east" ) )
    // axisOrientation = "east";
    // else if ( axisOrientation.toLowerCase().contains( "up" ) )
    // axisOrientation = "up";
    //
    // String axisName = rs.getString( 3 );
    // // do some adjusting of the string to our in-house names
    // if ( axisName.toLowerCase().contains( "longitude" ) )
    // axisName = "longitude";
    // else if ( axisName.toLowerCase().contains( "latitude" ) )
    // axisName = "latitude";
    // else if ( axisName.toLowerCase().contains( "height" ) )
    // axisName = "height";
    // else if ( axisName.toLowerCase().contains( "x" ) )
    // axisName = "x";
    // else if ( axisName.toLowerCase().contains( "y" ) )
    // axisName = "y";
    //
    // Unit uom = Unit.createUnitFromString( rs.getString( 4 ) );
    //
    // dbProvider.changeAxisCode( axisName, axisOrientation, uom, code );
    // }
    // }

    public EPSGDBSynchronizer() {
        // nothing necessary yet
    }

    protected void closeEPSGConnection() throws SQLException {
        EPSGdbConn.close();
    }

    static private Options initOptions() {
        Options options = new Options();

        Option opt = new Option("epsgPath", true, "path to epsg database");
        options.addOption(opt);

        CommandUtils.addDefaultOptions(options);

        return options;
    }

    private static void printHelp(Options options) {
        CommandUtils.printHelp(options, RasterTreeGridifier.class.getSimpleName(), null, "file/dir [file/dir(s)]");
    }

    static public void main(String[] args) {
        EPSGDBSynchronizer sync = new EPSGDBSynchronizer();

        Options options = initOptions();

        try {
            CommandLine line = new PosixParser().parse(options, args);

            if (line.hasOption("help")) {
                printHelp(options);
            }

            sync.epsgPath = options.getOption("epsgPath").getValue();

            if (sync.epsgPath == null || sync.epsgPath.trim().length() == 0) {
                sync.epsgPath = JDBC_CONNECTION_PATH;
                LOG.info("Using the default JDBC_CONNECTION_PATH: " + JDBC_CONNECTION_PATH);
            }

            sync.connectToEPSGdatabase();

            // get the CRS database provider
            DBCRSStore dbStore = new DBCRSStore(DSTransform.HELMERT);

            sync.getCodesForProjections(dbStore);

            // synchronizer.getCodesForAxes( dbProvider );

        } catch (ParseException e) {
            LOG.error(e.getMessage());
            e.printStackTrace();
        }

    }
}