package org.geoserver.wfs; import static org.easymock.EasyMock.createNiceMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import java.util.Arrays; import java.util.List; import org.geoserver.catalog.FeatureTypeInfo; import org.geotools.data.Join; import org.geotools.factory.CommonFactoryFinder; import org.junit.Before; import org.junit.Test; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory2; public class JoinExtractingVisitorTest { private FeatureTypeInfo lakes; private FeatureTypeInfo forests; private FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(); private FeatureTypeInfo buildings; @Before public void setup() { lakes = createNiceMock(FeatureTypeInfo.class); expect(lakes.prefixedName()).andReturn("gs:Lakes").anyTimes(); expect(lakes.getNativeName()).andReturn("Lakes").anyTimes(); expect(lakes.getName()).andReturn("Lakes").anyTimes(); forests = createNiceMock(FeatureTypeInfo.class); expect(forests.prefixedName()).andReturn("gs:Forests").anyTimes(); expect(forests.getNativeName()).andReturn("Forests").anyTimes(); expect(forests.getName()).andReturn("Forests").anyTimes(); buildings = createNiceMock(FeatureTypeInfo.class); expect(buildings.prefixedName()).andReturn("gs:Buildings").anyTimes(); expect(buildings.getNativeName()).andReturn("Buildings").anyTimes(); expect(buildings.getName()).andReturn("Buildings").anyTimes(); replay(lakes, forests, buildings); } @Test public void testTwoWayJoin() { JoinExtractingVisitor visitor = new JoinExtractingVisitor(Arrays.asList(lakes, forests), Arrays.asList("a", "b")); Filter f = ff.equals(ff.property("a/FID"), ff.property("b/FID")); f.accept(visitor, null); assertEquals("a", visitor.getPrimaryAlias()); Filter primary = visitor.getPrimaryFilter(); assertNull(primary); List<Join> joins = visitor.getJoins(); assertEquals(1, joins.size()); Join join = joins.get(0); assertEquals("Forests", join.getTypeName()); assertEquals("b", join.getAlias()); assertEquals(ff.equals(ff.property("a.FID"), ff.property("b.FID")), join.getJoinFilter()); } @Test public void testThreeWayJoinWithAliases() { JoinExtractingVisitor visitor = new JoinExtractingVisitor(Arrays.asList(lakes, forests, buildings), Arrays.asList("a", "b", "c")); Filter f1 = ff.equals(ff.property("a/FID"), ff.property("b/FID")); Filter f2 = ff.equals(ff.property("b/FID"), ff.property("c/FID")); Filter f = ff.and(Arrays.asList(f1, f2)); testThreeWayJoin(visitor, f); } @Test public void testThreeWayJoinNoAliasesUnqualified() { JoinExtractingVisitor visitor = new JoinExtractingVisitor(Arrays.asList(lakes, forests, buildings), null); Filter f1 = ff.equals(ff.property("Lakes/FID"), ff.property("Forests/FID")); Filter f2 = ff.equals(ff.property("Forests/FID"), ff.property("Buildings/FID")); Filter f = ff.and(Arrays.asList(f1, f2)); testThreeWayJoin(visitor, f); } @Test public void testThreeWayJoinNoAliasesQualified() { JoinExtractingVisitor visitor = new JoinExtractingVisitor(Arrays.asList(lakes, forests, buildings), null); Filter f1 = ff.equals(ff.property("gs:Lakes/FID"), ff.property("gs:Forests/FID")); Filter f2 = ff.equals(ff.property("gs:Forests/FID"), ff.property("gs:Buildings/FID")); Filter f = ff.and(Arrays.asList(f1, f2)); testThreeWayJoin(visitor, f); } private void testThreeWayJoin(JoinExtractingVisitor visitor, Filter f) { f.accept(visitor, null); assertEquals("b", visitor.getPrimaryAlias()); Filter primary = visitor.getPrimaryFilter(); assertNull(primary); List<Join> joins = visitor.getJoins(); assertEquals(2, joins.size()); Join j1 = joins.get(0); assertEquals("Lakes", j1.getTypeName()); assertEquals("a", j1.getAlias()); assertEquals(ff.equals(ff.property("a.FID"), ff.property("b.FID")), j1.getJoinFilter()); Join j2 = joins.get(1); assertEquals("Buildings", j2.getTypeName()); assertEquals("c", j2.getAlias()); assertEquals(ff.equals(ff.property("b.FID"), ff.property("c.FID")), j2.getJoinFilter()); } @Test public void testThreeWayJoinPrimaryFilters() { JoinExtractingVisitor visitor = new JoinExtractingVisitor(Arrays.asList(lakes, forests, buildings), Arrays.asList("a", "b", "c")); Filter fj1 = ff.equals(ff.property("a/FID"), ff.property("b/FID")); Filter fj2 = ff.equals(ff.property("b/FID"), ff.property("c/FID")); Filter f1 = ff.equals(ff.property("a/FID"), ff.literal("Lakes.10")); Filter f2 = ff.equals(ff.property("b/FID"), ff.literal("Forests.10")); Filter f3 = ff.equals(ff.property("c/FID"), ff.literal("Buildings.10")); Filter f = ff.and(Arrays.asList(f1, f2, f3, fj1, fj2)); f.accept(visitor, null); assertEquals("b", visitor.getPrimaryAlias()); Filter primary = visitor.getPrimaryFilter(); assertEquals(ff.equals(ff.property("FID"), ff.literal("Forests.10")), primary); List<Join> joins = visitor.getJoins(); assertEquals(2, joins.size()); Join j1 = joins.get(0); assertEquals("Lakes", j1.getTypeName()); assertEquals("a", j1.getAlias()); assertEquals(ff.equals(ff.property("a.FID"), ff.property("b.FID")), j1.getJoinFilter()); assertEquals(ff.equals(ff.property("FID"), ff.literal("Lakes.10")), j1.getFilter()); Join j2 = joins.get(1); assertEquals("Buildings", j2.getTypeName()); assertEquals("c", j2.getAlias()); assertEquals(ff.equals(ff.property("b.FID"), ff.property("c.FID")), j2.getJoinFilter()); assertEquals(ff.equals(ff.property("FID"), ff.literal("Buildings.10")), j2.getFilter()); } @Test public void testThreeWayJoinWithSelf() { JoinExtractingVisitor visitor = new JoinExtractingVisitor(Arrays.asList(forests, lakes, lakes), Arrays.asList("a", "b", "c")); Filter f1 = ff.equals(ff.property("a/FID"), ff.property("b/FID")); Filter f2 = ff.equals(ff.property("b/FID"), ff.property("c/FID")); Filter f = ff.and(Arrays.asList(f1, f2)); f.accept(visitor, null); assertEquals("b", visitor.getPrimaryAlias()); Filter primary = visitor.getPrimaryFilter(); assertNull(primary); List<Join> joins = visitor.getJoins(); assertEquals(2, joins.size()); Join j1 = joins.get(0); assertEquals("Forests", j1.getTypeName()); assertEquals("a", j1.getAlias()); assertEquals(ff.equals(ff.property("a.FID"), ff.property("b.FID")), j1.getJoinFilter()); Join j2 = joins.get(1); assertEquals("Lakes", j2.getTypeName()); assertEquals("c", j2.getAlias()); assertEquals(ff.equals(ff.property("b.FID"), ff.property("c.FID")), j2.getJoinFilter()); } }