/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2012, Geomatys
*
* 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;
* version 2.1 of the License.
*
* 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.
*/
package org.geotoolkit.coverage.postgresql.epsg;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Calendar;
import java.util.List;
import java.util.TimeZone;
import org.opengis.metadata.Identifier;
import javax.measure.Unit;
import javax.sql.DataSource;
import org.apache.sis.internal.referencing.GeodeticObjectBuilder;
import org.geotoolkit.coverage.postgresql.PGCoverageStore;
import org.opengis.referencing.crs.CompoundCRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.crs.TemporalCRS;
import org.opengis.referencing.crs.VerticalCRS;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.operation.Projection;
import org.opengis.util.FactoryException;
import static org.geotoolkit.coverage.postgresql.epsg.PGEPSGQueries.*;
import org.geotoolkit.referencing.EPSGWriter;
import org.apache.sis.referencing.datum.AbstractDatum;
import org.apache.sis.referencing.factory.IdentifiedObjectFinder;
import org.geotoolkit.temporal.object.TemporalUtilities;
import org.opengis.metadata.extent.Extent;
import org.opengis.referencing.IdentifiedObject;
import org.opengis.referencing.crs.SingleCRS;
import org.opengis.referencing.cs.CartesianCS;
import org.opengis.referencing.cs.EllipsoidalCS;
import org.opengis.referencing.cs.TimeCS;
import org.opengis.referencing.cs.VerticalCS;
import org.opengis.referencing.datum.Datum;
import org.opengis.referencing.datum.Ellipsoid;
import org.opengis.referencing.datum.GeodeticDatum;
import org.opengis.referencing.datum.PrimeMeridian;
import org.opengis.referencing.datum.TemporalDatum;
import org.opengis.referencing.datum.VerticalDatum;
import org.apache.sis.referencing.IdentifiedObjects;
import org.apache.sis.referencing.factory.sql.EPSGFactory;
import org.apache.sis.measure.Units;
/**
* EPSG Writer.
*
* @author Johann Sorel (Geomatys)
*/
public class PGEPSGWriter implements EPSGWriter {
private final PGCoverageStore store;
private final DataSource source;
private final EPSGFactory factory;
public PGEPSGWriter(final PGCoverageStore store) throws FactoryException {
this.store = store;
this.source = store.getDataSource();
this.factory = store.getEPSGFactory();
}
/**
* Use sequence in database to ensure having a unique code.
* @return next free epsg code in range >= 32768 et < 60 000 000
*/
private int getNextCode() throws SQLException{
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
cnx = source.getConnection();
cnx.setReadOnly(false);
stmt = cnx.prepareStatement(NEXT_CODE.query());
rs = stmt.executeQuery();
rs.next();
return rs.getInt(1);
}finally{
store.closeSafe(cnx, stmt, rs);
}
}
private String searchSimilar(Class clazz, IdentifiedObject candidate) throws FactoryException{
final IdentifiedObjectFinder finder = factory.newIdentifiedObjectFinder();
final Identifier id = IdentifiedObjects.getIdentifier(finder.findSingleton(candidate), null);
return (id != null) ? id.getCode() : null;
}
@Override
public int getOrCreateCoordinateReferenceSystem(final CoordinateReferenceSystem candidate) throws FactoryException{
//search if this object already exist
final String code = searchSimilar(CoordinateReferenceSystem.class, candidate);
if(code != null){
return codeToID(code);
}
//all required parameters
final Integer coord_ref_sys_code;
final String coord_ref_sys_name = candidate.getName().getCode();
final String coord_ref_sys_kind;
final Integer coord_sys_code;
final Integer datum_code;
final Integer source_geogcrs_code;
final Integer projection_conv_code;
final Integer cmpd_horizcrs_code;
final Integer cmpd_vertcrs_code;
final String crs_scope = (candidate.getScope() == null)? "" : candidate.getScope().toString();
final String remarks = (candidate.getRemarks() == null)? null : candidate.getRemarks().toString();
final String information_source = (candidate.getName().getCodeSpace()==null)? null : candidate.getName().getCodeSpace();
final String data_source = (candidate.getName().getCodeSpace()==null)? "" : candidate.getName().getCodeSpace();
final Date revision_date = new Date(System.currentTimeMillis());
final String change_id = "";
final Integer show_crs = 1;
final Integer deprecated = 0;
if(candidate instanceof CompoundCRS){
coord_ref_sys_kind = "compound";
coord_sys_code = null;
datum_code = null;
source_geogcrs_code = null;
projection_conv_code = null;
final CompoundCRS compound = (CompoundCRS) candidate;
final List<CoordinateReferenceSystem> parts = compound.getComponents();
cmpd_horizcrs_code = getOrCreateCoordinateReferenceSystem(parts.get(0));
if(parts.size() == 2){
cmpd_vertcrs_code = getOrCreateCoordinateReferenceSystem(parts.get(1));
}else{
//we can only aggregate crs two by two
final CoordinateReferenceSystem[] toSplit = new CoordinateReferenceSystem[parts.size()-1];
for(int i=1;i<parts.size();i++){
toSplit[i-1] = parts.get(i);
}
final CoordinateReferenceSystem secondPart = new GeodeticObjectBuilder().addName("Split-" + candidate.getName().getCode())
.createCompoundCRS(toSplit);
cmpd_vertcrs_code = getOrCreateCoordinateReferenceSystem(secondPart);
}
}else{
cmpd_horizcrs_code = null;
cmpd_vertcrs_code = null;
final CoordinateSystem cs = candidate.getCoordinateSystem();
coord_sys_code = getOrCreateCoordinateSystem(cs);
if(candidate instanceof GeographicCRS){
final GeographicCRS geocrs = (GeographicCRS) candidate;
coord_ref_sys_kind = "geographic 2D";
datum_code = getOrCreateDatum(geocrs.getDatum());
source_geogcrs_code = null; //TODO this can be non-null, when ?
projection_conv_code = null; //TODO this can be non-null, when ?
}else if(candidate instanceof ProjectedCRS){
final ProjectedCRS projcrs = (ProjectedCRS) candidate;
coord_ref_sys_kind = "projected";
datum_code = null;
source_geogcrs_code = getOrCreateCoordinateReferenceSystem(projcrs.getBaseCRS());
projection_conv_code = getOrCreateProjection(projcrs.getConversionFromBase());
}else if(candidate instanceof TemporalCRS){
final TemporalCRS tempcrs = (TemporalCRS) candidate;
coord_ref_sys_kind = "temporal";
datum_code = getOrCreateDatum(tempcrs.getDatum());
source_geogcrs_code = null;
projection_conv_code = null;
}else if(candidate instanceof VerticalCRS){
final VerticalCRS vertcrs = (VerticalCRS) candidate;
coord_ref_sys_kind = "vertical";
datum_code = getOrCreateDatum(vertcrs.getDatum());
source_geogcrs_code = null;
projection_conv_code = null;
}else if(candidate instanceof SingleCRS){
final SingleCRS singlecrs = (SingleCRS) candidate;
coord_ref_sys_kind = "single";
datum_code = getOrCreateDatum(singlecrs.getDatum());
source_geogcrs_code = null;
projection_conv_code = null;
}else{
throw new FactoryException("Can not store given crs : " +candidate);
}
}
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
cnx = source.getConnection();
//find similar
final Integer similar = findSimilar(cnx, FIND_COORDINATE_REFERENCE_SYSTEM,
coord_ref_sys_kind,coord_sys_code,datum_code,source_geogcrs_code,
projection_conv_code,cmpd_horizcrs_code,cmpd_vertcrs_code);
if(similar != null){ return similar; }
final Integer area_of_use_code = getOrCreateArea(candidate.getDomainOfValidity());
cnx.setReadOnly(false);
coord_ref_sys_code = getNextCode();
stmt = cnx.prepareStatement(CREATE_COORDINATE_REFERENCE_SYSTEM.query());
CREATE_COORDINATE_REFERENCE_SYSTEM.fillStatement(stmt,
coord_ref_sys_code,
coord_ref_sys_name,
area_of_use_code,
coord_ref_sys_kind,
coord_sys_code,
datum_code,
source_geogcrs_code,
projection_conv_code,
cmpd_horizcrs_code,
cmpd_vertcrs_code,
crs_scope,
remarks,
information_source,
data_source,
revision_date,
change_id,
show_crs,
deprecated);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
return coord_ref_sys_code;
}
@Override
public int getOrCreateCoordinateSystem(final CoordinateSystem candidate) throws FactoryException{
//search if this object already exist
final String code = searchSimilar(CoordinateSystem.class, candidate);
if(code != null){
return codeToID(code);
}
final Integer coord_sys_code;
final String coord_sys_name = candidate.getName().getCode();
final String coord_sys_type = getCoordinateSystemType(candidate);
final Integer dimension = candidate.getDimension();
final String remarks = (candidate.getRemarks() == null)? null : candidate.getRemarks().toString();
final String information_source = (candidate.getName().getCodeSpace()==null)? null : candidate.getName().getCodeSpace();
final String data_source = (candidate.getName().getCodeSpace()==null)? "" : candidate.getName().getCodeSpace();
final Date revision_date = new Date(System.currentTimeMillis());
final String change_id = "";
final Integer deprecated = 0;
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
cnx = source.getConnection();
//find similar
final Integer similar = findSimilarCoordinateSystem(candidate, cnx);
if(similar != null){ return similar; }
cnx.setReadOnly(false);
coord_sys_code = getNextCode();
stmt = cnx.prepareStatement(CREATE_COORDINATE_SYSTEM.query());
CREATE_COORDINATE_SYSTEM.fillStatement(stmt,
coord_sys_code,
coord_sys_name,
coord_sys_type,
dimension,
remarks,
information_source,
data_source,
revision_date,
change_id,
deprecated
);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
//generate axis
for(int i=0;i<dimension;i++){
final CoordinateSystemAxis axis = candidate.getAxis(i);
createCoordinateSystemAxis(coord_sys_code,i+1,axis);
}
return coord_sys_code;
}
private int createCoordinateSystemAxis(final int csid, final int axisOrder,
final CoordinateSystemAxis candidate) throws FactoryException{
final Integer coord_axis_code;
final Integer coord_sys_code = csid;
final Integer coord_axis_name_code = createCoordinateSystemAxisName(candidate);
final String coord_axis_orientation = candidate.getDirection().name();
final String coord_axis_abbreviation = candidate.getAbbreviation();
final Integer uom_code = getOrCreateUOM(candidate.getUnit());
final Integer coord_axis_order = axisOrder;
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
coord_axis_code = getNextCode();
cnx = source.getConnection();
cnx.setReadOnly(false);
stmt = cnx.prepareStatement(CREATE_COORDINATE_AXIS.query());
CREATE_COORDINATE_AXIS.fillStatement(stmt,
coord_axis_code,
coord_sys_code,
coord_axis_name_code,
coord_axis_orientation,
coord_axis_abbreviation,
uom_code,
coord_axis_order
);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
return coord_axis_code;
}
private int createCoordinateSystemAxisName(final CoordinateSystemAxis candidate) throws FactoryException{
final Integer coord_axis_name_code;
final String coord_axis_name = candidate.getName().getCode();
final String description = (candidate.getRemarks() == null)? null : candidate.getRemarks().toString();
final String remarks = (candidate.getRemarks() == null)? null : candidate.getRemarks().toString();
final String information_source = (candidate.getName().getCodeSpace()==null)? null : candidate.getName().getCodeSpace();
final String data_source = (candidate.getName().getCodeSpace()==null)? "" : candidate.getName().getCodeSpace();
final Date revision_date = new Date(System.currentTimeMillis());
final String change_id = "";
final Integer deprecated = 0;
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
coord_axis_name_code = getNextCode();
cnx = source.getConnection();
cnx.setReadOnly(false);
stmt = cnx.prepareStatement(CREATE_COORDINATE_AXIS_NAME.query());
CREATE_COORDINATE_AXIS_NAME.fillStatement(stmt,
coord_axis_name_code,
coord_axis_name,
description,
remarks,
information_source,
data_source,
revision_date,
change_id,
deprecated
);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
return coord_axis_name_code;
}
@Override
public int getOrCreateDatum(final Datum candidate) throws FactoryException{
//search if this object already exist
final String code = searchSimilar(Datum.class, candidate);
if(code != null){
return codeToID(code);
}
final Integer datum_code;
final String datum_name = candidate.getName().getCode();
final String datum_type;
final String origin_description;
final Integer realization_epoch;
final Integer ellipsoid_code;
final Integer prime_meridian_code;
final String datum_scope = (candidate.getRemarks() == null)? "" : candidate.getRemarks().toString();
final String remarks = (candidate.getRemarks() == null)? null : candidate.getRemarks().toString();
final String information_source = (candidate.getName().getCodeSpace()==null)? null : candidate.getName().getCodeSpace();
final String data_source = (candidate.getName().getCodeSpace()==null)? "" : candidate.getName().getCodeSpace();
final Date revision_date = new Date(System.currentTimeMillis());
final String change_id = "";
final Integer deprecated = 0;
if(candidate.getRealizationEpoch() == null){
realization_epoch = null;
}else{
final Calendar c = Calendar.getInstance();
c.setTime(candidate.getRealizationEpoch());
realization_epoch = c.get(Calendar.YEAR);
}
if(candidate instanceof GeodeticDatum){
final GeodeticDatum gd = (GeodeticDatum) candidate;
origin_description = "";
datum_type = "geodetic";
ellipsoid_code = getOrCreateEllipsoid(gd.getEllipsoid());
prime_meridian_code = getOrCreatePrimeMeridian(gd.getPrimeMeridian());
}else if(candidate instanceof VerticalDatum){
final VerticalDatum vd = (VerticalDatum) candidate;
origin_description = "";
datum_type = "vertical";
ellipsoid_code = null;
prime_meridian_code = null;
}else if(candidate instanceof TemporalDatum){
final TemporalDatum td = (TemporalDatum) candidate;
origin_description = TemporalUtilities.toISO8601Z(td.getOrigin(), TimeZone.getTimeZone("GMT+0"));
datum_type = "temporal";
ellipsoid_code = null;
prime_meridian_code = null;
}else if(candidate instanceof AbstractDatum){
final AbstractDatum td = (AbstractDatum) candidate;
origin_description = "";
datum_type = "abstract";
ellipsoid_code = null;
prime_meridian_code = null;
}else {
throw new FactoryException("Can not store given datum : " +candidate);
}
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
cnx = source.getConnection();
//find similar
if (!(candidate instanceof VerticalDatum)) {
final Integer similar = findSimilar(cnx, FIND_DATUM, datum_type,origin_description,ellipsoid_code,prime_meridian_code);
if(similar != null){ return similar; }
}
final Integer area_of_use_code = getOrCreateArea(candidate.getDomainOfValidity());
cnx.setReadOnly(false);
datum_code = getNextCode();
stmt = cnx.prepareStatement(CREATE_DATUM.query());
CREATE_DATUM.fillStatement(stmt,
datum_code,
datum_name,
datum_type,
origin_description,
realization_epoch,
ellipsoid_code,
prime_meridian_code,
area_of_use_code,
datum_scope,
remarks,
information_source,
data_source,
revision_date,
change_id,
deprecated
);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
return datum_code;
}
@Override
public int getOrCreateProjection(final Projection candidate) throws FactoryException{
//search if this object already exist
final String code = searchSimilar(Projection.class, candidate);
if(code != null){
return codeToID(code);
}
throw new FactoryException("No supported yet.");
// final ParameterValueGroup parameters = candidate.getParameterValues();
//
// final Integer coord_op_code;
// final String coord_op_name;
// final String coord_op_type;
// final Integer source_crs_code;
// final Integer target_crs_code;
// final String coord_tfm_version;
// final Integer coord_op_variant;
// final Integer area_of_use_code;
// final String coord_op_scope;
// final Double coord_op_accuracy;
// final Integer coord_op_method_code;
// final Integer uom_code_source_coord_diff;
// final Integer uom_code_target_coord_diff;
// final String remarks = (candidate.getRemarks() == null)? null : candidate.getRemarks().toString();
// final String information_source = (candidate.getName().getCodeSpace()==null)? null : candidate.getName().getCodeSpace();
// final String data_source = (candidate.getName().getCodeSpace()==null)? "" : candidate.getName().getCodeSpace();
// final Date revision_date = new Date(System.currentTimeMillis());
// final String change_id = "";
// final Integer show_operation = 1;
// final Integer deprecated = 0;
//
// //save object
// Connection cnx = null;
// PreparedStatement stmt = null;
// ResultSet rs = null;
// try{
// coord_op_code = getNextCode();
//
// cnx = source.getConnection();
// stmt = cnx.prepareStatement(CREATE_COORDINATE_OPERATION.query());
// CREATE_COORDINATE_OPERATION.fillStatement(stmt,
// coord_op_code,
// coord_op_name,
// coord_op_type,
// source_crs_code,
// target_crs_code,
// coord_tfm_version,
// coord_op_variant,
// area_of_use_code,
// coord_op_scope,
// coord_op_accuracy,
// coord_op_method_code,
// uom_code_source_coord_diff,
// uom_code_target_coord_diff,
// remarks,
// information_source,
// data_source,
// revision_date,
// change_id,
// show_operation,
// deprecated
// );
// stmt.executeUpdate();
// }catch(SQLException ex){
// throw new FactoryException(ex);
// }finally{
// store.closeSafe(cnx, stmt, rs);
// }
//
// return coord_op_code;
}
@Override
public int getOrCreateArea(final Extent candidate) throws FactoryException{
if(candidate == null){
//world extent
return 1262;
}
if(candidate instanceof IdentifiedObject){
final IdentifiedObject ie = (IdentifiedObject) candidate;
final String code = searchSimilar(ie.getClass(), ie);
if(code != null){
return codeToID(code);
}
}
//TODO save object, return code
//return world extent for now
return 1262;
}
@Override
public int getOrCreateUOM(final Unit candidate) throws FactoryException{
final Integer uom_code;
final String unit_of_meas_name = candidate.toString();
final String unit_of_meas_type;
Integer target_uom_code = null;
final Double factor_b = 1d; //TODO must check if unit is derivate and extract scale
final Double factor_c = 1d; //TODO must check if unit is derivate and extract offset
final String remarks = "";
final String information_source = null;
final String data_source = "";
final Date revision_date = new Date(System.currentTimeMillis());
final String change_id = "";
final Integer deprecated = 0;
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
final boolean selfDefined;
if(candidate.isCompatible(Units.METRE)){
selfDefined = false;
target_uom_code = 9001;
unit_of_meas_type = "length";
}else if(candidate.isCompatible(Units.RADIAN)){
selfDefined = false;
target_uom_code = 9102;
unit_of_meas_type = "angle";
}else if(candidate.isCompatible(Units.SECOND)){
selfDefined = true;
//refer to self, epsg does not contain any temporal unit we could refer to
unit_of_meas_type = "temp";
}else{
selfDefined = true;
//refer to self
unit_of_meas_type = "unknown";
}
cnx = source.getConnection();
//find similar
final Integer similar;
if(selfDefined){
similar = findSimilar(cnx, FIND_UNIT_OF_MEASURE_SELF, unit_of_meas_name, unit_of_meas_type,factor_b,factor_c);
}else{
similar = findSimilar(cnx, FIND_UNIT_OF_MEASURE, unit_of_meas_name, unit_of_meas_type,target_uom_code,factor_b,factor_c);
}
if(similar != null){ return similar; }
cnx.setReadOnly(false);
uom_code = getNextCode();
if(selfDefined){
target_uom_code = uom_code;
}
stmt = cnx.prepareStatement(CREATE_UNIT_OF_MEASURE.query());
CREATE_UNIT_OF_MEASURE.fillStatement(stmt,
uom_code,
unit_of_meas_name,
unit_of_meas_type,
target_uom_code,
factor_b,
factor_c,
remarks,
information_source,
data_source,
revision_date,
change_id,
deprecated
);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
return uom_code;
}
@Override
public int getOrCreateEllipsoid(final Ellipsoid candidate) throws FactoryException{
final String code = searchSimilar(Ellipsoid.class, candidate);
if(code != null){
return codeToID(code);
}
final Integer ellipsoid_code;
final String ellipsoid_name = candidate.getName().getCode();
final Double semi_major_axis = candidate.getSemiMajorAxis();
final Integer uom_code = getOrCreateUOM(candidate.getAxisUnit());
final Double inv_flattening = candidate.getInverseFlattening();
final Double semi_minor_axis = candidate.getSemiMinorAxis();
final Integer ellipsoid_shape = 1; //TODO how do we know that ?
final String remarks = (candidate.getRemarks()==null)? "" : candidate.getRemarks().toString();
final String information_source = (candidate.getName().getCodeSpace()==null)? null : candidate.getName().getCodeSpace();
final String data_source = (candidate.getName().getCodeSpace()==null)? "" : candidate.getName().getCodeSpace();
final Date revision_date = new Date(System.currentTimeMillis());
final String change_id = "";
final Integer deprecated = 0;
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
cnx = source.getConnection();
//find similar
final Integer similar = findSimilar(cnx, FIND_ELLIPSOID, semi_major_axis,uom_code,inv_flattening,semi_minor_axis,ellipsoid_shape);
if(similar != null){ return similar; }
cnx.setReadOnly(false);
ellipsoid_code = getNextCode();
stmt = cnx.prepareStatement(CREATE_UNIT_OF_MEASURE.query());
CREATE_UNIT_OF_MEASURE.fillStatement(stmt,
ellipsoid_code,
ellipsoid_name,
semi_major_axis,
uom_code,
inv_flattening,
semi_minor_axis,
ellipsoid_shape,
remarks,
information_source,
data_source,
revision_date,
change_id,
deprecated
);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
return ellipsoid_code;
}
@Override
public int getOrCreatePrimeMeridian(final PrimeMeridian candidate) throws FactoryException{
final String code = searchSimilar(PrimeMeridian.class, candidate);
if(code != null){
return codeToID(code);
}
final Integer prime_meridian_code;
final String prime_meridian_name = candidate.getName().getCode();
final Double greenwich_longitude = candidate.getGreenwichLongitude();
final Integer uom_code = getOrCreateUOM(candidate.getAngularUnit());
final String remarks = (candidate.getRemarks()==null)? "" : candidate.getRemarks().toString();
final String information_source = (candidate.getName().getCodeSpace()==null)? null : candidate.getName().getCodeSpace();
final String data_source = (candidate.getName().getCodeSpace()==null)? "" : candidate.getName().getCodeSpace();
final Date revision_date = new Date(System.currentTimeMillis());
final String change_id = "";
final Integer deprecated = 0;
//save object
Connection cnx = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
cnx = source.getConnection();
//find similar
final Integer similar = findSimilar(cnx, FIND_PRIME_MERIDIAN, prime_meridian_name,greenwich_longitude,uom_code);
if(similar != null){ return similar; }
cnx.setReadOnly(false);
prime_meridian_code = getNextCode();
stmt = cnx.prepareStatement(CREATE_PRIME_MERIDIAN.query());
CREATE_PRIME_MERIDIAN.fillStatement(stmt,
prime_meridian_code,
prime_meridian_name,
greenwich_longitude,
uom_code,
remarks,
information_source,
data_source,
revision_date,
change_id,
deprecated
);
stmt.executeUpdate();
}catch(SQLException ex){
throw new FactoryException(ex);
}finally{
store.closeSafe(cnx, stmt, rs);
}
return prime_meridian_code;
}
private int codeToID(String code){
return Integer.valueOf(code.split(":")[1]);
}
private String getCoordinateSystemType(CoordinateSystem candidate) throws FactoryException{
if(candidate instanceof CartesianCS){
return "Cartesian";
}else if(candidate instanceof EllipsoidalCS){
return "ellipsoidal";
}else if(candidate instanceof TimeCS){
return "temporal";
}else if(candidate instanceof VerticalCS){
return "vertical";
}else{
return "abstract";
}
}
/**
* Search for a similar record in the database.
*/
private Integer findSimilar(final Connection cnx, final PGEPSGQueries query, final Object ... parameters) throws SQLException{
Integer similar = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try{
stmt = query.createStatement(cnx, parameters);
rs = stmt.executeQuery();
if(rs.next()){
similar = rs.getInt(1);
}
}finally{
store.closeSafe(null, stmt, rs);
}
return similar;
}
/**
* Find a similar Coordinate sysmtem, will check axis
*/
private Integer findSimilarCoordinateSystem(final CoordinateSystem candidate,
final Connection cnx) throws SQLException, FactoryException{
Integer similar = null;
final String coord_sys_name = candidate.getName().getCode();
final String coord_sys_type = getCoordinateSystemType(candidate);
final Integer dimension = candidate.getDimension();
final int nbDim = candidate.getDimension();
PreparedStatement stmt = null;
ResultSet rs = null;
try{
stmt = FIND_COORDINATE_SYSTEM.createStatement(cnx, coord_sys_name,coord_sys_type,dimension);
rs = stmt.executeQuery();
search:
while(rs.next()){
//check each candidate axis
boolean match = true;
for(int i=0;i<nbDim;i++){
final CoordinateSystemAxis axis = candidate.getAxis(i);
final String expectedOrientation = axis.getDirection().name();
final String expectedAbbreviation = axis.getAbbreviation();
final int expectedUomCode = getOrCreateUOM(axis.getUnit());
final int coord_sys_code = rs.getInt(1);
final String coord_axis_orientation = rs.getString(2);
final String coord_axis_abbreviation = rs.getString(3);
final int uomCode = rs.getInt(4);
if(!(expectedOrientation.equalsIgnoreCase(coord_axis_orientation) &&
expectedAbbreviation.equalsIgnoreCase(coord_axis_abbreviation) &&
expectedUomCode == uomCode)){
match = false;
}
if(i==nbDim-1 && match){
//last axis, and all axis match
similar = coord_sys_code;
break search;
}
if(!rs.next()){ break; }
}
}
}finally{
store.closeSafe(null, stmt, rs);
}
return similar;
}
}