/* * Geotoolkit - An Open Source Java GIS Toolkit * http://www.geotoolkit.org * * (C) 2009, 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.data.query; import junit.framework.TestCase; import org.junit.Test; import org.apache.sis.feature.FeatureExt; import org.apache.sis.feature.builder.FeatureTypeBuilder; import org.apache.sis.referencing.CommonCRS; import org.geotoolkit.data.FeatureCollection; import org.geotoolkit.data.FeatureIterator; import org.geotoolkit.data.FeatureWriter; import org.geotoolkit.data.memory.MemoryFeatureStore; import org.geotoolkit.data.session.Session; import org.geotoolkit.factory.FactoryFinder; import org.geotoolkit.util.NamesExt; import org.opengis.feature.Feature; import org.opengis.feature.FeatureType; import org.opengis.util.GenericName; import org.opengis.filter.Filter; import org.opengis.filter.FilterFactory; import org.opengis.filter.sort.SortBy; import org.opengis.filter.sort.SortOrder; import org.apache.sis.internal.feature.AttributeConvention; /** * Test query builder. * * @author Johann Sorel (Geomatys) */ public class QueryTest extends TestCase{ private static final FilterFactory FF = FactoryFinder.getFilterFactory(null); private final MemoryFeatureStore store = new MemoryFeatureStore(); private final GenericName name1; private final GenericName name2; private final String fid_1_0; private final String fid_1_1; private final String fid_1_2; private final String fid_1_3; private final String fid_1_4; private final String fid_2_0; private final String fid_2_1; private final String fid_2_2; private final String fid_2_3; private final String fid_2_4; private final String fid_2_5; public QueryTest() throws Exception { FeatureTypeBuilder builder = new FeatureTypeBuilder(); //---------------------------------------------------------------------- name1 = NamesExt.create("http://type1.com", "Type1"); builder.setName(name1); builder.addAttribute(String.class).setName(AttributeConvention.IDENTIFIER_PROPERTY); builder.addAttribute(String.class).setName("http://type1.com", "att1"); builder.addAttribute(Integer.class).setName("http://type1.com", "att2"); final FeatureType sft1 = builder.build(); store.createFeatureType(sft1); FeatureWriter fw = store.getFeatureWriter(QueryBuilder.filtered(name1.toString(),Filter.EXCLUDE)); Feature sf = fw.next(); sf.setPropertyValue("att1", "str1"); sf.setPropertyValue("att2", 1); fw.write(); fid_1_0 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att1", "str2"); sf.setPropertyValue("att2", 2); fw.write(); fid_1_1 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att1", "str3"); sf.setPropertyValue("att2", 3); fw.write(); fid_1_2 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att1", "str50"); sf.setPropertyValue("att2", 50); fw.write(); fid_1_3 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att1", "str51"); sf.setPropertyValue("att2", 51); fw.write(); fid_1_4 = FeatureExt.getId(sf).getID(); fw.close(); //---------------------------------------------------------------------- name2 = NamesExt.create("http://type2.com", "Type2"); builder = new FeatureTypeBuilder(); builder.setName(name2); builder.addAttribute(String.class).setName(AttributeConvention.IDENTIFIER_PROPERTY); builder.addAttribute(Integer.class).setName("http://type2.com", "att3"); builder.addAttribute(Double.class).setName("http://type2.com", "att4"); final FeatureType sft2 = builder.build(); store.createFeatureType(sft2); fw = store.getFeatureWriter(QueryBuilder.filtered(name2.toString(),Filter.EXCLUDE)); sf = fw.next(); sf.setPropertyValue("att3", 1); sf.setPropertyValue("att4", 10d); fw.write(); fid_2_0 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att3", 2); sf.setPropertyValue("att4", 20d); fw.write(); fid_2_1 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att3", 2); sf.setPropertyValue("att4", 30d); fw.write(); fid_2_2 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att3", 3); sf.setPropertyValue("att4", 40d); fw.write(); fid_2_3 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att3", 60); sf.setPropertyValue("att4", 60d); fw.write(); fid_2_4 = FeatureExt.getId(sf).getID(); sf = fw.next(); sf.setPropertyValue("att3", 61); sf.setPropertyValue("att4", 61d); fw.write(); fid_2_5 = FeatureExt.getId(sf).getID(); fw.close(); } /** * test static methods from querybuilder */ @Test public void testStaticQueryBuilder() throws Exception { Query query = null; GenericName name = NamesExt.create("http://test.org", "testLocal"); //test null values------------------------------------------------------ try{ QueryBuilder.all((GenericName)null); throw new Exception("We can not build a query without at least the type name."); }catch(NullPointerException ex){ //ok } try{ QueryBuilder.fids(null); throw new Exception("We can not build a query without at least the type name."); }catch(NullPointerException ex){ //ok } try{ QueryBuilder.filtered(null, Filter.EXCLUDE); throw new Exception("We can not build a query without at least the type name."); }catch(NullPointerException ex){ //ok } try{ QueryBuilder.sorted(null, new SortBy[]{FF.sort("att1", SortOrder.DESCENDING)}); throw new Exception("We can not build a query without at least the type name."); }catch(NullPointerException ex){ //ok } //all------------------------------------------------------------------- query = QueryBuilder.all(name); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), null); assertEquals(query.getResolution(), null); assertEquals(query.getFilter(), Filter.INCLUDE); assertEquals(query.getMaxFeatures(), null); assertEquals(query.getPropertyNames(), null); assertEquals(query.getSortBy(), null); assertEquals(query.getStartIndex(), 0); //only ids-------------------------------------------------------------- query = QueryBuilder.fids(name.toString()); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), null); assertEquals(query.getResolution(), null); assertEquals(query.getFilter(), Filter.INCLUDE); assertEquals(query.getMaxFeatures(), null); assertNotNull(query.getPropertyNames()); //must be an empty array, not null assertTrue(query.getPropertyNames().length == 1); //must have only one value assertEquals(query.getSortBy(), null); assertEquals(query.getStartIndex(), 0); //only filter----------------------------------------------------------- query = QueryBuilder.filtered(name.toString(), Filter.EXCLUDE); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), null); assertEquals(query.getResolution(), null); assertEquals(query.getFilter(), Filter.EXCLUDE); assertEquals(query.getMaxFeatures(), null); assertEquals(query.getPropertyNames(), null); assertEquals(query.getSortBy(), null); assertEquals(query.getStartIndex(), 0); //only sort by---------------------------------------------------------- query = QueryBuilder.sorted(name.toString(), new SortBy[]{FF.sort("att1", SortOrder.DESCENDING)}); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), null); assertEquals(query.getResolution(), null); assertEquals(query.getFilter(), Filter.INCLUDE); assertEquals(query.getMaxFeatures(), null); assertEquals(query.getPropertyNames(), null); assertNotNull(query.getSortBy()); assertTrue(query.getSortBy().length == 1); assertEquals(query.getSortBy()[0], FF.sort("att1", SortOrder.DESCENDING)); assertEquals(query.getStartIndex(), 0); } /** * test querybuilder */ @Test public void testQueryBuilder() throws Exception { GenericName name = NamesExt.create("http://test.org", "testLocal"); Query query = null; Query query2 = null; //test no parameters---------------------------------------------------- QueryBuilder qb = new QueryBuilder(); try{ query = qb.buildQuery(); throw new Exception("We can not build a query without at least the type name."); }catch(NullPointerException ex){ //ok } //test all parameters--------------------------------------------------- qb.setTypeName(name); qb.setCRS(CommonCRS.WGS84.normalizedGeographic()); qb.setResolution(new double[]{45,31}); qb.setFilter(Filter.EXCLUDE); qb.setMaxFeatures(10); qb.setProperties(new String[]{"att1","att2"}); qb.setSortBy(new SortBy[]{FF.sort("att1", SortOrder.DESCENDING)}); qb.setStartIndex(5); query = qb.buildQuery(); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), CommonCRS.WGS84.normalizedGeographic()); assertEquals(query.getResolution()[0], 45d); assertEquals(query.getResolution()[1], 31d); assertEquals(query.getFilter(), Filter.EXCLUDE); assertEquals(query.getMaxFeatures(), Integer.valueOf(10)); assertEquals(query.getPropertyNames()[0], "att1"); assertEquals(query.getPropertyNames()[1], "att2"); assertEquals(query.getSortBy()[0], FF.sort("att1", SortOrder.DESCENDING)); assertEquals(query.getStartIndex(), 5); query2 = query; //test reset------------------------------------------------------------ qb.reset(); qb.setTypeName(name); query = qb.buildQuery(); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), null); assertEquals(query.getResolution(), null); assertEquals(query.getFilter(), Filter.INCLUDE); assertEquals(query.getMaxFeatures(), null); assertEquals(query.getPropertyNames(), null); assertEquals(query.getSortBy(), null); assertEquals(query.getStartIndex(), 0); //test copy------------------------------------------------------------- qb.copy(query2); query = qb.buildQuery(); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), CommonCRS.WGS84.normalizedGeographic()); assertEquals(query.getResolution()[0], 45d); assertEquals(query.getResolution()[1], 31d); assertEquals(query.getFilter(), Filter.EXCLUDE); assertEquals(query.getMaxFeatures(), Integer.valueOf(10)); assertEquals(query.getPropertyNames()[0], "att1"); assertEquals(query.getPropertyNames()[1], "att2"); assertEquals(query.getSortBy()[0], FF.sort("att1", SortOrder.DESCENDING)); assertEquals(query.getStartIndex(), 5); //test constructor with query------------------------------------------- qb = new QueryBuilder(query2); query = qb.buildQuery(); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), CommonCRS.WGS84.normalizedGeographic()); assertEquals(query.getResolution()[0], 45d); assertEquals(query.getResolution()[1], 31d); assertEquals(query.getFilter(), Filter.EXCLUDE); assertEquals(query.getMaxFeatures(), Integer.valueOf(10)); assertEquals(query.getPropertyNames()[0], "att1"); assertEquals(query.getPropertyNames()[1], "att2"); assertEquals(query.getSortBy()[0], FF.sort("att1", SortOrder.DESCENDING)); assertEquals(query.getStartIndex(), 5); //test constructor with name-------------------------------------------- qb = new QueryBuilder(name.toString()); query = qb.buildQuery(); assertEquals(query.getTypeName(), name.toString()); assertEquals(query.getCoordinateSystemReproject(), null); assertEquals(query.getResolution(), null); assertEquals(query.getFilter(), Filter.INCLUDE); assertEquals(query.getMaxFeatures(), null); assertEquals(query.getPropertyNames(), null); assertEquals(query.getSortBy(), null); assertEquals(query.getStartIndex(), 0); } /** * Test that cross featurestore queries works correctly. */ @Test public void testInnerJoinQuery() throws Exception{ final Session session = store.createSession(false); final QueryBuilder qb = new QueryBuilder(); final Join join = new DefaultJoin( new DefaultSelector(session, name1.toString(), "s1"), new DefaultSelector(session, name2.toString(), "s2"), JoinType.INNER, FF.equals(FF.property("att2"), FF.property("att3"))); qb.setSource(join); final Query query = qb.buildQuery(); final FeatureCollection col = session.getFeatureCollection(query); FeatureIterator ite = col.iterator(); Feature f = null; Feature c1 = null; Feature c2 = null; int count = 0; while(ite.hasNext()){ count++; f = ite.next(); if(FeatureExt.getId(f).getID().equals(fid_1_0 +" "+fid_2_0)){ c1 = (Feature) f.getPropertyValue("s1"); c2 = (Feature) f.getPropertyValue("s2"); assertEquals("str1", c1.getProperty("att1").getValue()); assertEquals(1, c1.getProperty("att2").getValue()); assertEquals(1, c2.getProperty("att3").getValue()); assertEquals(10d, c2.getProperty("att4").getValue()); }else if(FeatureExt.getId(f).getID().equals(fid_1_1 +" "+fid_2_1)){ c1 = (Feature) f.getPropertyValue("s1"); c2 = (Feature) f.getPropertyValue("s2"); assertEquals("str2", c1.getProperty("att1").getValue()); assertEquals(2, c1.getProperty("att2").getValue()); assertEquals(2, c2.getProperty("att3").getValue()); assertEquals(20d, c2.getProperty("att4").getValue()); }else if(FeatureExt.getId(f).getID().equals(fid_1_1 +" "+fid_2_2)){ c1 = (Feature) f.getPropertyValue("s1"); c2 = (Feature) f.getPropertyValue("s2"); assertEquals("str2", c1.getProperty("att1").getValue()); assertEquals(2, c1.getProperty("att2").getValue()); assertEquals(2, c2.getProperty("att3").getValue()); assertEquals(30d, c2.getProperty("att4").getValue()); }else if(FeatureExt.getId(f).getID().equals(fid_1_2 +" "+fid_2_3)){ c1 = (Feature) f.getPropertyValue("s1"); c2 = (Feature) f.getPropertyValue("s2"); assertEquals("str3", c1.getProperty("att1").getValue()); assertEquals(3, c1.getProperty("att2").getValue()); assertEquals(3, c2.getProperty("att3").getValue()); assertEquals(40d, c2.getProperty("att4").getValue()); }else{ fail("unexpected feature"); } } assertEquals("Was expecting 4 features.",4, count); ite.close(); } /** * Test that cross featurestore queries works correctly. */ @Test public void testOuterLeftQuery() throws Exception{ final Session session = store.createSession(false); final QueryBuilder qb = new QueryBuilder(); final Join join = new DefaultJoin( new DefaultSelector(session, name1.toString(), "s1"), new DefaultSelector(session, name2.toString(), "s2"), JoinType.LEFT_OUTER, FF.equals(FF.property("att2"), FF.property("att3"))); qb.setSource(join); final Query query = qb.buildQuery(); final FeatureCollection col = session.getFeatureCollection(query); final FeatureIterator ite = col.iterator(); boolean foundStr1 = false; boolean foundStr20 = false; boolean foundStr21 = false; boolean foundStr3 = false; boolean foundStr50 = false; boolean foundStr51 = false; int count = 0; while(ite.hasNext()){ final Feature f = ite.next(); final Feature c1 = (Feature) f.getPropertyValue("s1"); final Feature c2 = (Feature) f.getPropertyValue("s2"); final String att1 = c1.getProperty("att1").getValue().toString(); if(att1.equals("str1")){ foundStr1 = true; assertEquals(c1.getProperty("att2").getValue(), 1); assertEquals(c2.getProperty("att3").getValue(), 1); assertEquals(c2.getProperty("att4").getValue(), 10d); }else if(att1.equals("str2")){ assertEquals(c1.getProperty("att2").getValue(), 2); assertEquals(c2.getProperty("att3").getValue(), 2); double att4 = (Double)c2.getProperty("att4").getValue(); if(att4 == 20d){ foundStr20 = true; }else if(att4 == 30d){ foundStr21 = true; } }else if(att1.equals("str3")){ foundStr3 = true; assertEquals(c1.getProperty("att2").getValue(), 3); assertEquals(c2.getProperty("att3").getValue(), 3); assertEquals(c2.getProperty("att4").getValue(), 40d); }else if(att1.equals("str50")){ foundStr50 = true; assertEquals(c1.getProperty("att2").getValue(), 50); assertNull(c2); }else if(att1.equals("str51")){ foundStr51 = true; assertEquals(c1.getProperty("att2").getValue(), 51); assertNull(c2); } count++; } assertTrue(foundStr1); assertTrue(foundStr20); assertTrue(foundStr21); assertTrue(foundStr3); assertTrue(foundStr50); assertTrue(foundStr51); assertEquals(6, count); ite.close(); } /** * Test that cross featurestore queries works correctly. */ @Test public void testOuterRightQuery() throws Exception{ final Session session = store.createSession(false); final QueryBuilder qb = new QueryBuilder(); final Join join = new DefaultJoin( new DefaultSelector(session, name1.toString(), "s1"), new DefaultSelector(session, name2.toString(), "s2"), JoinType.RIGHT_OUTER, FF.equals(FF.property("att2"), FF.property("att3"))); qb.setSource(join); final Query query = qb.buildQuery(); final FeatureCollection col = session.getFeatureCollection(query); final FeatureIterator ite = col.iterator(); boolean foundStr1 = false; boolean foundStr20 = false; boolean foundStr21 = false; boolean foundStr3 = false; boolean foundStr60 = false; boolean foundStr61 = false; int count = 0; while(ite.hasNext()){ final Feature f = ite.next(); final Feature c1 = (Feature) f.getPropertyValue("s1"); final Feature c2 = (Feature) f.getPropertyValue("s2"); if(c1 != null){ final Object att1 = c1.getProperty("att1").getValue(); if("str1".equals(att1)){ foundStr1 = true; assertEquals(c1.getProperty("att2").getValue(), 1); assertEquals(c2.getProperty("att3").getValue(), 1); assertEquals(c2.getProperty("att4").getValue(), 10d); }else if("str2".equals(att1)){ assertEquals(c1.getProperty("att2").getValue(), 2); assertEquals(c2.getProperty("att3").getValue(), 2); double att4 = (Double)c2.getProperty("att4").getValue(); if(att4 == 20d){ foundStr20 = true; }else if(att4 == 30d){ foundStr21 = true; } }else if("str3".equals(att1)){ foundStr3 = true; assertEquals(c1.getProperty("att2").getValue(), 3); assertEquals(c2.getProperty("att3").getValue(), 3); assertEquals(c2.getProperty("att4").getValue(), 40d); } }else{ int att3 = (Integer)c2.getProperty("att3").getValue(); if(att3 == 60){ assertEquals(c2.getProperty("att4").getValue(), 60d); foundStr60 = true; }else if(att3 == 61){ assertEquals(c2.getProperty("att4").getValue(), 61d); foundStr61 = true; } } count++; } assertTrue(foundStr1); assertTrue(foundStr20); assertTrue(foundStr21); assertTrue(foundStr3); assertTrue(foundStr60); assertTrue(foundStr61); assertEquals(6, count); } }