package org.realityforge.jeo.geolatte.jpa;
import java.sql.SQLException;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;
import org.geolatte.geom.ByteBuffer;
import org.geolatte.geom.Geometry;
import org.geolatte.geom.codec.Wkb;
import org.geolatte.geom.codec.Wkt;
import org.geolatte.geom.codec.Wkt.Dialect;
import org.postgis.PGgeometry;
import org.postgresql.util.PGobject;
@Converter
public class PostgisConverter<T extends Geometry>
implements AttributeConverter<T, Object>
{
@Override
@SuppressWarnings( "unchecked" )
public T convertToEntityAttribute( final Object dbData )
{
if ( null == dbData )
{
return null;
}
else if ( dbData instanceof PGgeometry )
{
final org.postgis.Geometry geometry = ( (PGgeometry) dbData ).getGeometry();
return (T) Wkt.newDecoder( Dialect.POSTGIS_EWKT_1 ).decode( geometry.toString() );
}
else if ( dbData instanceof String )
{
/*
In some circumstances the data will come back in WKB format (i.e. When using the Driver directly)
and sometimes it will be returned in WKT format (i.e. In GlassFish when using the DataSource) and
it is unclear what is causing the variance so support both scenarios.
*/
final String wk = (String) dbData;
final char ch = wk.charAt( 0 );
if ( '0' == ch )
{
//Guess that it is in WKB format
return (T) Wkb.newDecoder( Wkb.Dialect.POSTGIS_EWKB_1 ).decode( ByteBuffer.from( wk ) );
}
else
{
//Assume a WKT format
return (T) Wkt.newDecoder( Dialect.POSTGIS_EWKT_1 ).decode( wk );
}
}
else
{
throw new IllegalStateException();
}
}
@Override
public Object convertToDatabaseColumn( final T attribute )
{
if ( null == attribute )
{
final PGobject pgObject = new PGobject();
pgObject.setType( "geometry" );
return pgObject;
}
final String wkt = Wkt.newEncoder( Dialect.POSTGIS_EWKT_1 ).encode( attribute );
try
{
return new PGgeometry( wkt );
}
catch ( final SQLException se )
{
throw new IllegalStateException( "Failed converting geometry", se );
}
}
}