/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-2008, Open Source Geospatial Foundation (OSGeo)
*
* 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.geotools.caching.util;
import java.util.ArrayList;
import java.util.List;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.feature.simple.SimpleFeatureTypeBuilder;
import org.geotools.filter.FilterFactoryImpl;
import org.geotools.referencing.crs.DefaultEngineeringCRS;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Polygon;
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
public class FilterSplitterTest extends TestCase {
protected FilterFactory ff;
protected Filter bb;
protected Filter bb2;
protected Filter att;
protected Filter bso;
protected Envelope bbenv;
protected Envelope bb2env;
protected Envelope bsoenv;
protected void setUp() {
ff = new FilterFactoryImpl();
bb = ff.bbox("geom", 0, 10, 1000, 1100, "srs");
bbenv = new Envelope(0, 1000, 10, 1100);
bb2 = ff.bbox("geom", 500, 510, 1500, 1600, "srs");
bb2env = new Envelope(500, 1500, 510, 1600);
att = ff.like(ff.property("dummydata"), "Id: 1*");
Polygon p = createPolygon();
bso = ((FilterFactoryImpl) ff).intersects(ff.property("the_geom"), ff.literal(p));
bsoenv = p.getEnvelopeInternal();
}
protected static Polygon createPolygon() {
Coordinate[] coords = new Coordinate[] {
new Coordinate(200, 210), new Coordinate(200, 500), new Coordinate(2000, 2100),
new Coordinate(500, 510), new Coordinate(200, 210)
};
CoordinateArraySequence seq = new CoordinateArraySequence(coords);
LinearRing ls = new LinearRing(seq, new GeometryFactory());
Polygon ret = new Polygon(ls, null, new GeometryFactory());
return ret;
}
public static Test suite() {
return new TestSuite(FilterSplitterTest.class);
}
public void testBBoxFilter() {
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
bb.accept(splitter, null);
assertEquals(bbenv, splitter.getEnvelope());
Filter result = splitter.getFilterPre();
assertEquals(bb, result);
}
public void testAndFilter() {
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
Filter and = ff.and(bb, att);
and.accept(splitter, null);
assertEquals(bbenv, splitter.getEnvelope());
assertEquals(bb, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
and = ff.and(bb, bb2);
splitter = new BBoxFilterSplitter();
and.accept(splitter, null);
Envelope i = new Envelope(bbenv);
i.expandToInclude(bb2env);
Envelope s = splitter.getEnvelope();
assertEquals(i, s);
assertEquals(and, splitter.getFilterPost());
}
public void testOrFilter() {
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
//tests or with an geometry and attribute -> should include everything
Filter or = ff.or(bb, att);
or.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(Filter.INCLUDE, splitter.getFilterPre());
assertEquals(or, splitter.getFilterPost());
//tests or with a two geometry filters
or = ff.or(bb, bb2);
splitter = new BBoxFilterSplitter();
or.accept(splitter, null);
bbenv.expandToInclude(bb2env);
assertEquals(bbenv, splitter.getEnvelope());
//assertEquals(or, splitter.getFilterPost());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
}
public void testNotFilter() {
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
Filter not = ff.not(bb);
not.accept(splitter, null);
assertEquals(Filter.INCLUDE, splitter.getFilterPre());
assertEquals(not, splitter.getFilterPost());
//tests: bb2 AND (NOT bb)
Filter and = ff.and(bb2, not);
splitter = new BBoxFilterSplitter();
and.accept(splitter, null);
assertEquals(bb2, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
}
public void testBinarySpatialOperator() {
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
Filter and = ff.and(bb, bso);
and.accept(splitter, null);
Envelope testenv = bbenv;
testenv.expandToInclude(bsoenv);
assertEquals(testenv, splitter.getEnvelope());
assertEquals(and, splitter.getFilterPost());
SimpleFeature sf = createTestFeature();
assertTrue(splitter.getFilterPre().evaluate(sf));
}
public void testAndManyFilters() {
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
List<Filter> filters = new ArrayList<Filter>();
filters.add(bb);
filters.add(bb2);
filters.add(att);
filters.add(bso);
Filter and = ff.and(filters);
and.accept(splitter, null);
Envelope tmp = new Envelope(bbenv);
tmp.expandToInclude(bb2env);
tmp.expandToInclude(bsoenv);
assertEquals(tmp, splitter.getEnvelope());
assertEquals(and, splitter.getFilterPost());
Filter bbox = ff.bbox("geom", 500, 210, 2000, 200, "srs");
Coordinate[] coords = new Coordinate[] {
new Coordinate(205, 455), new Coordinate(205, 500),
new Coordinate(210, 500),
new Coordinate(210, 455), new Coordinate(205, 455)
};
CoordinateArraySequence seq = new CoordinateArraySequence(coords);
LinearRing ls = new LinearRing(seq, new GeometryFactory());
Polygon ret = new Polygon(ls, null, new GeometryFactory());
Filter intersects = ((FilterFactoryImpl) ff).intersects(ff.property("geom"), ff.literal(ret));
and = ff.and(intersects, bbox);
splitter = new BBoxFilterSplitter();
and.accept(splitter, null);
tmp = new Envelope(500, 2000, 200, 210);
tmp.expandToInclude(ret.getEnvelopeInternal());
assertEquals(ff.bbox("geom", tmp.getMinX(), tmp.getMinY(), tmp.getMaxX(), tmp.getMaxY(), "srs"), splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
}
public void testOrManyFilters() {
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
List<Filter> filters = new ArrayList<Filter>();
filters.add(bb);
filters.add(bb2);
filters.add(att);
filters.add(bso);
Filter or = ff.or(filters);
or.accept(splitter, null);
Envelope e = new Envelope(bbenv);
e.expandToInclude(bb2env);
e.expandToInclude(bsoenv);
assertEquals(e, splitter.getEnvelope());
assertEquals(or, splitter.getFilterPost());
}
public void testOrAndAndManyFilters() {
Envelope testenv = new Envelope(bb2env);
testenv.expandToInclude(bbenv);
Filter testfilter = ff.bbox("geom", testenv.getMinX(), testenv.getMinY(), testenv.getMaxX(), testenv.getMaxY(), "srs");
//tests:
//(bbox or bbox) and attribute
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
Filter or = ff.or(bb, bb2);
Filter and = ff.and(or, att);
and.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(testfilter, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
//tests:
//(bbox and bbox) or attribute
splitter = new BBoxFilterSplitter();
and = ff.and(bb, bb2);
or = ff.or(and, att);
or.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(Filter.INCLUDE, splitter.getFilterPre());
assertEquals(or, splitter.getFilterPost());
//tests:
//(bbox or bbox) and bbox
splitter = new BBoxFilterSplitter();
or = ff.or(bb, bb2);
and = ff.and(or, bb);
and.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(testfilter, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
//tests:
//(bbox or attribute) and bbox
splitter = new BBoxFilterSplitter();
or = ff.or(bb, att);
and = ff.and(or, bb);
and.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(bb, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
//tests:
//(bbox and attribute) or bbox2
splitter = new BBoxFilterSplitter();
and = ff.and(bb, att);
or = ff.or(and, bb2);
or.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(testfilter, splitter.getFilterPre());
assertEquals(or, splitter.getFilterPost());
//tests:
//(bbox and attribute) or (bb2 and attribute);
splitter = new BBoxFilterSplitter();
Filter and1 = ff.and(bb, att);
Filter and2 = ff.and(bb2, att);
or = ff.or(and1, and2);
or.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(testfilter, splitter.getFilterPre());
assertEquals(or, splitter.getFilterPost());
//tests:
//(bbox or attribute) and (bb2 or attribute);
splitter = new BBoxFilterSplitter();
Filter or1 = ff.or(bb, att);
Filter or2 = ff.or(bb2, att);
and = ff.and(or1, or2);
and.accept(splitter, null);
assertNotNull(splitter.getEnvelope());
assertEquals(Filter.INCLUDE, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
}
/**
* Tests filters that contain include filters
*/
public void testIncludeFilter(){
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
List<Filter> filters = new ArrayList<Filter>();
Filter includeFilter = Filter.INCLUDE;
includeFilter.accept(splitter, null);
assertEquals(Filter.INCLUDE, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
//test include with another geometry filter using or
splitter = new BBoxFilterSplitter();
filters.add(includeFilter);
filters.add(bb2);
filters.add(bb);
Filter or = ff.or(filters);
or.accept(splitter, null);
assertEquals(Filter.INCLUDE, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
//test include with another geometry filter and attribute filter using or
splitter = new BBoxFilterSplitter();
filters = new ArrayList<Filter>();
filters.add(includeFilter);
filters.add(bb2);
filters.add(bb);
filters.add(att);
or = ff.or(filters);
or.accept(splitter, null);
assertEquals(Filter.INCLUDE, splitter.getFilterPre());
assertEquals(or, splitter.getFilterPost());
//test include with another geometry filter using and
splitter = new BBoxFilterSplitter();
filters = new ArrayList<Filter>();
filters.add(includeFilter);
filters.add(bb);
Filter and = ff.and(filters);
and.accept(splitter, null);
assertEquals(bb, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost()); //if pre incorporates all geometries then we need nothing post
//test include with another geometry filter using and with attribute
splitter = new BBoxFilterSplitter();
filters = new ArrayList<Filter>();
filters.add(includeFilter);
filters.add(bb);
filters.add(att);
and = ff.and(filters);
and.accept(splitter, null);
assertEquals(bb, splitter.getFilterPre());
assertEquals(and, splitter.getFilterPost());
}
/**
* Tests filters that contain exclude filters
*/
public void testExcludeFilter(){
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
List<Filter> filters = new ArrayList<Filter>();
Filter excludeFilter = Filter.EXCLUDE;
excludeFilter.accept(splitter, null);
assertEquals(Filter.EXCLUDE, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
//test include with another geometry filter using or
splitter = new BBoxFilterSplitter();
filters.add(excludeFilter);
filters.add(bb2);
filters.add(bb);
Filter or = ff.or(filters);
or.accept(splitter, null);
Envelope testenv = new Envelope(bb2env);
testenv.expandToInclude(bbenv);
Filter testfilter = ff.bbox("geom", testenv.getMinX(), testenv.getMinY(), testenv.getMaxX(), testenv.getMaxY(), "srs");
assertEquals(testfilter, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
//add exclude filter last
splitter = new BBoxFilterSplitter();
filters = new ArrayList<Filter>();
filters.add(bb);
filters.add(bb2);
filters.add(excludeFilter);
or = ff.or(filters);
or.accept(splitter, null);
assertEquals(testfilter, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
//test include with another geometry filter and attribute filter using or
splitter = new BBoxFilterSplitter();
filters = new ArrayList<Filter>();
filters.add(bb2);
filters.add(excludeFilter);
filters.add(bb);
filters.add(att);
or = ff.or(filters);
or.accept(splitter, null);
assertEquals(testfilter, splitter.getFilterPre());
assertEquals(or, splitter.getFilterPost());
//test include with another geometry filter using and
splitter = new BBoxFilterSplitter();
filters = new ArrayList<Filter>();
filters.add(excludeFilter);
filters.add(bb);
Filter and = ff.and(filters);
and.accept(splitter, null);
assertEquals(Filter.EXCLUDE, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost()); //if pre incorporates all geometries then we need nothing post
//test include with another geometry filter using and with attribute
splitter = new BBoxFilterSplitter();
filters = new ArrayList<Filter>();
filters.add(excludeFilter);
filters.add(bb);
filters.add(att);
and = ff.and(filters);
and.accept(splitter, null);
assertEquals(Filter.EXCLUDE, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
}
/**
* Tests filter that contains bost exclude and include filters
*/
public void testIncludeExcludeFilter(){
List<Filter> filters = new ArrayList<Filter>();
Filter excludeFilter = Filter.EXCLUDE;
Filter includeFilter = Filter.INCLUDE;
filters.add(bb);
filters.add(excludeFilter);
filters.add(bb2);
filters.add(bb);
filters.add(includeFilter);
filters.add(bb);
filters.add(att);
Filter or = ff.or(filters);
BBoxFilterSplitter splitter = new BBoxFilterSplitter();
or.accept(splitter, null);
assertEquals(includeFilter, splitter.getFilterPre());
assertEquals(or, splitter.getFilterPost());
splitter = new BBoxFilterSplitter();
Filter and = ff.and(filters);
and.accept(splitter, null);
assertEquals(excludeFilter, splitter.getFilterPre());
assertEquals(Filter.INCLUDE, splitter.getFilterPost());
}
private SimpleFeature createTestFeature(){
SimpleFeatureTypeBuilder st = new SimpleFeatureTypeBuilder();
st.setName("My Feature Type");
st.add("the_geom", Geometry.class, DefaultEngineeringCRS.CARTESIAN_2D);
SimpleFeatureType type;
try{
type = st.buildFeatureType();
}catch (Exception ex){
ex.printStackTrace();
return null;
}
SimpleFeatureBuilder sb = new SimpleFeatureBuilder(type);
SimpleFeature sf = sb.buildFeature("001");
sf.setDefaultGeometry(createPolygon());
return sf;
}
}