package org.geotoolkit.filter.visitor; import com.vividsolutions.jts.geom.Geometry; import org.apache.sis.feature.FeatureExt; import org.geotoolkit.filter.DefaultLiteral; import org.geotoolkit.filter.binaryspatial.LooseBBox; import org.geotoolkit.filter.binaryspatial.UnreprojectedLooseBBox; import org.geotoolkit.geometry.DefaultBoundingBox; import org.geotoolkit.geometry.jts.JTS; import org.apache.sis.referencing.CRS; import org.opengis.feature.AttributeType; import org.opengis.feature.FeatureType; import org.opengis.feature.PropertyNotFoundException; import org.opengis.feature.PropertyType; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Literal; import org.opengis.filter.expression.PropertyName; import org.opengis.filter.spatial.BBOX; import org.opengis.geometry.BoundingBox; import org.opengis.geometry.Envelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import org.apache.sis.geometry.Envelopes; import org.apache.sis.util.Utilities; /** * @author Johann Sorel (Geomatys) */ public class CRSAdaptorVisitor extends DuplicatingFilterVisitor { private final FeatureType dataType; public CRSAdaptorVisitor(FeatureType type){ super(); this.dataType = type; } @Override public Object visit(BBOX filter, final Object extraData) { final Expression exp1 = visit(filter.getExpression1(),extraData); final Expression exp2 = filter.getExpression2(); if(!(exp2 instanceof Literal)){ //this value is supposed to hold a BoundingBox throw new IllegalArgumentException("Illegal BBOX filter, " + "second expression should have been a literal with a boundingBox value: \n" + filter); }else{ CoordinateReferenceSystem targetCrs = null; if(exp1 instanceof PropertyName){ final PropertyName pn = (PropertyName)exp1; try{ final PropertyType desc = dataType.getProperty(pn.getPropertyName()); if(desc instanceof AttributeType){ targetCrs = FeatureExt.getCRS(desc); } }catch(PropertyNotFoundException ex){/* not important*/} } Literal l = (Literal)visit(exp2,extraData); if(targetCrs!=null){ Object lo = l.getValue(); try{ out: if(lo instanceof Geometry){ Geometry geom = (Geometry)lo; final CoordinateReferenceSystem sourceCRS = JTS.findCoordinateReferenceSystem(geom); if (Utilities.equalsIgnoreMetadata(sourceCRS, targetCrs)) break out; final MathTransform trs = CRS.findOperation(sourceCRS, targetCrs, null).getMathTransform(); geom = JTS.transform(geom, trs); l = ff.literal(geom); }else if(lo instanceof Envelope){ Envelope env = Envelopes.transform((Envelope) lo, targetCrs); l = ff.literal(new DefaultBoundingBox(env)); } }catch (Exception ex){ throw new IllegalArgumentException(ex.getMessage(),ex); } } final Object obj = l.getValue(); if(obj instanceof BoundingBox){ if (filter instanceof UnreprojectedLooseBBox) { return new UnreprojectedLooseBBox((PropertyName)exp1, new DefaultLiteral<BoundingBox>((BoundingBox) obj)); } else if (filter instanceof LooseBBox) { return new LooseBBox((PropertyName)exp1, new DefaultLiteral<BoundingBox>((BoundingBox) obj)); } else { return getFactory(extraData).bbox(exp1, (BoundingBox) obj); } }else{ throw new IllegalArgumentException("Illegal BBOX filter, " + "second expression should have been a literal with a boundingBox value but value was a : \n" + obj.getClass()); } } } }