/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2011-2013, 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.db.mysql;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import java.lang.reflect.Array;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import net.iharder.Base64;
import org.apache.sis.feature.FeatureExt;
import org.apache.sis.internal.feature.AttributeConvention;
import org.apache.sis.util.Version;
import org.geotoolkit.db.FilterToSQL;
import org.geotoolkit.db.JDBCFeatureStore;
import org.geotoolkit.db.reverse.ColumnMetaModel;
import org.geotoolkit.db.reverse.PrimaryKey;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.util.NamesExt;
import org.geotoolkit.filter.DefaultPropertyIsLike;
import org.apache.sis.util.ObjectConverters;
import org.opengis.util.GenericName;
import org.opengis.filter.And;
import org.opengis.filter.ExcludeFilter;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import org.opengis.filter.Id;
import org.opengis.filter.IncludeFilter;
import org.opengis.filter.Not;
import org.opengis.filter.Or;
import org.opengis.filter.PropertyIsBetween;
import org.opengis.filter.PropertyIsEqualTo;
import org.opengis.filter.PropertyIsGreaterThan;
import org.opengis.filter.PropertyIsGreaterThanOrEqualTo;
import org.opengis.filter.PropertyIsLessThan;
import org.opengis.filter.PropertyIsLessThanOrEqualTo;
import org.opengis.filter.PropertyIsLike;
import org.opengis.filter.PropertyIsNil;
import org.opengis.filter.PropertyIsNotEqualTo;
import org.opengis.filter.PropertyIsNull;
import org.opengis.filter.expression.Add;
import org.opengis.filter.expression.Divide;
import org.opengis.filter.expression.Expression;
import org.opengis.filter.expression.Function;
import org.opengis.filter.expression.Literal;
import org.opengis.filter.expression.Multiply;
import org.opengis.filter.expression.NilExpression;
import org.opengis.filter.expression.PropertyName;
import org.opengis.filter.expression.Subtract;
import org.opengis.filter.identity.Identifier;
import org.opengis.filter.spatial.BBOX;
import org.opengis.filter.spatial.Beyond;
import org.opengis.filter.spatial.BinarySpatialOperator;
import org.opengis.filter.spatial.Contains;
import org.opengis.filter.spatial.Crosses;
import org.opengis.filter.spatial.DWithin;
import org.opengis.filter.spatial.Disjoint;
import org.opengis.filter.spatial.Equals;
import org.opengis.filter.spatial.Intersects;
import org.opengis.filter.spatial.Overlaps;
import org.opengis.filter.spatial.Touches;
import org.opengis.filter.spatial.Within;
import org.opengis.filter.temporal.After;
import org.opengis.filter.temporal.AnyInteracts;
import org.opengis.filter.temporal.Before;
import org.opengis.filter.temporal.Begins;
import org.opengis.filter.temporal.BegunBy;
import org.opengis.filter.temporal.During;
import org.opengis.filter.temporal.EndedBy;
import org.opengis.filter.temporal.Ends;
import org.opengis.filter.temporal.Meets;
import org.opengis.filter.temporal.MetBy;
import org.opengis.filter.temporal.OverlappedBy;
import org.opengis.filter.temporal.TContains;
import org.opengis.filter.temporal.TEquals;
import org.opengis.filter.temporal.TOverlaps;
import org.opengis.geometry.Envelope;
import org.apache.sis.util.UnconvertibleObjectException;
import org.apache.sis.util.logging.Logging;
import org.geotoolkit.db.DefaultJDBCFeatureStore;
import org.opengis.feature.AttributeType;
import org.opengis.feature.FeatureType;
/**
*
* @author Johann Sorel (Geomatys)
*/
public class MySQLFilterToSQL implements FilterToSQL {
private final MySQLDialect dialect;
private final Version msVersion;
private final FeatureType featureType;
private final PrimaryKey pkey;
private Integer currentsrid;
public MySQLFilterToSQL(MySQLDialect dialect,FeatureType featureType, PrimaryKey pkey, Version msVersion) {
this.dialect = dialect;
this.featureType = featureType;
this.pkey = pkey;
this.msVersion = msVersion;
}
////////////////////////////////////////////////////////////////////////////
// EXPRESSION EXPRESSION ///////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
@Override
public StringBuilder visit(NilExpression candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
if(true) throw new UnsupportedOperationException("Not supported yet.");
return sb;
}
@Override
public StringBuilder visit(Add candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append('(');
candidate.getExpression1().accept(this, o);
sb.append(" + ");
candidate.getExpression2().accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Divide candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append('(');
candidate.getExpression1().accept(this, o);
sb.append(" / ");
candidate.getExpression2().accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Function candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
if(true) throw new UnsupportedOperationException("Not supported.");
return sb;
}
@Override
public StringBuilder visit(Literal candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final Object value = candidate.getValue();
writeValue(sb, value, currentsrid);
return sb;
}
public void writeValue(final StringBuilder sb, Object candidate, int srid){
if(candidate instanceof Date){
//convert it to a timestamp, string representation won't be ambiguious like dates toString()
candidate = new Timestamp(((Date)candidate).getTime());
}
if(candidate == null){
sb.append("NULL");
}else if(candidate instanceof Boolean){
sb.append(String.valueOf(candidate));
}else if(candidate instanceof Double){
if(((Double)candidate).isNaN()){
sb.append("'NaN'");
}else{
sb.append(String.valueOf(candidate));
}
}else if(candidate instanceof Float){
if(((Float)candidate).isNaN()){
sb.append("'NaN'");
}else{
sb.append(String.valueOf(candidate));
}
}else if(candidate instanceof Number){
sb.append(String.valueOf(candidate));
}else if(candidate instanceof byte[]){
//special case for byte array
sb.append("decode('");
sb.append(Base64.encodeBytes((byte[])candidate));
sb.append("','base64')");
}else if(candidate instanceof Geometry){
// evaluate the literal and store it for later
Geometry geom = (Geometry)candidate;
if(geom instanceof LinearRing){
//postgis does not handle linear rings, convert to just a line string
geom = geom.getFactory().createLineString(((LinearRing) geom).getCoordinateSequence());
}
sb.append("st_geomfromtext('");
sb.append(geom.toText());
if(srid>0){
sb.append("',").append(srid).append(')');
}else{
sb.append("')");
}
}else if(candidate.getClass().isArray()){
final int size = Array.getLength(candidate);
sb.append("'{");
for(int i=0;i<size;i++){
if(i>0){
sb.append(',');
}
final Object o = Array.get(candidate, i);
if(o != null && o.getClass().isArray()){
final StringBuilder suba = new StringBuilder();
writeValue(suba,o,-1);
if(suba.charAt(0)=='\''){
sb.append(suba.substring(1, suba.length()-1));
}else{
sb.append(suba.toString());
}
}else if(!(o instanceof Number || o instanceof Boolean) && o != null){
// we don't know what this is, let's convert back to a string
String encoding = null;
try {
encoding = ObjectConverters.convert(o, String.class);
} catch (UnconvertibleObjectException e) {
Logging.recoverableException(null, MySQLFilterToSQL.class, "writeValue", e);
// TODO - do we really want to ignore?
}
if (encoding == null) {
// could not convert back to string, use original value
encoding = o.toString();
}
// single quotes must be escaped to have a valid sql string
final String escaped = encoding.replaceAll("'", "''");
sb.append(escaped);
}else{
writeValue(sb,o,-1);
}
}
sb.append("}'");
}else{
// we don't know what this is, let's convert back to a string
String encoded = null;
try {
encoded = ObjectConverters.convert(candidate, String.class);
} catch (UnconvertibleObjectException e) {
Logging.recoverableException(null, MySQLFilterToSQL.class, "writeValue", e);
// TODO - do we really want to ignore?
}
if (encoded == null) {
// could not convert back to string, use original value
encoded = candidate.toString();
}
// single quotes must be escaped to have a valid sql string
final String escaped = encoded.replaceAll("'", "''");
sb.append('\'');
sb.append(escaped);
sb.append('\'');
}
}
@Override
public StringBuilder visit(Multiply candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append('(');
candidate.getExpression1().accept(this, o);
sb.append(" * ");
candidate.getExpression2().accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(PropertyName candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final GenericName name = NamesExt.valueOf(candidate.getPropertyName());
sb.append('"');
sb.append(name.tip().toString());
sb.append('"');
return sb;
}
@Override
public StringBuilder visit(Subtract candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append('(');
candidate.getExpression1().accept(this, o);
sb.append(" - ");
candidate.getExpression2().accept(this, o);
sb.append(')');
return sb;
}
////////////////////////////////////////////////////////////////////////////
// FILTER EXPRESSION ///////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
@Override
public StringBuilder visitNullFilter(Object o) {
final StringBuilder sb = toStringBuilder(o);
if(true) throw new UnsupportedOperationException("Not supported.");
return sb;
}
@Override
public StringBuilder visit(ExcludeFilter candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append("1=0");
return sb;
}
@Override
public StringBuilder visit(IncludeFilter candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append("1=1");
return sb;
}
@Override
public StringBuilder visit(And candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final List<Filter> subs = candidate.getChildren();
sb.append('(');
for(int i=0,n=subs.size();i<n;i++){
if(i>0){
sb.append(" AND ");
}
subs.get(i).accept(this, o);
}
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Id candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append('(');
final FilterFactory ff = FactoryFinder.getFilterFactory(null);
final List<ColumnMetaModel> columns = pkey.getColumns();
//we must split this in a serie of OR
final Identifier[] ids = candidate.getIdentifiers().toArray(new Identifier[0]);
final List<Filter> idFilters = new ArrayList<Filter>(ids.length);
final List<Filter> idPartFilters = new ArrayList<Filter>();
for(int i=0;i<ids.length;i++){
idPartFilters.clear();
final Object[] idValues = pkey.decodeFID(ids[i].toString());
for(int k=0;k<idValues.length;k++){
idPartFilters.add(ff.equals(ff.property(columns.get(k).getName()), ff.literal(idValues[k])));
}
final Filter and = ff.and(idPartFilters);
idFilters.add(and);
}
Filter filter = ff.or(idFilters);
filter.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Not candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
sb.append("NOT(");
candidate.getFilter().accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Or candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final List<Filter> subs = candidate.getChildren();
sb.append('(');
for(int i=0,n=subs.size();i<n;i++){
if(i>0){
sb.append(" OR ");
}
subs.get(i).accept(this, o);
}
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(PropertyIsBetween candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final Expression exp = candidate.getExpression();
final Expression lower = candidate.getLowerBoundary();
final Expression upper = candidate.getUpperBoundary();
exp.accept(this, o);
sb.append(" BETWEEN ");
lower.accept(this, o);
sb.append(" AND ");
upper.accept(this, o);
return sb;
}
@Override
public StringBuilder visit(PropertyIsEqualTo candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression1().accept(this, o);
sb.append(" = ");
candidate.getExpression2().accept(this, o);
return sb;
}
@Override
public StringBuilder visit(PropertyIsNotEqualTo candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression1().accept(this, o);
sb.append(" <> ");
candidate.getExpression2().accept(this, o);
return sb;
}
@Override
public StringBuilder visit(PropertyIsGreaterThan candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression1().accept(this, o);
sb.append(" > ");
candidate.getExpression2().accept(this, o);
return sb;
}
@Override
public StringBuilder visit(PropertyIsGreaterThanOrEqualTo candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression1().accept(this, o);
sb.append(" >= ");
candidate.getExpression2().accept(this, o);
return sb;
}
@Override
public StringBuilder visit(PropertyIsLessThan candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression1().accept(this, o);
sb.append(" < ");
candidate.getExpression2().accept(this, o);
return sb;
}
@Override
public StringBuilder visit(PropertyIsLessThanOrEqualTo candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression1().accept(this, o);
sb.append(" <= ");
candidate.getExpression2().accept(this, o);
return sb;
}
@Override
public StringBuilder visit(PropertyIsLike candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final char escape = candidate.getEscape().charAt(0);
final char wildCard = candidate.getWildCard().charAt(0);
final char single = candidate.getSingleChar().charAt(0);
final boolean matchingCase = candidate.isMatchingCase();
final Expression expression = candidate.getExpression();
final String literal = candidate.getLiteral();
String pattern = DefaultPropertyIsLike.convertToSQL92(escape, wildCard, single, literal);
if(!matchingCase){
pattern = pattern.toUpperCase();
sb.append(" UPPER(");
}
//we don't know the type, make a type cast to be on the safe side
sb.append(" CAST( ");
expression.accept(this, sb);
sb.append(" AS VARCHAR)");
if(!matchingCase){
sb.append(")");
}
sb.append(" LIKE '");
sb.append(pattern);
sb.append("' ");
return sb;
}
@Override
public StringBuilder visit(PropertyIsNull candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression().accept(this, o);
sb.append(" IS NULL");
return sb;
}
@Override
public StringBuilder visit(PropertyIsNil candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
candidate.getExpression().accept(this, o);
sb.append(" IS NULL");
return sb;
}
@Override
public StringBuilder visit(BBOX candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
sb.append("st_intersects(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Beyond candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
if(prepared.swap){
sb.append("st_dwithin(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(',');
sb.append(candidate.getDistance());
sb.append(')');
}else{
sb.append("st_distance(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(") > ");
sb.append(candidate.getDistance());
}
return sb;
}
@Override
public StringBuilder visit(Contains candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
if(prepared.swap){
sb.append("st_within(");
}else{
sb.append("st_contains(");
}
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Crosses candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
sb.append("st_crosses(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Disjoint candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
sb.append("not(st_intersects(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append("))");
return sb;
}
@Override
public StringBuilder visit(DWithin candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
if(prepared.swap){
sb.append("st_distance(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(',');
sb.append(candidate.getDistance());
sb.append(')');
}else{
sb.append("st_dwithin(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(") > ");
sb.append(candidate.getDistance());
}
return sb;
}
@Override
public StringBuilder visit(Equals candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
sb.append("st_equals(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Intersects candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
sb.append("st_intersects(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Overlaps candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
sb.append("st_overlaps(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Touches candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
sb.append("st_touches(");
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
@Override
public StringBuilder visit(Within candidate, Object o) {
final StringBuilder sb = toStringBuilder(o);
final PreparedSpatialFilter prepared = new PreparedSpatialFilter(candidate);
if(prepared.swap){
sb.append("st_contains(");
}else{
sb.append("st_within(");
}
prepared.property.accept(this, o);
sb.append(',');
prepared.geometry.accept(this, o);
sb.append(')');
return sb;
}
////////////////////////////////////////////////////////////////////////////
// TEMPORAL filters are not supported //////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
@Override
public StringBuilder visit(After candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(AnyInteracts candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(Before candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(Begins candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(BegunBy candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(During candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(EndedBy candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(Ends candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(Meets candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(MetBy candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(OverlappedBy candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(TContains candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(TEquals candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
@Override
public StringBuilder visit(TOverlaps candidate, Object o) {
throw new UnsupportedOperationException("Temporal filters not supported.");
}
////////////////////////////////////////////////////////////////////////////
// UTILITY METHODS /////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
private static StringBuilder toStringBuilder(Object candidate){
if(candidate instanceof StringBuilder){
return (StringBuilder) candidate;
}else{
throw new RuntimeException("Expected a StringBuilder argument");
}
}
/**
* Ensure the given double is not an infinite, doesn't work well with SQL and postgres.
* @param candidate
* @return double unchanged if not an infinite.
*/
private static double checkInfinites(final double candidate){
if(candidate == Double.NEGATIVE_INFINITY){
return Double.MIN_VALUE;
}else if(candidate == Double.POSITIVE_INFINITY){
return Double.MAX_VALUE;
}else{
return candidate;
}
}
/**
* prepare a spatial filter, isolate the field and geometry parts.
* Enventually converting it in a geometry.
*/
private class PreparedSpatialFilter{
public PropertyName property;
public Literal geometry;
public boolean swap;
public PreparedSpatialFilter(final BinarySpatialOperator filter){
final Expression exp1 = filter.getExpression1();
final Expression exp2 = filter.getExpression2();
if(exp1 instanceof PropertyName){
swap = false;
property = (PropertyName)exp1;
geometry = (Literal)exp2;
}else{
swap = true;
property = (PropertyName)exp2;
geometry = (Literal)exp1;
}
//change Envelope in polygon
final Object obj = geometry.getValue();
if (obj instanceof Envelope) {
final Envelope env = (Envelope) obj;
final FilterFactory ff = FactoryFinder.getFilterFactory(null);
final GeometryFactory gf = new GeometryFactory();
final Coordinate[] coords = new Coordinate[5];
double minx = checkInfinites(env.getMinimum(0));
double maxx = checkInfinites(env.getMaximum(0));
double miny = checkInfinites(env.getMinimum(1));
double maxy = checkInfinites(env.getMaximum(1));
coords[0] = new Coordinate(minx,miny);
coords[1] = new Coordinate(minx,maxy);
coords[2] = new Coordinate(maxx,maxy);
coords[3] = new Coordinate(maxx,miny);
coords[4] = new Coordinate(minx,miny);
final LinearRing ring = gf.createLinearRing(coords);
final Geometry geom = gf.createPolygon(ring, new LinearRing[0]);
geometry = ff.literal(geom);
}
//set the current srid, extract it from feature type
//requiered when encoding geometry
currentsrid = -1;
if (featureType != null) {
final AttributeType descriptor = (AttributeType) property.evaluate(featureType);
if (AttributeConvention.isGeometryAttribute(descriptor)) {
currentsrid = (Integer)FeatureExt.getCharacteristicValue(descriptor,DefaultJDBCFeatureStore.JDBC_PROPERTY_SRID.getName().toString(),null);
}
}
}
}
}