package org.geotools.jdbc; import java.io.IOException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.factory.CommonFactoryFinder; import org.geotools.filter.function.FilterFunction_strConcat; import org.geotools.filter.function.FilterFunction_strEndsWith; import org.geotools.filter.function.FilterFunction_strEqualsIgnoreCase; import org.geotools.filter.function.FilterFunction_strIndexOf; import org.geotools.filter.function.FilterFunction_strLength; import org.geotools.filter.function.FilterFunction_strStartsWith; import org.geotools.filter.function.FilterFunction_strSubstring; import org.geotools.filter.function.FilterFunction_strSubstringStart; import org.geotools.filter.function.FilterFunction_strToLowerCase; import org.geotools.filter.function.FilterFunction_strToUpperCase; import org.geotools.filter.function.FilterFunction_strTrim; import org.geotools.filter.function.math.FilterFunction_abs; import org.geotools.filter.function.math.FilterFunction_abs_2; import org.geotools.filter.function.math.FilterFunction_abs_3; import org.geotools.filter.function.math.FilterFunction_abs_4; import org.geotools.filter.function.math.FilterFunction_ceil; import org.geotools.util.logging.Logging; import org.opengis.feature.simple.SimpleFeature; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Function; /** * Base class for native function encoding tests * * @author Andrea Aime - GeoSolutions */ public abstract class JDBCFunctionTest extends JDBCTestSupport { static final Logger LOGGER = Logging.getLogger(JDBCFunctionTest.class); FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); SimpleFeatureSource fs; @Override protected void connect() throws Exception { super.connect(); fs = dataStore.getFeatureSource(tname("ft1")); } public void testStrfunc() throws IOException { if (skipTests(FilterFunction_strConcat.class)) { return; } Function func = ff.function("strConcat", ff.property(aname("stringProperty")), ff.literal("abc")); Filter filter = ff.equals(func, ff.literal("zeroabc")); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrfuncNumbers() throws IOException { if (skipTests(FilterFunction_strConcat.class)) { return; } Function func = ff.function("strConcat", ff.property(aname("intProperty")), ff.property(aname("intProperty"))); Filter filter = ff.equals(func, ff.literal("11")); assertFeatures(fs, filter, tname("ft1") + ".1"); } public void testStrEndsWith() throws IOException { if (skipTests(FilterFunction_strEndsWith.class)) { return; } Function func = ff.function("strEndsWith", ff.property(aname("stringProperty")), ff.literal("o")); Filter filter = ff.equals(func, ff.literal(true)); assertFeatures(fs, filter, tname("ft1") + ".0", tname("ft1") + ".2"); } public void testStrEndsWithOtherProperty() throws IOException { if (skipTests(FilterFunction_strEndsWith.class)) { return; } Function func = ff.function("strEndsWith", ff.property(aname("doubleProperty")), ff.property(aname("intProperty"))); Filter filter = ff.equals(func, ff.literal(true)); assertFeatures(fs, filter, tname("ft1") + ".0", tname("ft1") + ".1", tname("ft1") + ".2"); } public void testStrStartsWith() throws IOException { if (skipTests(FilterFunction_strStartsWith.class)) { return; } Function func = ff.function("strStartsWith", ff.property(aname("stringProperty")), ff.literal("ze")); Filter filter = ff.equals(func, ff.literal(true)); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrStartsWithOtherProperty() throws IOException { if (skipTests(FilterFunction_strStartsWith.class)) { return; } Function func = ff.function("strStartsWith", ff.property(aname("doubleProperty")), ff.property(aname("intProperty"))); Filter filter = ff.equals(func, ff.literal(true)); assertFeatures(fs, filter, tname("ft1") + ".0", tname("ft1") + ".1", tname("ft1") + ".2"); } public void testStrIndexOf() throws IOException { if (skipTests(FilterFunction_strIndexOf.class)) { return; } Function func = ff.function("strIndexOf", ff.property(aname("stringProperty")), ff.literal("er")); Filter filter = ff.equals(func, ff.literal(1)); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrLength() throws IOException { if (skipTests(FilterFunction_strLength.class)) { return; } Function func = ff.function("strLength", ff.property(aname("stringProperty"))); Filter filter = ff.equals(func, ff.literal(4)); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrLower() throws IOException { if (skipTests(FilterFunction_strToLowerCase.class)) { return; } Function func = ff.function("strToLowerCase", ff.property(aname("intProperty"))); Filter filter = ff.equals(func, ff.literal("0")); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrUpper() throws IOException { if (skipTests(FilterFunction_strToUpperCase.class)) { return; } Function func = ff.function("strToUpperCase", ff.property(aname("stringProperty"))); Filter filter = ff.equals(func, ff.literal("ZERO")); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrEqualsIgnoreCase() throws IOException { if (skipTests(FilterFunction_strEqualsIgnoreCase.class)) { return; } Function func = ff.function("strEqualsIgnoreCase", ff.property(aname("stringProperty")), ff.literal("ZeRo")); Filter filter = ff.equals(func, ff.literal(true)); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrSubstring() throws IOException { if (skipTests(FilterFunction_strSubstring.class)) { return; } // intentionally mixing string and int literals Function func = ff.function("strSubstring", ff.property(aname("stringProperty")), ff.literal("1"), ff.literal(3)); Filter filter = ff.equals(func, ff.literal("er")); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrSubstringStart() throws IOException { if (skipTests(FilterFunction_strSubstringStart.class)) { return; } // intentionally mixing string and int literals Function func = ff.function("strSubstringStart", ff.property(aname("stringProperty")), ff.literal("1")); Filter filter = ff.equals(func, ff.literal("ero")); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testStrTrim() throws IOException { if (skipTests(FilterFunction_strTrim.class) || skipTests(FilterFunction_strConcat.class)) { return; } // intentionally mixing string and int literals Function func1 = ff.function("strConcat", ff.property(aname("stringProperty")), ff.literal(" ")); Function func2 = ff.function("strTrim", func1); Filter filter = ff.equals(func2, ff.literal("zero")); assertFeatures(fs, filter, tname("ft1") + ".0"); } public void testAbs() throws IOException { if (skipTests(FilterFunction_abs.class)) { return; } // intentionally forcing a integer abs (makes no sense, but it's there...) Expression mul = ff.multiply(ff.property(aname("doubleProperty")), ff.literal(-1)); Function func2 = ff.function("abs", mul); Filter filter = ff.equals(func2, ff.literal("1")); assertFeatures(fs, filter, tname("ft1") + ".1"); } public void testAbs2() throws IOException { if (skipTests(FilterFunction_abs_2.class)) { return; } // intentionally forcing a integer abs (makes no sense, but it's there...) Expression mul = ff.multiply(ff.property(aname("doubleProperty")), ff.literal(-1)); Function func2 = ff.function("abs_2", mul); Filter filter = ff.equals(func2, ff.literal("1")); assertFeatures(fs, filter, tname("ft1") + ".1"); } public void testAbs3() throws IOException { if (skipTests(FilterFunction_abs_3.class)) { return; } // intentionally forcing a integer abs (makes no sense, but it's there...) Expression mul = ff.multiply(ff.property(aname("doubleProperty")), ff.literal(-1)); Function func2 = ff.function("abs_3", mul); Filter filter = ff.greaterOrEqual(func2, ff.literal(1)); assertFeatures(fs, filter, tname("ft1") + ".1", tname("ft1") + ".2"); } public void testAbs4() throws IOException { if (skipTests(FilterFunction_abs_4.class)) { return; } // intentionally forcing a integer abs (makes no sense, but it's there...) Expression mul = ff.multiply(ff.property(aname("doubleProperty")), ff.literal(-1)); Function func2 = ff.function("abs_4", mul); Filter filter = ff.greaterOrEqual(func2, ff.literal(1)); assertFeatures(fs, filter, tname("ft1") + ".1", tname("ft1") + ".2"); } public void testCeil() throws IOException { if (skipTests(FilterFunction_ceil.class)) { return; } Function func = ff.function("ceil", ff.property(aname("doubleProperty"))); Filter filter = ff.equals(func, ff.literal(2)); assertFeatures(fs, filter, tname("ft1") + ".1"); } public void testFloor() throws IOException { if (skipTests(FilterFunction_ceil.class)) { return; } Function func = ff.function("floor", ff.property(aname("doubleProperty"))); Filter filter = ff.equals(func, ff.literal(1)); assertFeatures(fs, filter, tname("ft1") + ".1"); } void assertFeatures(SimpleFeatureSource fs2, Filter filter, String... ids) throws IOException { SimpleFeatureIterator fi = null; Set<String> idSet = new HashSet<String>(Arrays.asList(ids)); int count = 0; try { fi = fs.getFeatures(filter).features(); while(fi.hasNext()) { SimpleFeature sf = fi.next(); assertTrue("Found unexpected id " + sf.getID(), idSet.contains(sf.getID())); count++; } } finally { if(fi != null) { fi.close(); } } if(count != idSet.size()) { fail("Expected to find " + idSet.size() + " features, but was " + count); } } protected boolean skipTests(Class<?> fClass) { if (!dataStore.getFilterCapabilities().supports(fClass)) { LOGGER.log(Level.INFO, "Function {0} is not natively supported, skipping test", fClass .getSimpleName()); return true; } return false; } }