You can subscribe to this list here.
2001 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
(39) |
Dec
(70) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2002 |
Jan
(52) |
Feb
(168) |
Mar
(248) |
Apr
(143) |
May
(418) |
Jun
(558) |
Jul
(702) |
Aug
(311) |
Sep
(141) |
Oct
(350) |
Nov
(172) |
Dec
(182) |
2003 |
Jan
(320) |
Feb
(362) |
Mar
(356) |
Apr
(218) |
May
(447) |
Jun
(203) |
Jul
(745) |
Aug
(494) |
Sep
(175) |
Oct
(422) |
Nov
(554) |
Dec
(162) |
2004 |
Jan
(217) |
Feb
(353) |
Mar
(228) |
Apr
(407) |
May
(211) |
Jun
(270) |
Jul
(264) |
Aug
(198) |
Sep
(268) |
Oct
(227) |
Nov
(118) |
Dec
(47) |
2005 |
Jan
(207) |
Feb
(243) |
Mar
(297) |
Apr
(197) |
May
(281) |
Jun
(166) |
Jul
(164) |
Aug
(92) |
Sep
(155) |
Oct
(196) |
Nov
(189) |
Dec
(114) |
2006 |
Jan
(129) |
Feb
(219) |
Mar
(274) |
Apr
(213) |
May
(245) |
Jun
(220) |
Jul
(376) |
Aug
(347) |
Sep
(179) |
Oct
(493) |
Nov
(448) |
Dec
(339) |
2007 |
Jan
(304) |
Feb
(273) |
Mar
(237) |
Apr
(186) |
May
(215) |
Jun
(320) |
Jul
(229) |
Aug
(313) |
Sep
(331) |
Oct
(279) |
Nov
(347) |
Dec
(266) |
2008 |
Jan
(332) |
Feb
(280) |
Mar
(203) |
Apr
(277) |
May
(301) |
Jun
(356) |
Jul
(292) |
Aug
(203) |
Sep
(277) |
Oct
(142) |
Nov
(210) |
Dec
(239) |
2009 |
Jan
(250) |
Feb
(193) |
Mar
(174) |
Apr
(183) |
May
(342) |
Jun
(230) |
Jul
(292) |
Aug
(161) |
Sep
(204) |
Oct
(280) |
Nov
(281) |
Dec
(175) |
2010 |
Jan
(113) |
Feb
(106) |
Mar
(199) |
Apr
(166) |
May
(298) |
Jun
(147) |
Jul
(175) |
Aug
(192) |
Sep
(71) |
Oct
(79) |
Nov
(58) |
Dec
(55) |
2011 |
Jan
(83) |
Feb
(169) |
Mar
(142) |
Apr
(207) |
May
(311) |
Jun
(183) |
Jul
(218) |
Aug
(190) |
Sep
(158) |
Oct
(197) |
Nov
(93) |
Dec
(74) |
2012 |
Jan
(92) |
Feb
(50) |
Mar
(64) |
Apr
(45) |
May
(100) |
Jun
(70) |
Jul
(3) |
Aug
(1) |
Sep
(2) |
Oct
(5) |
Nov
(7) |
Dec
(4) |
2013 |
Jan
(6) |
Feb
(2) |
Mar
(2) |
Apr
(4) |
May
(3) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2014 |
Jan
(2) |
Feb
(2) |
Mar
(2) |
Apr
(3) |
May
(3) |
Jun
(1) |
Jul
|
Aug
(4) |
Sep
|
Oct
(1) |
Nov
(1) |
Dec
|
2015 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
(1) |
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
(1) |
Dec
(1) |
2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
(1) |
Jul
|
Aug
(3) |
Sep
|
Oct
|
Nov
(1) |
Dec
|
2017 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
Author: aaime Date: 2012-04-15 17:35:58 -0700 (Sun, 15 Apr 2012) New Revision: 38671 Added: trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumDiameter.java trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_octagonalEnvelope.java trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function.orig trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumDiameterTest.java trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_octagonalEnvelopeTest.java Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function Log: [GEOT-4099] Octagonal Envelope and Minimum Diameter Filter Functions, patch by Jared Erickson Added: trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumDiameter.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumDiameter.java (rev 0) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumDiameter.java 2012-04-16 00:35:58 UTC (rev 38671) @@ -0,0 +1,74 @@ +package org.geotools.filter.function; + +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2005-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. + */ +import com.vividsolutions.jts.geom.Geometry; +import org.geotools.filter.FunctionExpressionImpl; +import org.geotools.filter.capability.FunctionNameImpl; +import org.opengis.filter.capability.FunctionName; + +/** + * A FilterFunction that expects a Geometry and returns it's minimum diameter. + * @author Jared Erickson + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumDiameter.java $ + */ +public class FilterFunction_minimumDiameter extends FunctionExpressionImpl { + + /** + * The FunctionName + */ + public static FunctionName NAME = new FunctionNameImpl("minimumdiameter","geometry"); + + /** + * Create a new FilterFunction_minimumDiameter instance + */ + public FilterFunction_minimumDiameter() { + super(NAME); + } + + /** + * Get the number of arguments + * @return The number of arguments + */ + @Override + public int getArgCount() { + return 1; + } + + /** + * Calculate the Geometry's minimum diameter. + * @param feature The feature should be a Geometry + * @return The minimum diameter Geometry + * @throws IllegalArgumentException if the feature is not a Geometry + */ + @Override + public Object evaluate(Object feature) { + Geometry arg0; + + // attempt to get value and perform conversion + try { + arg0 = (Geometry) getExpression(0).evaluate(feature); + } catch (Exception e) { + // probably a type error + throw new IllegalArgumentException( + "Filter Function problem for function minimum diameter argument #0 - expected type Geometry"); + } + + return (StaticGeometry.minimumDiameter(arg0)); + } +} Added: trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_octagonalEnvelope.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_octagonalEnvelope.java (rev 0) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_octagonalEnvelope.java 2012-04-16 00:35:58 UTC (rev 38671) @@ -0,0 +1,74 @@ +package org.geotools.filter.function; + +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2005-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. + */ +import com.vividsolutions.jts.geom.Geometry; +import org.geotools.filter.FunctionExpressionImpl; +import org.geotools.filter.capability.FunctionNameImpl; +import org.opengis.filter.capability.FunctionName; + +/** + * A FilterFunction that expects a Geometry and returns it's octagonal envelope. + * @author Jared Erickson + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_octagonalEnvelope.java $ + */ +public class FilterFunction_octagonalEnvelope extends FunctionExpressionImpl { + + /** + * The FunctionName + */ + public static FunctionName NAME = new FunctionNameImpl("octagonalenvelope","geometry"); + + /** + * Create a new FilterFunction_octagonalEnvelope instance + */ + public FilterFunction_octagonalEnvelope() { + super(NAME); + } + + /** + * Get the number of arguments + * @return The number of arguments + */ + @Override + public int getArgCount() { + return 1; + } + + /** + * Calculate the Geometry's octagonal envelope. + * @param feature The feature should be a Geometry + * @return The octagonal envelope Geometry + * @throws IllegalArgumentException if the feature is not a Geometry + */ + @Override + public Object evaluate(Object feature) { + Geometry arg0; + + // attempt to get value and perform conversion + try { + arg0 = (Geometry) getExpression(0).evaluate(feature); + } catch (Exception e) { + // probably a type error + throw new IllegalArgumentException( + "Filter Function problem for function octagonal envelope argument #0 - expected type Geometry"); + } + + return (StaticGeometry.octagonalEnvelope(arg0)); + } +} Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java 2012-04-16 00:25:15 UTC (rev 38670) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java 2012-04-16 00:35:58 UTC (rev 38671) @@ -26,6 +26,7 @@ import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.geom.OctagonalEnvelope; import com.vividsolutions.jts.io.WKTReader; @@ -450,6 +451,18 @@ return min.getMinimumRectangle(); } + static public Geometry octagonalEnvelope(Geometry arg0) { + if (arg0 == null) return null; + OctagonalEnvelope env = new OctagonalEnvelope(arg0); + return env.toGeometry(arg0.getFactory()); + } + + static public Geometry minimumDiameter(Geometry arg0) { + if (arg0 == null) return null; + MinimumDiameter minDiameter = new MinimumDiameter(arg0); + return minDiameter.getDiameter(); + } + //-------------------------------------------------------------------------- //JAVA String functions static public String strConcat(String s1,String s2) Modified: trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function =================================================================== --- trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function 2012-04-16 00:25:15 UTC (rev 38670) +++ trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function 2012-04-16 00:35:58 UTC (rev 38671) @@ -70,6 +70,8 @@ org.geotools.filter.function.FilterFunction_minimumCircle org.geotools.filter.function.FilterFunction_minimumRectangle org.geotools.filter.function.FilterFunction_interiorRingN +org.geotools.filter.function.FilterFunction_octagonalEnvelope +org.geotools.filter.function.FilterFunction_minimumDiameter org.geotools.filter.function.FilterFunction_strConcat org.geotools.filter.function.FilterFunction_strEndsWith org.geotools.filter.function.FilterFunction_strStartsWith Copied: trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function.orig (from rev 38668, trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function) =================================================================== --- trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function.orig (rev 0) +++ trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function.orig 2012-04-16 00:35:58 UTC (rev 38671) @@ -0,0 +1,160 @@ +org.geotools.filter.AreaFunction +org.geotools.filter.LengthFunction +org.geotools.filter.function.CategorizeFunction +org.geotools.filter.function.ClassifyFunction +org.geotools.filter.function.EqualIntervalFunction +org.geotools.filter.function.StandardDeviationFunction +org.geotools.filter.function.QuantileFunction +org.geotools.filter.function.UniqueIntervalFunction +org.geotools.filter.function.Collection_AverageFunction +org.geotools.filter.function.Collection_BoundsFunction +org.geotools.filter.function.Collection_CountFunction +org.geotools.filter.function.Collection_MinFunction +org.geotools.filter.function.Collection_MedianFunction +org.geotools.filter.function.Collection_MaxFunction +org.geotools.filter.function.Collection_SumFunction +org.geotools.filter.function.Collection_UniqueFunction +org.geotools.filter.function.EnvFunction +org.geotools.filter.function.FilterFunction_contains +org.geotools.filter.function.FilterFunction_isEmpty +org.geotools.filter.function.FilterFunction_parseDouble +org.geotools.filter.function.FilterFunction_parseInt +org.geotools.filter.function.FilterFunction_parseLong +org.geotools.filter.function.FilterFunction_intersects +org.geotools.filter.function.FilterFunction_isClosed +org.geotools.filter.function.FilterFunction_geomFromWKT +org.geotools.filter.function.FilterFunction_toWKT +org.geotools.filter.function.FilterFunction_geomLength +org.geotools.filter.function.FilterFunction_isValid +org.geotools.filter.function.FilterFunction_geometryType +org.geotools.filter.function.FilterFunction_numPoints +org.geotools.filter.function.FilterFunction_isSimple +org.geotools.filter.function.FilterFunction_distance +org.geotools.filter.function.FilterFunction_isWithinDistance +org.geotools.filter.function.FilterFunction_area +org.geotools.filter.function.FilterFunction_centroid +org.geotools.filter.function.FilterFunction_interiorPoint +org.geotools.filter.function.FilterFunction_dimension +org.geotools.filter.function.FilterFunction_boundary +org.geotools.filter.function.FilterFunction_boundaryDimension +org.geotools.filter.function.FilterFunction_envelope +org.geotools.filter.function.FilterFunction_disjoint +org.geotools.filter.function.FilterFunction_touches +org.geotools.filter.function.FilterFunction_crosses +org.geotools.filter.function.FilterFunction_within +org.geotools.filter.function.FilterFunction_overlaps +org.geotools.filter.function.FilterFunction_relatePattern +org.geotools.filter.function.FilterFunction_relate +org.geotools.filter.function.FilterFunction_bufferWithSegments +org.geotools.filter.function.FilterFunction_buffer +org.geotools.filter.function.FilterFunction_convexHull +org.geotools.filter.function.FilterFunction_intersection +org.geotools.filter.function.FilterFunction_union +org.geotools.filter.function.FilterFunction_difference +org.geotools.filter.function.FilterFunction_symDifference +org.geotools.filter.function.FilterFunction_equalsExactTolerance +org.geotools.filter.function.FilterFunction_equalsExact +org.geotools.filter.function.FilterFunction_numGeometries +org.geotools.filter.function.FilterFunction_getGeometryN +org.geotools.filter.function.FilterFunction_getX +org.geotools.filter.function.FilterFunction_getY +org.geotools.filter.function.FilterFunction_getZ +org.geotools.filter.function.FilterFunction_pointN +org.geotools.filter.function.FilterFunction_startAngle +org.geotools.filter.function.FilterFunction_startPoint +org.geotools.filter.function.FilterFunction_endPoint +org.geotools.filter.function.FilterFunction_endAngle +org.geotools.filter.function.FilterFunction_isRing +org.geotools.filter.function.FilterFunction_exteriorRing +org.geotools.filter.function.FilterFunction_numInteriorRing +org.geotools.filter.function.FilterFunction_minimumCircle +org.geotools.filter.function.FilterFunction_minimumRectangle +org.geotools.filter.function.FilterFunction_interiorRingN +org.geotools.filter.function.FilterFunction_strConcat +org.geotools.filter.function.FilterFunction_strEndsWith +org.geotools.filter.function.FilterFunction_strStartsWith +org.geotools.filter.function.FilterFunction_strCapitalize +org.geotools.filter.function.FilterFunction_strEqualsIgnoreCase +org.geotools.filter.function.FilterFunction_strIndexOf +org.geotools.filter.function.FilterFunction_strLastIndexOf +org.geotools.filter.function.FilterFunction_strLength +org.geotools.filter.function.FilterFunction_strToLowerCase +org.geotools.filter.function.FilterFunction_strToUpperCase +org.geotools.filter.function.FilterFunction_strMatches +org.geotools.filter.function.FilterFunction_strPosition +org.geotools.filter.function.FilterFunction_strReplace +org.geotools.filter.function.FilterFunction_strSubstring +org.geotools.filter.function.FilterFunction_strSubstringStart +org.geotools.filter.function.FilterFunction_strTrim +org.geotools.filter.function.FilterFunction_strTrim2 +org.geotools.filter.function.FilterFunction_parseBoolean +org.geotools.filter.function.FilterFunction_roundDouble +org.geotools.filter.function.FilterFunction_int2ddouble +org.geotools.filter.function.FilterFunction_int2bbool +org.geotools.filter.function.FilterFunction_double2bool +org.geotools.filter.function.FilterFunction_if_then_else +org.geotools.filter.function.FilterFunction_equalTo +org.geotools.filter.function.FilterFunction_notEqualTo +org.geotools.filter.function.FilterFunction_lessThan +org.geotools.filter.function.FilterFunction_greaterThan +org.geotools.filter.function.FilterFunction_greaterEqualThan +org.geotools.filter.function.FilterFunction_lessEqualThan +org.geotools.filter.function.FilterFunction_isLike +org.geotools.filter.function.FilterFunction_isNull +org.geotools.filter.function.FilterFunction_between +org.geotools.filter.function.FilterFunction_not +org.geotools.filter.function.FilterFunction_in2 +org.geotools.filter.function.FilterFunction_in3 +org.geotools.filter.function.FilterFunction_in4 +org.geotools.filter.function.FilterFunction_in5 +org.geotools.filter.function.FilterFunction_in6 +org.geotools.filter.function.FilterFunction_in7 +org.geotools.filter.function.FilterFunction_in8 +org.geotools.filter.function.FilterFunction_in9 +org.geotools.filter.function.FilterFunction_in10 +org.geotools.filter.function.FilterFunction_dateParse +org.geotools.filter.function.FilterFunction_dateFormat +org.geotools.filter.function.FilterFunction_numberFormat +org.geotools.filter.function.FilterFunction_numberFormat2 +org.geotools.filter.function.FilterFunction_Convert +org.geotools.filter.function.FilterFunction_vertices +org.geotools.filter.function.FilterFunction_offset +org.geotools.filter.function.FilterFunction_isometric +org.geotools.filter.function.IDFunction +org.geotools.filter.function.InterpolateFunction +org.geotools.filter.function.RecodeFunction +org.geotools.filter.function.math.FilterFunction_IEEEremainder +org.geotools.filter.function.math.FilterFunction_abs +org.geotools.filter.function.math.FilterFunction_abs_2 +org.geotools.filter.function.math.FilterFunction_abs_3 +org.geotools.filter.function.math.FilterFunction_abs_4 +org.geotools.filter.function.math.FilterFunction_acos +org.geotools.filter.function.math.FilterFunction_asin +org.geotools.filter.function.math.FilterFunction_atan +org.geotools.filter.function.math.FilterFunction_atan2 +org.geotools.filter.function.math.FilterFunction_ceil +org.geotools.filter.function.math.FilterFunction_cos +org.geotools.filter.function.math.FilterFunction_exp +org.geotools.filter.function.math.FilterFunction_floor +org.geotools.filter.function.math.FilterFunction_log +org.geotools.filter.function.math.FilterFunction_max +org.geotools.filter.function.math.FilterFunction_max_2 +org.geotools.filter.function.math.FilterFunction_max_3 +org.geotools.filter.function.math.FilterFunction_max_4 +org.geotools.filter.function.math.FilterFunction_min +org.geotools.filter.function.math.FilterFunction_min_2 +org.geotools.filter.function.math.FilterFunction_min_3 +org.geotools.filter.function.math.FilterFunction_min_4 +org.geotools.filter.function.math.FilterFunction_pow +org.geotools.filter.function.math.FilterFunction_random +org.geotools.filter.function.math.FilterFunction_rint +org.geotools.filter.function.math.FilterFunction_round +org.geotools.filter.function.math.FilterFunction_round_2 +org.geotools.filter.function.math.FilterFunction_sin +org.geotools.filter.function.math.FilterFunction_sqrt +org.geotools.filter.function.math.FilterFunction_tan +org.geotools.filter.function.math.FilterFunction_toDegrees +org.geotools.filter.function.math.FilterFunction_toRadians +org.geotools.filter.function.math.PiFunction +org.geotools.filter.function.string.ConcatenateFunction +org.geotools.filter.function.JenksNaturalBreaksFunction \ No newline at end of file Added: trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumDiameterTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumDiameterTest.java (rev 0) +++ trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumDiameterTest.java 2012-04-16 00:35:58 UTC (rev 38671) @@ -0,0 +1,86 @@ +package org.geotools.filter.function; + +import com.vividsolutions.jts.algorithm.MinimumDiameter; +import static org.junit.Assert.*; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.io.WKTReader; +import org.geotools.data.DataUtilities; +import org.geotools.data.memory.MemoryDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.GeoTools; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.junit.Test; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.FilterFactory2; +import org.opengis.filter.expression.Function; + +/** + * The FilterFunction_minimumDiameter UnitTest + * @author Jared Erickson + */ +public class FilterFunction_minimumDiameterTest { + + /** + * Test of getArgCount method, of class FilterFunction_minimumDiameter. + */ + @Test + public void testGetArgCount() { + FilterFunction_minimumDiameter f = new FilterFunction_minimumDiameter(); + assertEquals(1, f.getArgCount()); + } + + /** + * Test of getName method, of class FilterFunction_minimumDiameter. + */ + @Test + public void getName() { + FilterFunction_minimumDiameter f = new FilterFunction_minimumDiameter(); + assertEquals("minimumdiameter", f.getName()); + } + + /** + * Test of evaluate method, of class FilterFunction_minimumDiameter. + */ + @Test + public void testEvaluate() throws Exception { + + // Create SimpleFeatures + SimpleFeatureType type = DataUtilities.createType("polygons", "id:int,geom:Polygon"); + MemoryDataStore store = new MemoryDataStore(); + store.createSchema(type); + String[] polygons = { + "POLYGON ((1235702.2034807256 707935.1879023351, 1229587.156498981 671715.2942412316, 1242287.6386918353 688649.2704983709, 1245109.9680680253 677359.9529936113, 1247932.297444215 711227.9055078899, 1239935.6975450104 705583.2467555101, 1235702.2034807256 707935.1879023351))", + "POLYGON ((1237113.3681688206 622324.5301579087, 1224883.274205331 586575.0247261701, 1258280.8384902447 589397.3541023601, 1237113.3681688206 622324.5301579087))", + "POLYGON ((1131746.4047910655 718754.1171777296, 1115282.8167632914 681593.4470578962, 1139272.6164609052 679241.5059110713, 1147269.2163601099 707935.1879023351, 1131746.4047910655 718754.1171777296)))" + }; + WKTReader reader = new WKTReader(); + SimpleFeature[] features = new SimpleFeature[polygons.length]; + for (int i = 0; i < polygons.length; i++) { + Geometry polygon = reader.read(polygons[i]); + features[i] = SimpleFeatureBuilder.build(type, new Object[]{i, polygon}, String.valueOf(i)); + } + store.addFeatures(features); + SimpleFeatureCollection featureCollection = store.getFeatureSource("polygons").getFeatures(); + + // Test the Function + FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); + Function exp = ff.function("minimumdiameter", ff.property("geom")); + SimpleFeatureIterator iter = featureCollection.features(); + while (iter.hasNext()) { + SimpleFeature feature = iter.next(); + Geometry geom = (Geometry) feature.getDefaultGeometry(); + Geometry minimumDiameter = new MinimumDiameter(geom).getDiameter(); + Object value = exp.evaluate(feature); + assertTrue(value instanceof LineString); + assertTrue(minimumDiameter.equalsExact((Geometry) value, 0.1)); + } + iter.close(); + + // Check for null safeness + assertNull(exp.evaluate(null)); + } +} Added: trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_octagonalEnvelopeTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_octagonalEnvelopeTest.java (rev 0) +++ trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_octagonalEnvelopeTest.java 2012-04-16 00:35:58 UTC (rev 38671) @@ -0,0 +1,86 @@ +package org.geotools.filter.function; + +import static org.junit.Assert.*; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.OctagonalEnvelope; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.io.WKTReader; +import org.geotools.data.DataUtilities; +import org.geotools.data.memory.MemoryDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.GeoTools; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.junit.Test; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.FilterFactory2; +import org.opengis.filter.expression.Function; + +/** + * The FilterFunction_octagonalEnvelope UnitTest + * @author Jared Erickson + */ +public class FilterFunction_octagonalEnvelopeTest { + + /** + * Test of getArgCount method, of class FilterFunction_octagonalEnvelope. + */ + @Test + public void testGetArgCount() { + FilterFunction_octagonalEnvelope f = new FilterFunction_octagonalEnvelope(); + assertEquals(1, f.getArgCount()); + } + + /** + * Test of getName method, of class FilterFunction_octagonalEnvelope. + */ + @Test + public void getName() { + FilterFunction_octagonalEnvelope f = new FilterFunction_octagonalEnvelope(); + assertEquals("octagonalenvelope", f.getName()); + } + + /** + * Test of evaluate method, of class FilterFunction_octagonalEnvelope. + */ + @Test + public void testEvaluate() throws Exception { + + // Create SimpleFeatures + SimpleFeatureType type = DataUtilities.createType("polygons", "id:int,geom:Polygon"); + MemoryDataStore store = new MemoryDataStore(); + store.createSchema(type); + String[] polygons = { + "POLYGON ((1235702.2034807256 707935.1879023351, 1229587.156498981 671715.2942412316, 1242287.6386918353 688649.2704983709, 1245109.9680680253 677359.9529936113, 1247932.297444215 711227.9055078899, 1239935.6975450104 705583.2467555101, 1235702.2034807256 707935.1879023351))", + "POLYGON ((1237113.3681688206 622324.5301579087, 1224883.274205331 586575.0247261701, 1258280.8384902447 589397.3541023601, 1237113.3681688206 622324.5301579087))", + "POLYGON ((1131746.4047910655 718754.1171777296, 1115282.8167632914 681593.4470578962, 1139272.6164609052 679241.5059110713, 1147269.2163601099 707935.1879023351, 1131746.4047910655 718754.1171777296)))" + }; + WKTReader reader = new WKTReader(); + SimpleFeature[] features = new SimpleFeature[polygons.length]; + for (int i = 0; i < polygons.length; i++) { + Geometry polygon = reader.read(polygons[i]); + features[i] = SimpleFeatureBuilder.build(type, new Object[]{i, polygon}, String.valueOf(i)); + } + store.addFeatures(features); + SimpleFeatureCollection featureCollection = store.getFeatureSource("polygons").getFeatures(); + + // Test the Function + FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); + Function exp = ff.function("octagonalenvelope", ff.property("geom")); + SimpleFeatureIterator iter = featureCollection.features(); + while (iter.hasNext()) { + SimpleFeature feature = iter.next(); + Geometry geom = (Geometry) feature.getDefaultGeometry(); + Geometry octagonalEnvelope = new OctagonalEnvelope(geom).toGeometry(geom.getFactory()); + Object value = exp.evaluate(feature); + assertTrue(value instanceof Polygon); + assertTrue(octagonalEnvelope.equalsExact((Geometry) value, 0.1)); + } + iter.close(); + + // Check for null safeness + assertNull(exp.evaluate(null)); + } +} |
From: <svn...@os...> - 2012-04-16 00:25:22
|
Author: aaime Date: 2012-04-15 17:25:15 -0700 (Sun, 15 Apr 2012) New Revision: 38670 Added: branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java Log: Forgot to add tests Added: branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java =================================================================== --- branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java (rev 0) +++ branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java 2012-04-16 00:25:15 UTC (rev 38670) @@ -0,0 +1,86 @@ +package org.geotools.filter.function; + +import com.vividsolutions.jts.algorithm.MinimumBoundingCircle; +import static org.junit.Assert.*; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.io.WKTReader; +import org.geotools.data.DataUtilities; +import org.geotools.data.memory.MemoryDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.GeoTools; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.junit.Test; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.FilterFactory2; +import org.opengis.filter.expression.Function; + +/** + * The FilterFunction_minimumCircle UnitTest + * @author Jared Erickson + */ +public class FilterFunction_minimumCircleTest { + + /** + * Test of getArgCount method, of class FilterFunction_minimumCircle. + */ + @Test + public void testGetArgCount() { + FilterFunction_minimumCircle f = new FilterFunction_minimumCircle(); + assertEquals(1, f.getArgCount()); + } + + /** + * Test of getName method, of class FilterFunction_minimumCircle. + */ + @Test + public void getName() { + FilterFunction_minimumCircle f = new FilterFunction_minimumCircle(); + assertEquals("mincircle", f.getName()); + } + + /** + * Test of evaluate method, of class FilterFunction_minimumCircle. + */ + @Test + public void testEvaluate() throws Exception { + + // Create SimpleFeatures + SimpleFeatureType type = DataUtilities.createType("polygons", "id:int,geom:Polygon"); + MemoryDataStore store = new MemoryDataStore(); + store.createSchema(type); + String[] polygons = { + "POLYGON ((1235702.2034807256 707935.1879023351, 1229587.156498981 671715.2942412316, 1242287.6386918353 688649.2704983709, 1245109.9680680253 677359.9529936113, 1247932.297444215 711227.9055078899, 1239935.6975450104 705583.2467555101, 1235702.2034807256 707935.1879023351))", + "POLYGON ((1237113.3681688206 622324.5301579087, 1224883.274205331 586575.0247261701, 1258280.8384902447 589397.3541023601, 1237113.3681688206 622324.5301579087))", + "POLYGON ((1131746.4047910655 718754.1171777296, 1115282.8167632914 681593.4470578962, 1139272.6164609052 679241.5059110713, 1147269.2163601099 707935.1879023351, 1131746.4047910655 718754.1171777296)))" + }; + WKTReader reader = new WKTReader(); + SimpleFeature[] features = new SimpleFeature[polygons.length]; + for (int i = 0; i < polygons.length; i++) { + Geometry polygon = reader.read(polygons[i]); + features[i] = SimpleFeatureBuilder.build(type, new Object[]{i, polygon}, String.valueOf(i)); + } + store.addFeatures(features); + SimpleFeatureCollection featureCollection = store.getFeatureSource("polygons").getFeatures(); + + // Test the Function + FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); + Function exp = ff.function("mincircle", ff.property("geom")); + SimpleFeatureIterator iter = featureCollection.features(); + while (iter.hasNext()) { + SimpleFeature feature = iter.next(); + Geometry geom = (Geometry) feature.getDefaultGeometry(); + Geometry circle = new MinimumBoundingCircle(geom).getCircle(); + Object value = exp.evaluate(feature); + assertTrue(value instanceof Polygon); + assertTrue(circle.equals((Geometry) value)); + } + iter.close(); + + // Check for null safeness + assertNull(exp.evaluate(null)); + } +} Added: branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java =================================================================== --- branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java (rev 0) +++ branches/2.7.x/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java 2012-04-16 00:25:15 UTC (rev 38670) @@ -0,0 +1,86 @@ +package org.geotools.filter.function; + +import com.vividsolutions.jts.algorithm.MinimumDiameter; +import static org.junit.Assert.*; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.io.WKTReader; +import org.geotools.data.DataUtilities; +import org.geotools.data.memory.MemoryDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.GeoTools; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.junit.Test; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.FilterFactory2; +import org.opengis.filter.expression.Function; + +/** + * The FilterFunction_minimumRectangle UnitTest + * @author Jared Erickson + */ +public class FilterFunction_minimumRectangleTest { + + /** + * Test of getArgCount method, of class FilterFunction_minimumRectangle. + */ + @Test + public void testGetArgCount() { + FilterFunction_minimumRectangle f = new FilterFunction_minimumRectangle(); + assertEquals(1, f.getArgCount()); + } + + /** + * Test of getName method, of class FilterFunction_minimumRectangle. + */ + @Test + public void getName() { + FilterFunction_minimumRectangle f = new FilterFunction_minimumRectangle(); + assertEquals("minrectangle", f.getName()); + } + + /** + * Test of evaluate method, of class FilterFunction_minimumCircle. + */ + @Test + public void testEvaluate() throws Exception { + + // Create SimpleFeatures + SimpleFeatureType type = DataUtilities.createType("polygons", "id:int,geom:Polygon"); + MemoryDataStore store = new MemoryDataStore(); + store.createSchema(type); + String[] polygons = { + "POLYGON ((1235702.2034807256 707935.1879023351, 1229587.156498981 671715.2942412316, 1242287.6386918353 688649.2704983709, 1245109.9680680253 677359.9529936113, 1247932.297444215 711227.9055078899, 1239935.6975450104 705583.2467555101, 1235702.2034807256 707935.1879023351))", + "POLYGON ((1237113.3681688206 622324.5301579087, 1224883.274205331 586575.0247261701, 1258280.8384902447 589397.3541023601, 1237113.3681688206 622324.5301579087))", + "POLYGON ((1131746.4047910655 718754.1171777296, 1115282.8167632914 681593.4470578962, 1139272.6164609052 679241.5059110713, 1147269.2163601099 707935.1879023351, 1131746.4047910655 718754.1171777296)))" + }; + WKTReader reader = new WKTReader(); + SimpleFeature[] features = new SimpleFeature[polygons.length]; + for (int i = 0; i < polygons.length; i++) { + Geometry polygon = reader.read(polygons[i]); + features[i] = SimpleFeatureBuilder.build(type, new Object[]{i, polygon}, String.valueOf(i)); + } + store.addFeatures(features); + SimpleFeatureCollection featureCollection = store.getFeatureSource("polygons").getFeatures(); + + // Test the Function + FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); + Function exp = ff.function("minrectangle", ff.property("geom")); + SimpleFeatureIterator iter = featureCollection.features(); + while (iter.hasNext()) { + SimpleFeature feature = iter.next(); + Geometry geom = (Geometry) feature.getDefaultGeometry(); + Geometry rectangle = new MinimumDiameter(geom).getMinimumRectangle(); + Object value = exp.evaluate(feature); + assertTrue(value instanceof Polygon); + assertTrue(rectangle.equals((Geometry) value)); + } + iter.close(); + + // Check for null safeness + assertNull(exp.evaluate(null)); + } +} \ No newline at end of file |
From: <svn...@os...> - 2012-04-16 00:24:29
|
Author: aaime Date: 2012-04-15 17:24:22 -0700 (Sun, 15 Apr 2012) New Revision: 38669 Modified: branches/2.7.x/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function Log: [GEOT-3470] Minimum circle and rectangle Filter Functions, patch by Jared Erickson Modified: branches/2.7.x/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function =================================================================== --- branches/2.7.x/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function 2012-04-16 00:18:05 UTC (rev 38668) +++ branches/2.7.x/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function 2012-04-16 00:24:22 UTC (rev 38669) @@ -67,6 +67,8 @@ org.geotools.filter.function.FilterFunction_isRing org.geotools.filter.function.FilterFunction_exteriorRing org.geotools.filter.function.FilterFunction_numInteriorRing +org.geotools.filter.function.FilterFunction_minimumCircle +org.geotools.filter.function.FilterFunction_minimumRectangle org.geotools.filter.function.FilterFunction_interiorRingN org.geotools.filter.function.FilterFunction_strConcat org.geotools.filter.function.FilterFunction_strEndsWith |
Author: aaime Date: 2012-04-15 17:18:05 -0700 (Sun, 15 Apr 2012) New Revision: 38668 Added: trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumCircle.java trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumRectangle.java trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function Log: [GEOT-3470] Minimum circle and rectangle Filter Functions, patch by Jared Erickson Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumCircle.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumCircle.java 2012-04-16 00:06:18 UTC (rev 38667) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumCircle.java 2012-04-16 00:18:05 UTC (rev 38668) @@ -16,29 +16,23 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ +import org.geotools.filter.FunctionExpression; import org.geotools.filter.FunctionExpressionImpl; -import org.geotools.filter.capability.FunctionNameImpl; -import org.opengis.filter.capability.FunctionName; import com.vividsolutions.jts.geom.Geometry; /** * A FilterFunction that expects a Geometry and returns it's minimum bounding circle. * @author Jared Erickson - * - * - * @source $URL$ */ -public class FilterFunction_minimumCircle extends FunctionExpressionImpl { +public class FilterFunction_minimumCircle extends FunctionExpressionImpl implements + FunctionExpression { - public static FunctionName NAME = new FunctionNameImpl("mincircle","geometry"); - /** * Create a new FilterFunction_minimumCircle instance */ public FilterFunction_minimumCircle() { super("mincircle"); - functionName = NAME; } /** Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumRectangle.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumRectangle.java 2012-04-16 00:06:18 UTC (rev 38667) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/FilterFunction_minimumRectangle.java 2012-04-16 00:18:05 UTC (rev 38668) @@ -16,29 +16,23 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ +import org.geotools.filter.FunctionExpression; import org.geotools.filter.FunctionExpressionImpl; -import org.geotools.filter.capability.FunctionNameImpl; -import org.opengis.filter.capability.FunctionName; import com.vividsolutions.jts.geom.Geometry; /** * A FilterFunction that expects a Geometry and returns it's minimum rectangle. * @author Jared Erickson - * - * - * @source $URL$ */ -public class FilterFunction_minimumRectangle extends FunctionExpressionImpl { +public class FilterFunction_minimumRectangle extends FunctionExpressionImpl implements + FunctionExpression { - public static FunctionName NAME = new FunctionNameImpl("minrectangle","geometry"); - /** * Create a new FilterFunction_minimumRectangle instance */ public FilterFunction_minimumRectangle() { super("minrectangle"); - functionName = NAME; } /** @@ -60,7 +54,7 @@ // attempt to get value and perform conversion try { - arg0 = getExpression(0).evaluate(feature, Geometry.class); + arg0 = (Geometry) getExpression(0).evaluate(feature); } catch (Exception e) { // probably a type error throw new IllegalArgumentException( Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java 2012-04-16 00:06:18 UTC (rev 38667) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/StaticGeometry.java 2012-04-16 00:18:05 UTC (rev 38668) @@ -438,15 +438,15 @@ return _this.getInteriorRingN(arg1); } - static public Geometry minimumCircle(Geometry arg0) { - if (arg0 == null) return null; - MinimumBoundingCircle circle = new MinimumBoundingCircle(arg0); + static public Geometry minimumCircle(Geometry g) { + if (g == null) return null; + MinimumBoundingCircle circle = new MinimumBoundingCircle(g); return circle.getCircle(); } - static public Geometry minimumRectangle(Geometry arg0) { - if (arg0 == null) return null; - MinimumDiameter min = new MinimumDiameter(arg0); + static public Geometry minimumRectangle(Geometry g) { + if (g == null) return null; + MinimumDiameter min = new MinimumDiameter(g); return min.getMinimumRectangle(); } Modified: trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function =================================================================== --- trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function 2012-04-16 00:06:18 UTC (rev 38667) +++ trunk/modules/library/main/src/main/resources/META-INF/services/org.opengis.filter.expression.Function 2012-04-16 00:18:05 UTC (rev 38668) @@ -67,6 +67,8 @@ org.geotools.filter.function.FilterFunction_isRing org.geotools.filter.function.FilterFunction_exteriorRing org.geotools.filter.function.FilterFunction_numInteriorRing +org.geotools.filter.function.FilterFunction_minimumCircle +org.geotools.filter.function.FilterFunction_minimumRectangle org.geotools.filter.function.FilterFunction_interiorRingN org.geotools.filter.function.FilterFunction_strConcat org.geotools.filter.function.FilterFunction_strEndsWith Added: trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java (rev 0) +++ trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumCircleTest.java 2012-04-16 00:18:05 UTC (rev 38668) @@ -0,0 +1,86 @@ +package org.geotools.filter.function; + +import com.vividsolutions.jts.algorithm.MinimumBoundingCircle; +import static org.junit.Assert.*; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.io.WKTReader; +import org.geotools.data.DataUtilities; +import org.geotools.data.memory.MemoryDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.GeoTools; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.junit.Test; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.FilterFactory2; +import org.opengis.filter.expression.Function; + +/** + * The FilterFunction_minimumCircle UnitTest + * @author Jared Erickson + */ +public class FilterFunction_minimumCircleTest { + + /** + * Test of getArgCount method, of class FilterFunction_minimumCircle. + */ + @Test + public void testGetArgCount() { + FilterFunction_minimumCircle f = new FilterFunction_minimumCircle(); + assertEquals(1, f.getArgCount()); + } + + /** + * Test of getName method, of class FilterFunction_minimumCircle. + */ + @Test + public void getName() { + FilterFunction_minimumCircle f = new FilterFunction_minimumCircle(); + assertEquals("mincircle", f.getName()); + } + + /** + * Test of evaluate method, of class FilterFunction_minimumCircle. + */ + @Test + public void testEvaluate() throws Exception { + + // Create SimpleFeatures + SimpleFeatureType type = DataUtilities.createType("polygons", "id:int,geom:Polygon"); + MemoryDataStore store = new MemoryDataStore(); + store.createSchema(type); + String[] polygons = { + "POLYGON ((1235702.2034807256 707935.1879023351, 1229587.156498981 671715.2942412316, 1242287.6386918353 688649.2704983709, 1245109.9680680253 677359.9529936113, 1247932.297444215 711227.9055078899, 1239935.6975450104 705583.2467555101, 1235702.2034807256 707935.1879023351))", + "POLYGON ((1237113.3681688206 622324.5301579087, 1224883.274205331 586575.0247261701, 1258280.8384902447 589397.3541023601, 1237113.3681688206 622324.5301579087))", + "POLYGON ((1131746.4047910655 718754.1171777296, 1115282.8167632914 681593.4470578962, 1139272.6164609052 679241.5059110713, 1147269.2163601099 707935.1879023351, 1131746.4047910655 718754.1171777296)))" + }; + WKTReader reader = new WKTReader(); + SimpleFeature[] features = new SimpleFeature[polygons.length]; + for (int i = 0; i < polygons.length; i++) { + Geometry polygon = reader.read(polygons[i]); + features[i] = SimpleFeatureBuilder.build(type, new Object[]{i, polygon}, String.valueOf(i)); + } + store.addFeatures(features); + SimpleFeatureCollection featureCollection = store.getFeatureSource("polygons").getFeatures(); + + // Test the Function + FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); + Function exp = ff.function("mincircle", ff.property("geom")); + SimpleFeatureIterator iter = featureCollection.features(); + while (iter.hasNext()) { + SimpleFeature feature = iter.next(); + Geometry geom = (Geometry) feature.getDefaultGeometry(); + Geometry circle = new MinimumBoundingCircle(geom).getCircle(); + Object value = exp.evaluate(feature); + assertTrue(value instanceof Polygon); + assertTrue(circle.equals((Geometry) value)); + } + iter.close(); + + // Check for null safeness + assertNull(exp.evaluate(null)); + } +} Added: trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java (rev 0) +++ trunk/modules/library/main/src/test/java/org/geotools/filter/function/FilterFunction_minimumRectangleTest.java 2012-04-16 00:18:05 UTC (rev 38668) @@ -0,0 +1,86 @@ +package org.geotools.filter.function; + +import com.vividsolutions.jts.algorithm.MinimumDiameter; +import static org.junit.Assert.*; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.io.WKTReader; +import org.geotools.data.DataUtilities; +import org.geotools.data.memory.MemoryDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.GeoTools; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.junit.Test; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.FilterFactory2; +import org.opengis.filter.expression.Function; + +/** + * The FilterFunction_minimumRectangle UnitTest + * @author Jared Erickson + */ +public class FilterFunction_minimumRectangleTest { + + /** + * Test of getArgCount method, of class FilterFunction_minimumRectangle. + */ + @Test + public void testGetArgCount() { + FilterFunction_minimumRectangle f = new FilterFunction_minimumRectangle(); + assertEquals(1, f.getArgCount()); + } + + /** + * Test of getName method, of class FilterFunction_minimumRectangle. + */ + @Test + public void getName() { + FilterFunction_minimumRectangle f = new FilterFunction_minimumRectangle(); + assertEquals("minrectangle", f.getName()); + } + + /** + * Test of evaluate method, of class FilterFunction_minimumCircle. + */ + @Test + public void testEvaluate() throws Exception { + + // Create SimpleFeatures + SimpleFeatureType type = DataUtilities.createType("polygons", "id:int,geom:Polygon"); + MemoryDataStore store = new MemoryDataStore(); + store.createSchema(type); + String[] polygons = { + "POLYGON ((1235702.2034807256 707935.1879023351, 1229587.156498981 671715.2942412316, 1242287.6386918353 688649.2704983709, 1245109.9680680253 677359.9529936113, 1247932.297444215 711227.9055078899, 1239935.6975450104 705583.2467555101, 1235702.2034807256 707935.1879023351))", + "POLYGON ((1237113.3681688206 622324.5301579087, 1224883.274205331 586575.0247261701, 1258280.8384902447 589397.3541023601, 1237113.3681688206 622324.5301579087))", + "POLYGON ((1131746.4047910655 718754.1171777296, 1115282.8167632914 681593.4470578962, 1139272.6164609052 679241.5059110713, 1147269.2163601099 707935.1879023351, 1131746.4047910655 718754.1171777296)))" + }; + WKTReader reader = new WKTReader(); + SimpleFeature[] features = new SimpleFeature[polygons.length]; + for (int i = 0; i < polygons.length; i++) { + Geometry polygon = reader.read(polygons[i]); + features[i] = SimpleFeatureBuilder.build(type, new Object[]{i, polygon}, String.valueOf(i)); + } + store.addFeatures(features); + SimpleFeatureCollection featureCollection = store.getFeatureSource("polygons").getFeatures(); + + // Test the Function + FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()); + Function exp = ff.function("minrectangle", ff.property("geom")); + SimpleFeatureIterator iter = featureCollection.features(); + while (iter.hasNext()) { + SimpleFeature feature = iter.next(); + Geometry geom = (Geometry) feature.getDefaultGeometry(); + Geometry rectangle = new MinimumDiameter(geom).getMinimumRectangle(); + Object value = exp.evaluate(feature); + assertTrue(value instanceof Polygon); + assertTrue(rectangle.equals((Geometry) value)); + } + iter.close(); + + // Check for null safeness + assertNull(exp.evaluate(null)); + } +} \ No newline at end of file |
Author: aaime Date: 2012-04-15 17:06:18 -0700 (Sun, 15 Apr 2012) New Revision: 38667 Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties Modified: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java Log: [GEOT-4096] Contribute three LRS WPS processes, patch by David R Robison Modified: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java 2012-04-15 23:54:54 UTC (rev 38666) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -61,7 +61,10 @@ UnionFeatureCollection.class, UniqueProcess.class, VectorZonalStatistics.class, - TransformProcess.class); + TransformProcess.class, + LRSGeocodeProcess.class, + LRSMeasureProcess.class, + LRSSegmentProcess.class); } } Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSGeocodeProcess.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,193 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * 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.process.feature.gs; + +import java.util.logging.Logger; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.process.ProcessException; +import org.geotools.process.factory.DescribeParameter; +import org.geotools.process.factory.DescribeProcess; +import org.geotools.process.factory.DescribeResult; +import org.geotools.process.gs.GSProcess; +import org.geotools.util.logging.Logging; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.AttributeDescriptor; +import org.opengis.feature.type.FeatureType; +import org.opengis.feature.type.PropertyDescriptor; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.linearref.LengthIndexedLine; + +@DescribeProcess(title = "LRSGeocode", description = "Translate LRS measure to geocoded point") +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/NearestProcess.java $ + */ +public class LRSGeocodeProcess implements GSProcess { + private static final Logger LOGGER = Logging.getLogger(LRSGeocodeProcess.class); + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + /** + * Process the input data set. + * + * @param featureCollection the data set + * @param crs the CRS + * @param point the given point + * @return the snapped to feature + * @throws ProcessException error + */ + @DescribeResult(name = "result", description = "The geocoded point") + public FeatureCollection execute( + @DescribeParameter(name = "features", description = "The features to search") FeatureCollection featureCollection, + @DescribeParameter(name = "from_measure_attb", description = "The feature attribue holding the features starting measure") String fromMeasureAttb, + @DescribeParameter(name = "to_measure_attb", description = "The feature attribue holding the features ending measure") String toMeasureAttb, + @DescribeParameter(name = "measure", description = "The LRS measure") Double measure) + throws ProcessException { + FeatureCollection results = FeatureCollections.newCollection(); + try { + if (featureCollection == null || featureCollection.size() == 0) { + LOGGER.info("No features provided in request"); + return results; + } + if (fromMeasureAttb == null + || featureCollection.getSchema().getDescriptor(fromMeasureAttb) == null) { + throw new ProcessException( + "The from_measure_attb parameter was not provided or not defined in schema"); + } + if (toMeasureAttb == null + || featureCollection.getSchema().getDescriptor(toMeasureAttb) == null) { + throw new ProcessException("The to_measure_attb parameter was not provided"); + } + if (measure == null) { + throw new ProcessException("The measure parameter was not provided"); + } + SimpleFeatureType targetFeatureType = createTargetFeatureType(featureCollection + .getSchema()); + + FeatureIterator<Feature> featureIterator = null; + try { + featureIterator = featureCollection.features(); + Feature feature = featureIterator.next(); + Double featureFromMeasure = (Double) feature.getProperty(fromMeasureAttb) + .getValue(); + Double featureToMeasure = (Double) feature.getProperty(toMeasureAttb).getValue(); + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine((Geometry) feature + .getDefaultGeometryProperty().getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double startOffset = measure - featureFromMeasure; + double calcLength = ((Geometry) feature.getDefaultGeometryProperty().getValue()) + .getLength(); + if (calcLength == 0) { + LOGGER.info("Edge feature has zero length"); + return results; + } + if (featureLength == 0) { + LOGGER.info("Requested feature has zero length"); + return results; + } + Coordinate point = lengthIndexedLine.extractPoint(startOffset * calcLength + / featureLength); + results.add(createTargetFeature(feature, targetFeatureType, point)); + } finally { + if (featureIterator != null) + featureIterator.close(); + } + return results; + } catch (ProcessException e) { + throw e; + } catch (Throwable e) { + LOGGER.warning("Error executing method: " + e); + throw new ProcessException("Error executing method: " + e, e); + } + } + + /** + * Create the modified feature type. + * + * @param sourceFeatureType the source feature type + * @return the modified feature type + * @throws ProcessException errror + */ + private SimpleFeatureType createTargetFeatureType(FeatureType sourceFeatureType) + throws ProcessException { + try { + SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); + typeBuilder.setName(sourceFeatureType.getName().getLocalPart()); + typeBuilder.setNamespaceURI(sourceFeatureType.getName().getNamespaceURI()); + AttributeDescriptor geomAttbType = sourceFeatureType.getGeometryDescriptor(); + for (PropertyDescriptor attbType : sourceFeatureType.getDescriptors()) { + if (attbType.equals(geomAttbType)) { + typeBuilder.add(geomAttbType.getLocalName(), Point.class); + } else { + typeBuilder.add((AttributeDescriptor) attbType); + } + } + typeBuilder + .setDefaultGeometry(sourceFeatureType.getGeometryDescriptor().getLocalName()); + return typeBuilder.buildFeatureType(); + } catch (Exception e) { + LOGGER.warning("Error creating type: " + e); + throw new ProcessException("Error creating type: " + e, e); + } + } + + /** + * Create the modified feature. + * + * @param feature the source feature + * @param targetFeatureType the modified feature type + * @param nearestDistance the snap distance + * @param nearestBearing the snap bearing + * @return the modified feature + * @throws ProcessException error + */ + private SimpleFeature createTargetFeature(Feature feature, SimpleFeatureType targetFeatureType, + Coordinate geocodePoint) throws ProcessException { + try { + AttributeDescriptor geomAttbType = targetFeatureType.getGeometryDescriptor(); + Object[] attributes = new Object[targetFeatureType.getAttributeCount()]; + for (int i = 0; i < attributes.length; i++) { + AttributeDescriptor attbType = targetFeatureType.getAttributeDescriptors().get(i); + if (attbType.equals(geomAttbType)) { + Point point = geometryFactory.createPoint(geocodePoint); + point.setSRID(4326); + attributes[i] = point; + } else { + attributes[i] = feature.getProperty(attbType.getName()).getValue(); + } + } + return SimpleFeatureBuilder.build(targetFeatureType, attributes, feature + .getIdentifier().getID()); + } catch (Exception e) { + LOGGER.warning("Error creating feature: " + e); + throw new ProcessException("Error creating feature: " + e, e); + } + } +} Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSMeasureProcess.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,257 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * 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.process.feature.gs; + +import java.util.logging.Logger; + +import javax.measure.converter.UnitConverter; +import javax.measure.unit.SI; +import javax.measure.unit.Unit; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.measure.Measure; +import org.geotools.process.ProcessException; +import org.geotools.process.factory.DescribeParameter; +import org.geotools.process.factory.DescribeProcess; +import org.geotools.process.factory.DescribeResult; +import org.geotools.process.gs.GSProcess; +import org.geotools.referencing.CRS; +import org.geotools.referencing.crs.DefaultGeographicCRS; +import org.geotools.util.logging.Logging; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.AttributeDescriptor; +import org.opengis.feature.type.FeatureType; +import org.opengis.feature.type.GeometryDescriptor; +import org.opengis.feature.type.PropertyDescriptor; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.MathTransform; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.linearref.LengthIndexedLine; +import com.vividsolutions.jts.operation.distance.DistanceOp; + +@DescribeProcess(title = "LRSGeocode", description = "Translate geocoded point to LRS measure") +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/NearestProcess.java $ + */ +public class LRSMeasureProcess implements GSProcess { + private static final Logger LOGGER = Logging.getLogger(LRSMeasureProcess.class); + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + /** + * Process the input data set. + * + * @param featureCollection the data set + * @param crs the CRS + * @param point the given point + * @return the snapped to feature + * @throws ProcessException error + */ + @DescribeResult(name = "result", description = "The LRS measure") + public FeatureCollection execute( + @DescribeParameter(name = "features", description = "The features to search") FeatureCollection featureCollection, + @DescribeParameter(name = "from_measure_attb", description = "The feature attribue holding the features starting measure") String fromMeasureAttb, + @DescribeParameter(name = "to_measure_attb", description = "The feature attribue holding the features ending measure") String toMeasureAttb, + @DescribeParameter(name = "point", description = "The point to search from") Point point, + @DescribeParameter(name = "crs", min = 0, description = "The coordinate reference system of the collection and point (will use the collection one if not provided") CoordinateReferenceSystem crs) + throws ProcessException { + FeatureCollection results = FeatureCollections.newCollection(); + try { + if (featureCollection == null || featureCollection.size() == 0) { + LOGGER.info("No features provided in request"); + return results; + } + if (crs == null) { + GeometryDescriptor gd = featureCollection.getSchema().getGeometryDescriptor(); + if (gd != null) { + crs = gd.getCoordinateReferenceSystem(); + } + } + if (crs == null) { + throw new ProcessException( + "The CRS parameter was not provided and the feature collection does not have a default one either"); + } + if (fromMeasureAttb == null + || featureCollection.getSchema().getDescriptor(fromMeasureAttb) == null) { + throw new ProcessException( + "The from_measure_attb parameter was not provided or not defined in schema"); + } + if (toMeasureAttb == null + || featureCollection.getSchema().getDescriptor(toMeasureAttb) == null) { + throw new ProcessException("The to_measure_attb parameter was not provided"); + } + if (point == null) { + throw new ProcessException("The point parameter was not provided"); + } + + CoordinateReferenceSystem epsg4326; + try { + epsg4326 = CRS.decode("EPSG:4326"); + } catch (Exception e) { + throw new ProcessException("Unknown CRS code: EPSG:4326", e); + } + MathTransform crsTransform = CRS.findMathTransform(crs, epsg4326); + + FeatureType targetFeatureType = createTargetFeatureType(featureCollection.getSchema()); + Unit fromUnit = SI.METER; + Unit toUnit = Unit.valueOf("mi"); + UnitConverter unitConvert = fromUnit.getConverterTo(toUnit); + Feature nearestFeature = null; + double nearestDistance = 9e9; + Coordinate[] nearestCoords = null; + FeatureIterator<Feature> featureIterator = null; + try { + featureIterator = featureCollection.features(); + while (featureIterator.hasNext()) { + SimpleFeature f = (SimpleFeature) featureIterator.next(); + if (f.getDefaultGeometryProperty().getValue() == null) + continue; + DistanceOp op = new DistanceOp(point, (Geometry) f.getDefaultGeometryProperty() + .getValue()); + Coordinate[] co = op.closestPoints(); + double[] co0 = new double[] { co[0].x, co[0].y, }; + double[] co1 = new double[] { co[1].x, co[1].y, }; + double[] geo0 = new double[2]; + double[] geo1 = new double[2]; + crsTransform.transform(co0, 0, geo0, 0, 1); + crsTransform.transform(co1, 0, geo1, 0, 1); + + // get distance + Measure m = DefaultGeographicCRS.WGS84.distance(geo0, geo1); + if (m.doubleValue() > nearestDistance) + continue; + nearestFeature = f; + nearestDistance = m.doubleValue(); + nearestCoords = co; + } + } finally { + if (featureIterator != null) + featureIterator.close(); + } + if (nearestFeature != null) { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) nearestFeature.getDefaultGeometryProperty().getValue()); + double lineIndex = lengthIndexedLine.indexOf(nearestCoords[1]); + double lineLength = ((Geometry) nearestFeature.getDefaultGeometryProperty() + .getValue()).getLength(); + Double featureFromMeasure = (Double) nearestFeature.getProperty(fromMeasureAttb) + .getValue(); + Double featureToMeasure = (Double) nearestFeature.getProperty(toMeasureAttb) + .getValue(); + double lrsMeasure = featureFromMeasure + (featureToMeasure - featureFromMeasure) + * lineIndex / lineLength; + nearestFeature.getDefaultGeometryProperty().setValue( + geometryFactory.createPoint(new Coordinate(nearestCoords[1].x, + nearestCoords[1].y))); + results.add(createTargetFeature(nearestFeature, + (SimpleFeatureType) targetFeatureType, lrsMeasure)); + return results; + } + return results; + } catch (ProcessException e) { + throw e; + } catch (Throwable e) { + LOGGER.warning("Error executing method: " + e); + throw new ProcessException("Error executing method: " + e, e); + } + } + + /** + * Create the modified feature type. + * + * @param sourceFeatureType the source feature type + * @return the modified feature type + * @throws ProcessException errror + */ + private SimpleFeatureType createTargetFeatureType(FeatureType sourceFeatureType) + throws ProcessException { + try { + SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); + typeBuilder.setName(sourceFeatureType.getName().getLocalPart()); + typeBuilder.setNamespaceURI(sourceFeatureType.getName().getNamespaceURI()); + for (PropertyDescriptor attbType : sourceFeatureType.getDescriptors()) { + typeBuilder.add((AttributeDescriptor) attbType); + } + typeBuilder.minOccurs(1).maxOccurs(1).nillable(false).add("lrs_measure", Double.class); + typeBuilder + .setDefaultGeometry(sourceFeatureType.getGeometryDescriptor().getLocalName()); + return typeBuilder.buildFeatureType(); + } catch (Exception e) { + LOGGER.warning("Error creating type: " + e); + throw new ProcessException("Error creating type: " + e, e); + } + } + + /** + * Create the modified feature. + * + * @param feature the source feature + * @param targetFeatureType the modified feature type + * @param nearestDistance the snap distance + * @param nearestBearing the snap bearing + * @return the modified feature + * @throws ProcessException error + */ + private SimpleFeature createTargetFeature(Feature feature, SimpleFeatureType targetFeatureType, + Double lrsMeasure) throws ProcessException { + try { + AttributeDescriptor lrsMeasureAttbType = targetFeatureType.getDescriptor("lrs_measure"); + Object[] attributes = new Object[targetFeatureType.getAttributeCount()]; + for (int i = 0; i < attributes.length; i++) { + AttributeDescriptor attbType = targetFeatureType.getAttributeDescriptors().get(i); + if (attbType.equals(lrsMeasureAttbType)) { + attributes[i] = lrsMeasure; + } else { + attributes[i] = feature.getProperty(attbType.getName()).getValue(); + } + } + return SimpleFeatureBuilder.build(targetFeatureType, attributes, feature + .getIdentifier().getID()); + } catch (Exception e) { + LOGGER.warning("Error creating feature: " + e); + throw new ProcessException("Error creating feature: " + e, e); + } + } + + /** + * Calculate the bearing between two points. + * + * @param coords the points + * @return the bearing + */ + private double calcBearing(Coordinate[] coords) { + double y = Math.sin(coords[1].x - coords[0].x) * Math.cos(coords[1].y); + double x = Math.cos(coords[0].y) * Math.sin(coords[1].y) - Math.sin(coords[0].y) + * Math.cos(coords[1].y) * Math.cos(coords[1].x - coords[0].x); + double brng = ((Math.atan2(y, x) * 180.0 / Math.PI) + 360) % 360; + return brng; + } + +} Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/LRSSegmentProcess.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,226 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * 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.process.feature.gs; + +import java.util.logging.Logger; + +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.process.ProcessException; +import org.geotools.process.factory.DescribeParameter; +import org.geotools.process.factory.DescribeProcess; +import org.geotools.process.factory.DescribeResult; +import org.geotools.process.gs.GSProcess; +import org.geotools.util.logging.Logging; +import org.opengis.feature.Feature; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.AttributeDescriptor; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.LineString; +import com.vividsolutions.jts.geom.MultiLineString; +import com.vividsolutions.jts.linearref.LengthIndexedLine; +import com.vividsolutions.jts.operation.linemerge.LineMerger; + +@DescribeProcess(title = "LRSSegment", description = "Return a segment geometry for a LRM measure range") +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/NearestProcess.java $ + */ +public class LRSSegmentProcess implements GSProcess { + private static final Logger LOGGER = Logging.getLogger(LRSSegmentProcess.class); + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + /** + * Process the input data set. + * + * @param featureCollection the data set + * @param crs the CRS + * @param point the given point + * @return the snapped to feature + * @throws ProcessException error + */ + @DescribeResult(name = "result", description = "The segment geometry") + public FeatureCollection execute( + @DescribeParameter(name = "features", description = "The features to search") FeatureCollection featureCollection, + @DescribeParameter(name = "from_measure_attb", description = "The feature attribue holding the features starting measure") String fromMeasureAttb, + @DescribeParameter(name = "to_measure_attb", description = "The feature attribue holding the features ending measure") String toMeasureAttb, + @DescribeParameter(name = "from_measure", description = "The from LRS measure") Double fromMeasure, + @DescribeParameter(name = "to_measure", description = "The to LRS measure") Double toMeasure) + throws ProcessException { + FeatureCollection results = FeatureCollections.newCollection(); + try { + if (featureCollection == null || featureCollection.size() == 0) { + LOGGER.info("No features provided in request"); + return results; + } + if (fromMeasureAttb == null + || featureCollection.getSchema().getDescriptor(fromMeasureAttb) == null) { + throw new ProcessException( + "The from_measure_attb parameter was not provided or not defined in schema"); + } + if (toMeasureAttb == null + || featureCollection.getSchema().getDescriptor(toMeasureAttb) == null) { + throw new ProcessException("The to_measure_attb parameter was not provided"); + } + if (fromMeasure == null) { + throw new ProcessException("The from_measure parameter was not provided"); + } + if (toMeasure == null) { + throw new ProcessException("The to_measure parameter was not provided"); + } + if (fromMeasure.doubleValue() == toMeasure.doubleValue()) { + LOGGER.info("Zero length segment requested"); + return results; + } + + FeatureIterator<Feature> featureIterator = null; + Feature firstFeature = null; + try { + LineMerger lineMerger = new LineMerger(); + if (toMeasure.doubleValue() > fromMeasure.doubleValue()) { + featureIterator = featureCollection.features(); + while (featureIterator.hasNext()) { + Feature feature = featureIterator.next(); + if (firstFeature == null) + firstFeature = feature; + Double featureFromMeasure = (Double) feature.getProperty(fromMeasureAttb) + .getValue(); + Double featureToMeasure = (Double) feature.getProperty(toMeasureAttb) + .getValue(); + + if (fromMeasure < featureToMeasure && toMeasure > featureFromMeasure) { + try { + if (fromMeasure <= featureFromMeasure + && toMeasure >= featureToMeasure) { + lineMerger.add((Geometry) feature.getDefaultGeometryProperty() + .getValue()); + } else if (fromMeasure > featureFromMeasure + && toMeasure < featureToMeasure) { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) feature.getDefaultGeometryProperty() + .getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double startOffset = fromMeasure - featureFromMeasure; + double stopOffset = toMeasure - featureFromMeasure; + double calcLength = ((Geometry) feature + .getDefaultGeometryProperty().getValue()).getLength(); + if (calcLength == 0 || featureLength == 0) + continue; + Geometry extracted = lengthIndexedLine.extractLine(startOffset + * calcLength / featureLength, stopOffset * calcLength + / featureLength); + if (!extracted.isEmpty()) + lineMerger.add(extracted); + } else if (fromMeasure > featureFromMeasure) { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) feature.getDefaultGeometryProperty() + .getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double startOffset = fromMeasure - featureFromMeasure; + double calcLength = ((Geometry) feature + .getDefaultGeometryProperty().getValue()).getLength(); + if (calcLength == 0 || featureLength == 0) + continue; + Geometry extracted = lengthIndexedLine.extractLine(startOffset + * calcLength / featureLength, calcLength); + if (!extracted.isEmpty()) + lineMerger.add(extracted); + } else { + LengthIndexedLine lengthIndexedLine = new LengthIndexedLine( + (Geometry) feature.getDefaultGeometryProperty() + .getValue()); + double featureLength = featureToMeasure - featureFromMeasure; + double stopOffset = toMeasure - featureFromMeasure; + double calcLength = ((Geometry) feature + .getDefaultGeometryProperty().getValue()).getLength(); + if (calcLength == 0 || featureLength == 0) + continue; + Geometry extracted = lengthIndexedLine.extractLine(0, + stopOffset * calcLength / featureLength); + if (extracted.isEmpty() || extracted.getLength() == 0.0) { + LOGGER.info("Empty segment: featureFromMeasure=" + + featureFromMeasure + " featureToMeasure:" + + featureToMeasure + " toMeasure:" + toMeasure + + " fromMeasure:" + fromMeasure); + } else { + lineMerger.add(extracted); + } + } + } catch (Exception e) { + LOGGER.warning("Error merging line strings: " + e + + " featureFromMeasure=" + featureFromMeasure + + " featureToMeasure:" + featureToMeasure + " toMeasure:" + + toMeasure + " fromMeasure:" + fromMeasure); + } + } + } + results.add(createTargetFeature(firstFeature, (SimpleFeatureType) firstFeature + .getType(), new MultiLineString((LineString[]) lineMerger + .getMergedLineStrings().toArray(new LineString[0]), geometryFactory))); + } + } finally { + if (featureIterator != null) + featureIterator.close(); + } + return results; + } catch (ProcessException e) { + throw e; + } catch (Throwable e) { + LOGGER.warning("Error executing method: " + e); + throw new ProcessException("Error executing method: " + e, e); + } + } + + /** + * Create the modified feature. + * + * @param feature the source feature + * @param targetFeatureType the modified feature type + * @param nearestDistance the snap distance + * @param nearestBearing the snap bearing + * @return the modified feature + * @throws ProcessException error + */ + private SimpleFeature createTargetFeature(Feature feature, SimpleFeatureType targetFeatureType, + MultiLineString multiLineString) throws ProcessException { + try { + AttributeDescriptor geomAttbType = targetFeatureType.getGeometryDescriptor(); + Object[] attributes = new Object[targetFeatureType.getAttributeCount()]; + for (int i = 0; i < attributes.length; i++) { + AttributeDescriptor attbType = targetFeatureType.getAttributeDescriptors().get(i); + if (attbType.equals(geomAttbType)) { + attributes[i] = multiLineString; + } else { + attributes[i] = feature.getProperty(attbType.getName()).getValue(); + } + } + return SimpleFeatureBuilder.build(targetFeatureType, attributes, feature + .getIdentifier().getID()); + } catch (Exception e) { + LOGGER.warning("Error creating feature: " + e); + throw new ProcessException("Error creating feature: " + e, e); + } + } +} Added: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSGeocodeProcessTest.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,150 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2012, 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.process.feature.gs; + +import java.io.File; +import java.io.IOException; + +import org.geotools.data.DataStore; +import org.geotools.data.property.PropertyDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.process.ProcessException; +import org.geotools.test.TestData; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.Feature; + +import com.vividsolutions.jts.geom.Point; + +/** + * + * + * @source $URL$ + */ +public class LRSGeocodeProcessTest { + private DataStore featureSource; + + @Before + public void setup() throws IOException { + File file = TestData.file(this, null); + featureSource = new PropertyDataStore(file); + } + + @After + public void tearDown() { + featureSource.dispose(); + } + + @Test + public void testBadParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs_bad", "to_lrs", 1.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", 1.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testnullParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, null, "to_lrs", 1.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNullParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", null, 1.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", null); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNoFeaturesGiven() throws Exception { + LRSGeocodeProcess process = new LRSGeocodeProcess(); + FeatureCollection origional = FeatureCollections.newCollection(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 1.0); + Assert.assertEquals(0, result.size()); + } + + @Test + public void testGoodGeocode() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSGeocodeProcess process = new LRSGeocodeProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 1.0); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + Point point = (Point) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(1.0, point.getX(), 0.0); + Assert.assertEquals(0.0, point.getY(), 0.0); + } + +} Added: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSMeasureProcessTest.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,164 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2012, 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.process.feature.gs; + +import java.io.File; +import java.io.IOException; + +import org.geotools.data.DataStore; +import org.geotools.data.property.PropertyDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.process.ProcessException; +import org.geotools.test.TestData; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.Feature; + +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; + +/** + * + * + * @source $URL$ + */ +public class LRSMeasureProcessTest { + private DataStore featureSource; + + private final GeometryFactory geometryFactory = new GeometryFactory(); + + @Before + public void setup() throws IOException { + File file = TestData.file(this, null); + featureSource = new PropertyDataStore(file); + } + + @After + public void tearDown() { + featureSource.dispose(); + } + + @Test + public void testBadParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, "from_lrs_bad", "to_lrs", point, + null); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", point, + null); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testnullParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, null, "to_lrs", point, null); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNullParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", null, point, null); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadPoint() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", null, + null); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNoFeaturesGiven() throws Exception { + LRSMeasureProcess process = new LRSMeasureProcess(); + FeatureCollection origional = FeatureCollections.newCollection(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", point, null); + Assert.assertEquals(0, result.size()); + } + + @Test + public void testGoodMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSMeasureProcess process = new LRSMeasureProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + Point point = geometryFactory.createPoint(new Coordinate(1.0, 0.0)); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", point, null); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + Assert.assertNotNull(feature.getProperty("lrs_measure")); + Assert.assertNotNull(feature.getProperty("lrs_measure").getValue()); + Double measure = (Double) feature.getProperty("lrs_measure").getValue(); + Assert.assertEquals(1.0, measure, 0.0); + } + +} Added: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/LRSSegmentProcessTest.java 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,205 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2012, 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.process.feature.gs; + +import java.io.File; +import java.io.IOException; + +import org.geotools.data.DataStore; +import org.geotools.data.property.PropertyDataStore; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureCollections; +import org.geotools.process.ProcessException; +import org.geotools.test.TestData; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.Feature; + +import com.vividsolutions.jts.geom.MultiLineString; + +/** + * + * + * @source $URL$ + */ +public class LRSSegmentProcessTest { + private DataStore featureSource; + + @Before + public void setup() throws IOException { + File file = TestData.file(this, null); + featureSource = new PropertyDataStore(file); + } + + @After + public void tearDown() { + featureSource.dispose(); + } + + @Test + public void testBadParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs_bad", "to_lrs", 1.0, + 2.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", 1.0, + 2.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testnullParamFromLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, null, "to_lrs", 1.0, 2.0); + Assert.fail("Expected error from bad from_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNullParamToLrs() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", null, 1.0, 2.0); + Assert.fail("Expected error from bad to_lrs name"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadFromMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", null, + 2.0); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testBadToMeasure() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + try { + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs_bad", 1.0, + null); + Assert.fail("Expected error from bad measure value"); + } catch (ProcessException e) { + // Successful + } + } + + @Test + public void testNoFeaturesGiven() throws Exception { + LRSSegmentProcess process = new LRSSegmentProcess(); + FeatureCollection origional = FeatureCollections.newCollection(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 1.0, 2.0); + Assert.assertEquals(0, result.size()); + } + + @Test + public void testSegmentInOneFeature() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 0.5, 1.5); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + MultiLineString segment = (MultiLineString) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(2, segment.getNumPoints()); + Assert.assertEquals(0.5, segment.getCoordinates()[0].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[0].y, 0.0); + Assert.assertEquals(1.5, segment.getCoordinates()[1].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[1].y, 0.0); + } + + @Test + public void testSegmentInTwoFeature() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 0.5, 3.5); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + MultiLineString segment = (MultiLineString) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(3, segment.getNumPoints()); + Assert.assertEquals(0.5, segment.getCoordinates()[0].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[0].y, 0.0); + Assert.assertEquals(3.5, segment.getCoordinates()[2].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[2].y, 0.0); + } + + @Test + public void testSegmentInThreeFeature() throws Exception { + SimpleFeatureSource source = featureSource.getFeatureSource("lrssimple"); + LRSSegmentProcess process = new LRSSegmentProcess(); + SimpleFeatureCollection origional = source.getFeatures(); + + FeatureCollection result = process.execute(origional, "from_lrs", "to_lrs", 0.5, 5.5); + Assert.assertEquals(1, result.size()); + Feature feature = result.features().next(); + MultiLineString segment = (MultiLineString) feature.getDefaultGeometryProperty().getValue(); + Assert.assertEquals(4, segment.getNumPoints()); + Assert.assertEquals(0.5, segment.getCoordinates()[0].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[0].y, 0.0); + Assert.assertEquals(5.5, segment.getCoordinates()[3].x, 0.0); + Assert.assertEquals(0.0, segment.getCoordinates()[3].y, 0.0); + } + +} Added: trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties =================================================================== --- trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/resources/org/geotools/process/feature/gs/test-data/lrssimple.properties 2012-04-16 00:06:18 UTC (rev 38667) @@ -0,0 +1,4 @@ +_=the_geom:MultiLineString:srid=4326,from_lrs:java.lang.Double,to_lrs:java.lang.Double,str1:String +lrssimple.1=MULTILINESTRING ((0 0, 2 0))|0.0|2.0|lrs a +lrssimple.2=MULTILINESTRING ((2 0, 4 0))|2.0|4.0|lrs b +lrssimple.3=MULTILINESTRING ((4 0, 6 0))|4.0|6.0|lrs c |
From: <svn...@os...> - 2012-04-15 23:55:02
|
Author: aaime Date: 2012-04-15 16:54:54 -0700 (Sun, 15 Apr 2012) New Revision: 38666 Modified: trunk/modules/library/main/src/main/java/org/geotools/styling/SLDTransformer.java trunk/modules/library/main/src/test/java/org/geotools/styling/SLDTransformerTest.java Log: [GEOT-4075] Rendering Transforms are not encoded in SLD Modified: trunk/modules/library/main/src/main/java/org/geotools/styling/SLDTransformer.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/styling/SLDTransformer.java 2012-04-15 22:53:28 UTC (rev 38665) +++ trunk/modules/library/main/src/main/java/org/geotools/styling/SLDTransformer.java 2012-04-15 23:54:54 UTC (rev 38666) @@ -993,6 +993,10 @@ if ((fts.featureTypeNames() != null) && (fts.featureTypeNames().size() > 0)) { element("FeatureTypeName", fts.featureTypeNames().iterator().next().toString()); } + + if (fts.getTransformation() != null) { + element("Transformation", fts.getTransformation()); + } String[] sti = fts.getSemanticTypeIdentifiers(); Modified: trunk/modules/library/main/src/test/java/org/geotools/styling/SLDTransformerTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/styling/SLDTransformerTest.java 2012-04-15 22:53:28 UTC (rev 38665) +++ trunk/modules/library/main/src/test/java/org/geotools/styling/SLDTransformerTest.java 2012-04-15 23:54:54 UTC (rev 38666) @@ -27,6 +27,7 @@ import java.awt.Color; import java.io.IOException; import java.io.StringReader; +import java.io.StringWriter; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -997,4 +998,60 @@ // compare assertEquals("Perpendicular offset of LineSymbolizer has not been correctly ex- and reimported",ls.getPerpendicularOffset(),copy.getPerpendicularOffset()); } + + + /** + * Make sure the FeatureTypeStyle Transformation element survives a SLD to Style to SLD round + * trip. + * + * @throws Exception if an error occurs + */ + @Test + public void testFeatureTypeStyleTransformation() throws Exception { + + String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + + "<sld:UserStyle xmlns=\"http://www.opengis.net/sld\" " + + " xmlns:sld=\"http://www.opengis.net/sld\" " + + " xmlns:ogc=\"http://www.opengis.net/ogc\" " + + " xmlns:gml=\"http://www.opengis.net/gml\">" + + " <sld:Name>Default Styler</sld:Name>" + + " <sld:Title/>" + + " <sld:FeatureTypeStyle>" + + " <sld:Name>Buffer</sld:Name>" + + " <sld:Transformation>" + + " <ogc:Function name=\"buffer\">" + + " <ogc:PropertyName>the_geom</ogc:PropertyName>" + + " <ogc:Literal>500</ogc:Literal>" + + " </ogc:Function>" + + " </sld:Transformation>" + + " <sld:Rule>" + + " <sld:LineSymbolizer>" + + " <sld:Stroke>" + + " <sld:CssParameter name=\"stroke\">#312624</sld:CssParameter>" + + " <sld:CssParameter name=\"stroke-width\">0.1</sld:CssParameter>" + + " </sld:Stroke>" + " </sld:LineSymbolizer>" + + " <sld:PolygonSymbolizer>" + " <sld:Fill>" + + " <sld:CssParameter name=\"fill\">#f5deb3</sld:CssParameter>" + + " </sld:Fill>" + " </sld:PolygonSymbolizer>" + + " </sld:Rule>" + " </sld:FeatureTypeStyle>" + "</sld:UserStyle>"; + + StringReader reader = new StringReader(xml); + SLDParser sldParser = new SLDParser(sf, reader); + + Style[] styles = sldParser.readXML(); + assertNotNull("parsed xml", styles); + assertTrue("parsed xml into style", styles.length > 0); + + SLDTransformer styleTransform = new SLDTransformer(); + styleTransform.setIndentation(2); + StringWriter writer = new StringWriter(); + styleTransform.transform(styles[0], writer); + String actualXml = writer.toString(); + assertTrue(actualXml.contains("<sld:Transformation>")); + assertTrue(actualXml.contains("<ogc:Function name=\"buffer\">")); + assertTrue(actualXml.contains("<ogc:PropertyName>the_geom</ogc:PropertyName>")); + assertTrue(actualXml.contains("<ogc:Literal>500</ogc:Literal>")); + assertTrue(actualXml.contains("</ogc:Function>")); + assertTrue(actualXml.contains("</sld:Transformation>")); + } } |
Author: jdeolive Date: 2012-04-15 15:53:28 -0700 (Sun, 15 Apr 2012) New Revision: 38665 Modified: trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GML2ParsingUtils.java trunk/modules/unsupported/geojson/src/main/java/org/geotools/geojson/feature/FeatureHandler.java Log: explicitly setting null crs on feature type schema builder to avoid extensive warnings when creating feature type with no crs Modified: trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GML2ParsingUtils.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GML2ParsingUtils.java 2012-04-15 22:53:17 UTC (rev 38664) +++ trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GML2ParsingUtils.java 2012-04-15 22:53:28 UTC (rev 38665) @@ -173,7 +173,7 @@ SimpleFeatureTypeBuilder ftBuilder = new SimpleFeatureTypeBuilder(); ftBuilder.setName(node.getComponent().getName()); ftBuilder.setNamespaceURI(node.getComponent().getNamespace()); - + ftBuilder.setCRS(null); //JD: set explicitly to null to avoid warning //mandatory gml attributes if (!node.hasChild("description")) { ftBuilder.add("description", String.class); Modified: trunk/modules/unsupported/geojson/src/main/java/org/geotools/geojson/feature/FeatureHandler.java =================================================================== --- trunk/modules/unsupported/geojson/src/main/java/org/geotools/geojson/feature/FeatureHandler.java 2012-04-15 22:53:17 UTC (rev 38664) +++ trunk/modules/unsupported/geojson/src/main/java/org/geotools/geojson/feature/FeatureHandler.java 2012-04-15 22:53:28 UTC (rev 38665) @@ -208,9 +208,7 @@ SimpleFeatureTypeBuilder typeBuilder = new SimpleFeatureTypeBuilder(); typeBuilder.setName("feature"); typeBuilder.setNamespaceURI("http://geotools.org"); - if (crs != null) { - typeBuilder.setCRS(crs); - } + typeBuilder.setCRS(crs); if (properties != null) { for (int i = 0; i < properties.size(); i++) { |
From: <svn...@os...> - 2012-04-15 22:53:24
|
Author: jdeolive Date: 2012-04-15 15:53:17 -0700 (Sun, 15 Apr 2012) New Revision: 38664 Modified: trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GMLEncodingUtils.java Log: decreasing log level from warning to info for case of encoding feature type when none can be found in schema Modified: trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GMLEncodingUtils.java =================================================================== --- trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GMLEncodingUtils.java 2012-04-15 22:29:46 UTC (rev 38663) +++ trunk/modules/extension/xsd/xsd-gml2/src/main/java/org/geotools/gml2/bindings/GMLEncodingUtils.java 2012-04-15 22:53:17 UTC (rev 38664) @@ -111,7 +111,7 @@ if (type == null) { if (featureType instanceof SimpleFeatureType) { // could not find the feature type in the schema, create a mock one - LOGGER.warning("Could find type for " + typeName + LOGGER.fine("Could find type for " + typeName + " in the schema, generating type from feature."); type = createXmlTypeFromFeatureType((SimpleFeatureType) featureType, schemaIndex, toFilter); |
From: <svn...@os...> - 2012-04-15 22:29:55
|
Author: aaime Date: 2012-04-15 15:29:46 -0700 (Sun, 15 Apr 2012) New Revision: 38663 Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/CentroidProcess.java trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/ProcessingCollection.java trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/SimpleProcessingCollection.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/CentroidProcessTest.java Modified: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/BufferFeatureCollection.java trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/BufferFeatureCollectionTest.java Log: [GEOT-3948] New WPS process: org.geotools.process.features.gs.CentroidProcess by Rohan Singh, plus some base class improvements and tests by yours truly Modified: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/BufferFeatureCollection.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/BufferFeatureCollection.java 2012-04-12 14:29:44 UTC (rev 38662) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/BufferFeatureCollection.java 2012-04-15 22:29:46 UTC (rev 38663) @@ -32,6 +32,7 @@ import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.feature.type.GeometryTypeImpl; +import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.util.Converters; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; @@ -86,20 +87,43 @@ /** * Wrapper that will trigger the buffer computation as features are requested */ - static class BufferedFeatureCollection extends DecoratingSimpleFeatureCollection { + static class BufferedFeatureCollection extends SimpleProcessingCollection { Double distance; String attribute; + + SimpleFeatureCollection delegate; - SimpleFeatureType schema; - public BufferedFeatureCollection(SimpleFeatureCollection delegate, String attribute, Double distance) { - super(delegate); this.distance = distance; this.attribute = attribute; + this.delegate = delegate; + + } + + @Override + public SimpleFeatureIterator features() { + return new BufferedFeatureIterator(delegate, this.attribute, this.distance, getSchema()); + } + + @Override + public ReferencedEnvelope getBounds() { + if(attribute == null) { + // in this case we just have to expand the original collection bounds + ReferencedEnvelope re = delegate.getBounds(); + re.expandBy(distance); + return re; + } else { + // unlucky case, we need to actually compute by hand... + return getFeatureBounds(); + } + } + + @Override + protected SimpleFeatureType buildTargetFeatureType() { // create schema SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); for (AttributeDescriptor descriptor : delegate.getSchema().getAttributeDescriptors()) { @@ -120,30 +144,15 @@ tb.setDescription(delegate.getSchema().getDescription()); tb.setCRS(delegate.getSchema().getCoordinateReferenceSystem()); tb.setName(delegate.getSchema().getName()); - this.schema = tb.buildFeatureType(); + return tb.buildFeatureType(); } @Override - public SimpleFeatureIterator features() { - return new BufferedFeatureIterator(delegate, this.attribute, this.distance, getSchema()); + public int size() { + return delegate.size(); } - @Override - public Iterator<SimpleFeature> iterator() { - return new WrappingIterator(features()); - } - - @Override - public void close(Iterator<SimpleFeature> close) { - if (close instanceof WrappingIterator) { - ((WrappingIterator) close).close(); - } - } - - @Override - public SimpleFeatureType getSchema() { - return this.schema; - } + } /** Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/CentroidProcess.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/CentroidProcess.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/CentroidProcess.java 2012-04-15 22:29:46 UTC (rev 38663) @@ -0,0 +1,137 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * 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.process.feature.gs; + +import java.util.NoSuchElementException; + +import org.geotools.data.DataUtilities; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.process.ProcessException; +import org.geotools.process.factory.DescribeParameter; +import org.geotools.process.factory.DescribeProcess; +import org.geotools.process.factory.DescribeResult; +import org.geotools.process.gs.GSProcess; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.AttributeDescriptor; +import org.opengis.feature.type.GeometryDescriptor; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.Point; + +/** + * A process that returns the centroids for the geometries in the + * input feature collection. + * + * @author Rohan Singh + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/CentroidProcess.java $ + */ +@DescribeProcess(title = "centroid", description = "Returns centroids of the geometries in the feature collection") +public class CentroidProcess implements GSProcess { + + @DescribeResult(name = "result", description = "The feature collection with centroids") + public SimpleFeatureCollection execute( + @DescribeParameter(name = "features", description = "The feature collection to get centroids for") SimpleFeatureCollection features) + throws ProcessException { + return DataUtilities.simple(new CentroidFeatureCollection(features)); + } + + static class CentroidFeatureCollection extends SimpleProcessingCollection { + SimpleFeatureCollection delegate; + + public CentroidFeatureCollection(SimpleFeatureCollection delegate) { + this.delegate = delegate; + } + + @Override + public SimpleFeatureIterator features() { + return new CentroidFeatureIterator(delegate.features(), getSchema()); + } + + @Override + public ReferencedEnvelope getBounds() { + return getFeatureBounds(); + } + + @Override + protected SimpleFeatureType buildTargetFeatureType() { + SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); + for (AttributeDescriptor ad : delegate.getSchema().getAttributeDescriptors()) { + if(ad instanceof GeometryDescriptor) { + GeometryDescriptor gd = (GeometryDescriptor) ad; + Class<?> binding = ad.getType().getBinding(); + if(Point.class.isAssignableFrom(binding)) { + tb.add(ad); + } else { + tb.minOccurs(ad.getMinOccurs()); + tb.maxOccurs(ad.getMaxOccurs()); + tb.nillable(ad.isNillable()); + tb.add(ad.getLocalName(), Point.class, gd.getCoordinateReferenceSystem()); + } + } else { + tb.add(ad); + } + } + tb.setName(delegate.getSchema().getName()); + return tb.buildFeatureType(); + } + + @Override + public int size() { + return delegate.size(); + } + } + + static class CentroidFeatureIterator implements SimpleFeatureIterator { + SimpleFeatureIterator delegate; + + SimpleFeatureBuilder fb; + + public CentroidFeatureIterator(SimpleFeatureIterator delegate, SimpleFeatureType schema) { + this.delegate = delegate; + fb = new SimpleFeatureBuilder(schema); + } + + public void close() { + delegate.close(); + } + + public boolean hasNext() { + return delegate.hasNext(); + } + + public SimpleFeature next() throws NoSuchElementException { + SimpleFeature f = delegate.next(); + for (Object attribute : f.getAttributes()) { + if ((attribute instanceof Geometry) && + !(attribute instanceof Point)) { + attribute = ((Geometry) attribute).getCentroid(); + } + fb.add(attribute); + } + return fb.buildFeature(f.getID()); + } + + } +} Modified: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java 2012-04-12 14:29:44 UTC (rev 38662) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/FeatureGSProcessFactory.java 2012-04-15 22:29:46 UTC (rev 38663) @@ -5,6 +5,7 @@ import org.geotools.process.feature.gs.AggregateProcess; import org.geotools.process.feature.gs.BoundsProcess; import org.geotools.process.feature.gs.BufferFeatureCollection; +import org.geotools.process.feature.gs.CentroidProcess; import org.geotools.process.feature.gs.ClipProcess; import org.geotools.process.feature.gs.CollectGeometries; import org.geotools.process.feature.gs.CountProcess; @@ -42,6 +43,7 @@ AggregateProcess.class, BoundsProcess.class, BufferFeatureCollection.class, + CentroidProcess.class, ClipProcess.class, CollectGeometries.class, CountProcess.class, Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/ProcessingCollection.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/ProcessingCollection.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/ProcessingCollection.java 2012-04-15 22:29:46 UTC (rev 38663) @@ -0,0 +1,434 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * 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.process.feature.gs; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.UUID; + +import org.geotools.data.DataUtilities; +import org.geotools.data.store.FilteringFeatureCollection; +import org.geotools.feature.CollectionListener; +import org.geotools.feature.FeatureCollection; +import org.geotools.feature.FeatureIterator; +import org.geotools.feature.collection.SortedSimpleFeatureCollection; +import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.util.NullProgressListener; +import org.opengis.feature.Feature; +import org.opengis.feature.FeatureVisitor; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.feature.type.FeatureType; +import org.opengis.filter.Filter; +import org.opengis.filter.sort.SortBy; +import org.opengis.util.ProgressListener; + +/** + * Abstract base class to ease the implementation of a streaming processing collection, that is, one + * that tries to compute the results on the fly as the iterator is traversed. + * + * Besides the few methods that the implementor actually needs to override it suggested to consider + * overriding also the followings to get extra performance gains: + * <ul> + * {@link #subCollection(Filter)} {@link #sort(SortBy)} + * </ul> + * + * @author Andrea Aime - GeoSolutions + * + * @param <T> + * @param <F> + */ +public abstract class ProcessingCollection<T extends FeatureType, F extends Feature> + implements FeatureCollection<T, F> { + + private static final String READ_ONLY_ERROR = "This collection is read only"; + + private T schema; + + private String id; + + public ProcessingCollection() { + id = getClass().getSimpleName() + "-" + UUID.randomUUID().toString(); + } + + /** + * Streams out the output features + */ + @Override + public abstract FeatureIterator<F> features(); + + @Override + public void accepts(FeatureVisitor visitor, ProgressListener progress) throws IOException { + FeatureIterator<F> iterator = null; + float size = progress != null ? size() : 0; + if (progress == null) { + progress = new NullProgressListener(); + } + try { + float position = 0; + progress.started(); + iterator = features(); + while (iterator.hasNext()) { + try { + F feature = iterator.next(); + visitor.visit(feature); + if (size > 0) { + progress.progress(position++ / size); + } + } catch (Exception erp) { + progress.exceptionOccurred(erp); + throw new IOException("Error occurred while iterating over features", erp); + } + } + } finally { + progress.complete(); + close(iterator); + } + + } + + /** + * Convenience implementation that just wraps this collection into a + * {@link FilteringFeatureCollection}. Subclasses might want to override this in case the filter + * can be cascaded to their data sources. + * + * @param filter + * @return + */ + @Override + public FeatureCollection<T, F> subCollection(Filter filter) { + return new FilteringFeatureCollection<T, F>(this, filter); + } + + /** + * Convenience implementation that + */ + @Override + public FeatureCollection<T, F> sort(SortBy order) { + if (schema instanceof SimpleFeatureType) { + // go for the most efficient way if possible, otherwise rely on pure in memory + // sorting... + return (FeatureCollection<T, F>) new SortedSimpleFeatureCollection( + DataUtilities + .simple((FeatureCollection<SimpleFeatureType, SimpleFeature>) this), + new SortBy[] { order }); + } else { + // hmm... we don't even have a basic non simple collection... need to implement one + // before + // going here + throw new UnsupportedOperationException("Cannot sort on complex features at the moment"); + } + } + + /** + * The bounds of features in the output. If the bounds are not known in advance once can call the + * getFeatureBounds() which will build it from the features as they are returned from the feature + * iterator. + */ + @Override + public abstract ReferencedEnvelope getBounds(); + + @Override + public Iterator<F> iterator() { + final FeatureIterator<F> features = features(); + if (features == null) { + return null; + } else { + return new WrappingIterator(features); + } + } + + /** + * Builds once and for all the target feature type. The results are available by calling getSchema() + * + * @return + */ + protected abstract T buildTargetFeatureType(); + + /** + * The number of features in the output. If the size is not known in advance once can call the + * getFeatureCount() which will count the features as they are returned from the feature + * iterator. + */ + @Override + public abstract int size(); + + /** + * Convenience method that counts features by traversing the feature iterator. + * + * @return + */ + protected int getFeatureCount() { + FeatureIterator<F> fi = null; + try { + fi = features(); + int count = 0; + while (fi.hasNext()) { + fi.next(); + count++; + } + return count; + } finally { + close(fi); + } + } + + /** + * Convenience method that computes the feature bounds by traversing the feature iterator. + * + * @return + */ + protected ReferencedEnvelope getFeatureBounds() { + FeatureIterator<F> fi = null; + try { + fi = features(); + ReferencedEnvelope bounds = null; + while (fi.hasNext()) { + F feature = fi.next(); + ReferencedEnvelope featureEnvelope = null; + if(feature != null && feature.getBounds() != null) { + featureEnvelope = ReferencedEnvelope.reference(feature.getBounds()); + } + + if(featureEnvelope != null) { + if(bounds == null) { + bounds = new ReferencedEnvelope(featureEnvelope); + } else { + bounds.expandToInclude(featureEnvelope); + } + } + } + + return bounds; + } finally { + close(fi); + } + } + + @Override + public void close(FeatureIterator<F> fi) { + if (fi != null) { + fi.close(); + } + } + + @Override + public void close(Iterator<F> close) { + if (close instanceof WrappingIterator) { + ((WrappingIterator) close).close(); + } + } + + /** + * An implementation that actually does not attach the listener, since the collection is not + * modifiable. Subclasses might want to override this. + */ + @Override + public void addListener(CollectionListener listener) throws NullPointerException { + // we just don't implement this, contents of the collection might be generated + // out of thin air and cannot be changed normally, subclasses may want to override + } + + @Override + public void removeListener(CollectionListener listener) throws NullPointerException { + // we just don't implement this, contents of the collection might be generated + // out of thin air and cannot be changed normally, subclasses may want to override + } + + @Override + public T getSchema() { + if(schema == null) { + schema = buildTargetFeatureType(); + } + + return schema; + } + + @Override + public String getID() { + return id; + } + + /** + * Empty as the collection is supposed to be empty anyways, but subclasses might want to + * override the method to get rid of whatever state they might be holding onto. + */ + @Override + public void purge() { + // nothing to do here + } + + @Override + public boolean add(F obj) { + throw new UnsupportedOperationException(READ_ONLY_ERROR); + } + + @Override + public boolean addAll(Collection<? extends F> collection) { + throw new UnsupportedOperationException(READ_ONLY_ERROR); + } + + @Override + public boolean addAll(FeatureCollection<? extends T, ? extends F> resource) { + throw new UnsupportedOperationException(READ_ONLY_ERROR); + } + + @Override + public void clear() { + throw new UnsupportedOperationException(READ_ONLY_ERROR); + } + + /** + * Returns <tt>true</tt> if this collection contains the specified element. <tt></tt>. + * <p> + * + * This implementation iterates over the elements in the collection, checking each element in + * turn for equality with the specified element. + * + * @param o object to be checked for containment in this collection. + * @return <tt>true</tt> if this collection contains the specified element. + */ + public boolean contains(Object o) { + Iterator<F> e = null; + try { + e = iterator(); + if (o == null) { + while (e.hasNext()) + if (e.next() == null) + return true; + } else { + while (e.hasNext()) + if (o.equals(e.next())) + return true; + } + return false; + } finally { + close(e); + } + } + + /** + * Returns <tt>true</tt> if this collection contains all of the elements in the specified + * collection. + * <p> + * + * @param c collection to be checked for containment in this collection. + * @return <tt>true</tt> if this collection contains all of the elements in the specified + * collection. + * @throws NullPointerException if the specified collection is null. + * + * @see #contains(Object) + */ + public boolean containsAll(Collection<?> c) { + Iterator<?> e = c.iterator(); + try { + while (e.hasNext()) + if (!contains(e.next())) + return false; + return true; + } finally { + if (c instanceof FeatureCollection) { + ((FeatureCollection) c).close(e); + } + } + } + + @Override + public boolean isEmpty() { + FeatureIterator<F> fi = null; + try { + fi = features(); + return !fi.hasNext(); + } finally { + close(fi); + } + } + + @Override + public boolean remove(Object o) { + throw new UnsupportedOperationException(READ_ONLY_ERROR); + } + + @Override + public boolean removeAll(Collection<?> c) { + throw new UnsupportedOperationException(READ_ONLY_ERROR); + } + + @Override + public boolean retainAll(Collection<?> c) { + throw new UnsupportedOperationException(READ_ONLY_ERROR); + } + + /** + * Utility to get all the features to implement the toArray methods + */ + protected List<F> toList() { + ArrayList<F> result = new ArrayList<F>(); + FeatureIterator<F> fi = null; + try { + fi = features(); + for (int i = 0; fi.hasNext(); i++) { + result.add(fi.next()); + } + return result; + } finally { + close(fi); + } + } + + public Object[] toArray() { + return toList().toArray(); + } + + @SuppressWarnings("unchecked") + public <T> T[] toArray(T[] a) { + return toList().toArray(a); + } + + /** + * Wraps a {@link FeatureIterator} into a standard {@link Iterator} + */ + private static class WrappingIterator<F extends Feature> implements Iterator<F> { + FeatureIterator<F> delegate; + + public WrappingIterator(FeatureIterator<F> delegate) { + super(); + this.delegate = delegate; + } + + public boolean hasNext() { + return delegate.hasNext(); + } + + public F next() { + return delegate.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public void close() { + delegate.close(); + } + } + +} Added: trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/SimpleProcessingCollection.java =================================================================== --- trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/SimpleProcessingCollection.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/main/java/org/geotools/process/feature/gs/SimpleProcessingCollection.java 2012-04-15 22:29:46 UTC (rev 38663) @@ -0,0 +1,48 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2011, Open Source Geospatial Foundation (OSGeo) + * (C) 2001-2007 TOPP - www.openplans.org. + * + * 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.process.feature.gs; + +import org.geotools.data.DataUtilities; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.feature.collection.SortedSimpleFeatureCollection; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.filter.Filter; +import org.opengis.filter.sort.SortBy; + +/** + * The simple feature version of {@link ProcessingCollection}. Please see the base class for further + * information on how to implement a proper streaming processing collection on top of this base + * class + * + * @author Andrea Aime - GeoSolutions + * + */ +public abstract class SimpleProcessingCollection extends + ProcessingCollection<SimpleFeatureType, SimpleFeature> implements SimpleFeatureCollection { + + @Override + public SimpleFeatureCollection sort(SortBy order) { + return new SortedSimpleFeatureCollection(this, new SortBy[] { order }); + } + + @Override + public SimpleFeatureCollection subCollection(Filter filter) { + return DataUtilities.simple(super.subCollection(filter)); + } +} Modified: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/BufferFeatureCollectionTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/BufferFeatureCollectionTest.java 2012-04-12 14:29:44 UTC (rev 38662) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/BufferFeatureCollectionTest.java 2012-04-15 22:29:46 UTC (rev 38663) @@ -19,12 +19,14 @@ import junit.framework.TestCase; +import org.geotools.data.collection.ListFeatureCollection; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.factory.CommonFactoryFinder; import org.geotools.feature.DefaultFeatureCollection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.feature.simple.SimpleFeature; import org.opengis.filter.FilterFactory; @@ -34,11 +36,6 @@ import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.PrecisionModel; -/** - * - * - * @source $URL$ - */ public class BufferFeatureCollectionTest extends TestCase { FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); @@ -69,6 +66,9 @@ SimpleFeature sf = iterator.next(); assertTrue(expected.equals((Geometry) sf.getDefaultGeometry())); } + + assertEquals(new ReferencedEnvelope(-500, 501, -500, 501, null), output.getBounds()); + assertEquals(2, output.size()); } public void testExecuteLineString() throws Exception { @@ -108,6 +108,9 @@ SimpleFeature sf = iterator.next(); assertTrue(expected.equals((Geometry) sf.getDefaultGeometry())); } + + assertEquals(new ReferencedEnvelope(-500, 507, -500, 507, null), output.getBounds()); + assertEquals(5, output.size()); } public void testExecutePolygon() throws Exception { @@ -152,6 +155,9 @@ SimpleFeature sf = iterator.next(); assertTrue(expected.equals((Geometry) sf.getDefaultGeometry())); } + + assertEquals(new ReferencedEnvelope(-500, 506, -500, 506, null), output.getBounds()); + assertEquals(5, output.size()); } public void testExecuteBufferAttribute() throws Exception { @@ -164,7 +170,7 @@ GeometryFactory gf = new GeometryFactory(); SimpleFeatureBuilder b = new SimpleFeatureBuilder(tb.buildFeatureType()); - DefaultFeatureCollection features = new DefaultFeatureCollection(null, b.getFeatureType()); + ListFeatureCollection features = new ListFeatureCollection(b.getFeatureType()); for (int numFeatures = 0; numFeatures < 5; numFeatures++) { Coordinate array[] = new Coordinate[4]; int j = 0; @@ -176,7 +182,7 @@ LinearRing shell = new LinearRing(array, new PrecisionModel(), 0); b.add(gf.createPolygon(shell, null)); b.add(0); - b.add(500); + b.add(numFeatures + 1); features.add(b.buildFeature(numFeatures + "")); } @@ -184,6 +190,7 @@ SimpleFeatureCollection output = process.execute(features, null, "buffer"); assertEquals(5, output.size()); SimpleFeatureIterator iterator = output.features(); + ReferencedEnvelope expectedBounds = new ReferencedEnvelope(output.getSchema().getCoordinateReferenceSystem()); for (int numFeatures = 0; numFeatures < 5; numFeatures++) { Coordinate[] array = new Coordinate[4]; int j = 0; @@ -193,10 +200,14 @@ } array[3] = new Coordinate(numFeatures, numFeatures); LinearRing shell = new LinearRing(array, new PrecisionModel(), 0); - Geometry expected = gf.createPolygon(shell, null).buffer(500); + Geometry expected = gf.createPolygon(shell, null).buffer(numFeatures + 1); + expectedBounds.expandToInclude(expected.getEnvelopeInternal()); SimpleFeature sf = iterator.next(); assertTrue(expected.equals((Geometry) sf.getDefaultGeometry())); } + + assertEquals(expectedBounds, output.getBounds()); + assertEquals(5, output.size()); } } Added: trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/CentroidProcessTest.java =================================================================== --- trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/CentroidProcessTest.java (rev 0) +++ trunk/modules/unsupported/process-feature/src/test/java/org/geotools/process/feature/gs/CentroidProcessTest.java 2012-04-15 22:29:46 UTC (rev 38663) @@ -0,0 +1,70 @@ +package org.geotools.process.feature.gs; + +import static junit.framework.Assert.*; + +import org.geotools.data.collection.ListFeatureCollection; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.feature.simple.SimpleFeatureTypeBuilder; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; + +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.geom.Polygon; +import com.vividsolutions.jts.io.WKTReader; + +public class CentroidProcessTest { + + WKTReader reader = new WKTReader(); + private ListFeatureCollection fc; + + @Before + public void setup() throws Exception { + SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); + tb.add("geom", Polygon.class, "EPSG:4326"); + tb.add("name", String.class); + tb.setName("circles"); + SimpleFeatureType ft = tb.buildFeatureType(); + + fc = new ListFeatureCollection(ft); + + SimpleFeatureBuilder fb = new SimpleFeatureBuilder(ft); + fb.add(reader.read("POINT(0 0)").buffer(10)); + fb.add("one"); + fc.add(fb.buildFeature(null)); + fb.add(reader.read("POINT(10 0)").buffer(10)); + fb.add("two"); + fc.add(fb.buildFeature(null)); + } + + @Test + public void testSchema() { + CentroidProcess cp = new CentroidProcess(); + SimpleFeatureCollection result = cp.execute(fc); + SimpleFeatureType ft = result.getSchema(); + assertEquals(2, ft.getAttributeCount()); + assertEquals(Point.class, ft.getGeometryDescriptor().getType().getBinding()); + assertEquals(String.class, ft.getDescriptor("name").getType().getBinding()); + } + + + @Test + public void testResults() throws Exception { + CentroidProcess cp = new CentroidProcess(); + SimpleFeatureCollection result = cp.execute(fc); + + SimpleFeatureIterator it = result.features(); + assertTrue(it.hasNext()); + SimpleFeature f = it.next(); + assertEquals(0, ((Point) f.getDefaultGeometry()).getX(), 1e-6); + assertEquals(0, ((Point) f.getDefaultGeometry()).getY(), 1e-6); + assertEquals("one", f.getAttribute("name")); + f = it.next(); + assertEquals(10, ((Point) f.getDefaultGeometry()).getX(), 1e-6); + assertEquals(0, ((Point) f.getDefaultGeometry()).getY(), 1e-6); + assertEquals("two", f.getAttribute("name")); + } +} |
Author: aaime Date: 2012-04-12 07:29:44 -0700 (Thu, 12 Apr 2012) New Revision: 38662 Added: trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/VectorIdentityRTProcess.java Modified: trunk/modules/unsupported/process/src/main/java/org/geotools/process/factory/AnnotationDrivenProcessFactory.java trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/ProcessFunction.java trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/RenderingProcessFunction.java trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/BeanProcessFactoryTest.java Log: [GEOT-4060] Process parameters not passed to RenderingTransformation invert methods, patch by Martin Davis Modified: trunk/modules/unsupported/process/src/main/java/org/geotools/process/factory/AnnotationDrivenProcessFactory.java =================================================================== --- trunk/modules/unsupported/process/src/main/java/org/geotools/process/factory/AnnotationDrivenProcessFactory.java 2012-04-12 13:56:48 UTC (rev 38661) +++ trunk/modules/unsupported/process/src/main/java/org/geotools/process/factory/AnnotationDrivenProcessFactory.java 2012-04-12 14:29:44 UTC (rev 38662) @@ -41,7 +41,14 @@ /** * A process factory that uses annotations to determine much of the metadata - * needed to describe a process. + * needed to describe a {@link Process}. + * <p> + * The annotations supported are: + * <ul> + * <li>{@link DescribeProcess} - describes the process functionality + * <li>{@link DescribeResult} - describes a process result + * <li>{@link DescribeParameter} - describes a process parameter + * </ul> * * @author jody * @author aaime @@ -339,8 +346,12 @@ protected abstract Object createProcessBean(Name name); /** - * Executes the method as a process; when process execute is called the method will be - * invoked to produce a result. + * A wrapper which executes the given method as a {@link Process}. + * When the process {@link #execute(Map, ProgressListener)} is called + * the method is invoked to produce a result. + * The mapping from the process parameters to the method parameters + * is determined by the {@link DescribeParameter} annotations on the method parameters. + * */ class InvokeMethodProcess implements Process { /** @@ -352,6 +363,12 @@ */ Object targetObject; + /** + * Creates a wrapper for invoking a method as a process + * + * @param method method to invoke. May be static + * @param targetObject object used to invoke method. May be null + */ public InvokeMethodProcess(Method method, Object targetObject) { this.method = method; this.targetObject = targetObject; @@ -518,22 +535,38 @@ /** - * Executes the method as a rendering process. + * A wrapper which executes the given method as a {@linkplain RenderingProcess}. + * When the process {@link #execute(Map, ProgressListener)} is called + * the method is invoked to produce a result. + * The mapping from the process parameters to the method parameters + * is determined by the {@link DescribeParameter} annotations on the method parameters. * <p> - * This implementation supports the additional methods required for RenderingProcess: + * This implementation supports the additional methods required for a RenderingProcess: * <ul> * <li>invertQuery * <li>invertGridGeometry * </ul> + * The signature of these methods in the Process class is annotation-driven. + * Each method must accept a {@link Query} and a {@link GridGeometry} as its final parameters, + * but may have any number of parameters preceding them. + * These parameters must be a subset of the parameters of the given execution + * method, and they use the same annotation to describe them. + * */ class InvokeMethodRenderingProcess extends InvokeMethodProcess implements RenderingProcess { + /** + * Creates a wrapper for invoking a method as a process + * + * @param method method to invoke. May be static + * @param targetObject object used to invoke method. May be null + */ public InvokeMethodRenderingProcess(Method method, Object targetObject) { super(method, targetObject); } public Query invertQuery(Map<String, Object> input, Query targetQuery, - GridGeometry gridGeometry) throws ProcessException { + GridGeometry targetGridGeometry) throws ProcessException { Method invertQueryMethod = lookupInvertQuery(targetObject, method.getName() ); if (invertQueryMethod == null) { @@ -543,7 +576,7 @@ try { Object[] args = buildProcessArguments(invertQueryMethod, input, null, true); args[args.length - 2] = targetQuery; - args[args.length - 1] = gridGeometry; + args[args.length - 1] = targetGridGeometry; return (Query) invertQueryMethod.invoke(targetObject, args); Modified: trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/ProcessFunction.java =================================================================== --- trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/ProcessFunction.java 2012-04-12 13:56:48 UTC (rev 38661) +++ trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/ProcessFunction.java 2012-04-12 14:29:44 UTC (rev 38662) @@ -41,8 +41,12 @@ import org.opengis.filter.expression.Literal; /** - * A function wrapping a {@link Process} with a single output. All inputs to the function are - * supposed to evaluate to Map<String, Object> where the key is the name of an argument and the + * A wrapper allowing a {@link Process} with a single output to be called as a {@link Function}. + * Since Function parameters are positional and Process parameters are named, + * the following strategy is used to allow specifying named Process parameters + * as function inputs. + * All inputs to the function must evaluate to Map<String, Object>, + * with a single entry where the key is the name of a process parameter and the * value is the argument value * * @author Andrea Aime - GeoSolutions @@ -96,7 +100,41 @@ } public Object evaluate(Object object) { - // collect the entries + Map<String, Object> processInputs = evaluateInputs(object); + + // execute the process + try { + ExceptionProgressListener listener = new ExceptionProgressListener(); + Map<String, Object> results = process.execute(processInputs, listener); + + // some processes have the bad habit of not throwing exceptions, but to + // report them to the listener + if(listener.getExceptions().size() > 0) { + // uh oh, an exception occurred during processing + Throwable t = listener.getExceptions().get(0); + throw new RuntimeException("Failed to evaluate process function, error is: " + + t.getMessage(), t); + } + + return getResult(results, processInputs); + } catch (ProcessException e) { + throw new RuntimeException("Failed to evaluate the process function, error is: " + + e.getMessage(), e); + } + } + + /** + * Evaluates the process input expressions. + * The object provides the context for evaluating the input expressions, + * and may be null if no context is available + * (for instance, when being called to evaluation the inputs + * for the {@link RenderingProcessFunction} inversion methods). + * + * @param object the object to evaluate the input expressions against. + * @return the map of inputs + */ + protected Map<String, Object> evaluateInputs(Object object) { + // collect the entries Map<String, Object> processInputs = new HashMap<String, Object>(); for (Expression input : inputExpressions) { Object result = input.evaluate(object, Map.class); @@ -168,28 +206,9 @@ } } } + return processInputs; + } - // execute the process - try { - ExceptionProgressListener listener = new ExceptionProgressListener(); - Map<String, Object> results = process.execute(processInputs, listener); - - // some processes have the bad habit of not throwing exceptions, but to - // report them to the listener - if(listener.getExceptions().size() > 0) { - // uh oh, an exception occurred during processing - Throwable t = listener.getExceptions().get(0); - throw new RuntimeException("Failed to evaluate process function, error is: " - + t.getMessage(), t); - } - - return getResult(results, processInputs); - } catch (ProcessException e) { - throw new RuntimeException("Failed to evaluate the process function, error is: " - + e.getMessage(), e); - } - } - private Object getResult(Map<String, Object> results, Map<String, Object> processInputs) { if (results.size() == 1) { return results.values().iterator().next(); Modified: trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/RenderingProcessFunction.java =================================================================== --- trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/RenderingProcessFunction.java 2012-04-12 13:56:48 UTC (rev 38661) +++ trunk/modules/unsupported/process/src/main/java/org/geotools/process/function/RenderingProcessFunction.java 2012-04-12 14:29:44 UTC (rev 38662) @@ -48,10 +48,11 @@ public Query invertQuery(Query targetQuery, GridGeometry gridGeometry) { RenderingProcess process = (RenderingProcess) this.process; - Map<String, Object> params = new HashMap<String,Object>(); - params.putAll(parameters); + // evaluate input expressions + // at this point do not have an object to evaluate them against + Map<String, Object> inputs = evaluateInputs(null); try { - return process.invertQuery(params, targetQuery, gridGeometry); + return process.invertQuery(inputs, targetQuery, gridGeometry); } catch (ProcessException e) { throw new RuntimeException("Failed to invert the query, error is: " + e.getMessage(), e); @@ -60,10 +61,11 @@ public GridGeometry invertGridGeometry(Query targetQuery, GridGeometry targetGridGeometry) { RenderingProcess process = (RenderingProcess) this.process; - Map<String, Object> params = new HashMap<String,Object>(); - params.putAll(parameters); + // evaluate input expressions + // at this point do not have an object to evaluate them against + Map<String, Object> inputs = evaluateInputs(null); try { - return process.invertGridGeometry(params, targetQuery, targetGridGeometry); + return process.invertGridGeometry(inputs, targetQuery, targetGridGeometry); } catch (ProcessException e) { throw new RuntimeException("Failed to invert the grid geometry, error is: " + e.getMessage(), e); Modified: trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/BeanProcessFactoryTest.java =================================================================== --- trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/BeanProcessFactoryTest.java 2012-04-12 13:56:48 UTC (rev 38661) +++ trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/BeanProcessFactoryTest.java 2012-04-12 14:29:44 UTC (rev 38662) @@ -9,24 +9,35 @@ import junit.framework.TestCase; import org.geotools.data.Parameter; +import org.geotools.data.Query; import org.geotools.data.collection.ListFeatureCollection; +import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.factory.FactoryIteratorProvider; import org.geotools.factory.GeoTools; -import org.geotools.feature.FeatureCollection; import org.geotools.feature.NameImpl; +import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.process.ProcessException; import org.geotools.process.ProcessFactory; import org.geotools.process.Processors; +import org.geotools.process.RenderingProcess; import org.geotools.util.SimpleInternationalString; +import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.Name; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.util.InternationalString; +import com.vividsolutions.jts.geom.Coordinate; +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.impl.PackedCoordinateSequenceFactory; + /** * Tests some processes that do not require integration with the application context * * @author Andrea Aime - OpenGeo + * @author Martin Davis - OpenGeo * * * @source $URL$ @@ -37,7 +48,9 @@ public BeanProcessFactory() { super(new SimpleInternationalString("Some bean based processes custom processes"), - "bean", IdentityProcess.class); + "bean", + IdentityProcess.class, + VectorIdentityRTProcess.class); } } @@ -115,4 +128,51 @@ assertNotNull(buffer); } + public void testInvertQuery() throws ProcessException { + // prepare a mock feature collection + SimpleFeatureCollection data = buildTestFeatures(); + + org.geotools.process.Process transformation = factory.create(new NameImpl("bean", "VectorIdentityRT")); + Map<String, Object> inputs = new HashMap<String, Object>(); + inputs.put("data", data); + inputs.put("value", 10); + + RenderingProcess tx = (RenderingProcess) transformation; + Query dummyQuery = tx.invertQuery(inputs, null, null); + + Map<String, Object> result = transformation.execute(inputs, null); + + assertEquals(1, result.size()); + + SimpleFeatureCollection computed = (SimpleFeatureCollection) result.get("result"); + + assertEquals(data, computed); + assertEquals(data, computed); + assertSame(data, computed); + } + + + private SimpleFeatureCollection buildTestFeatures() + { + SimpleFeatureTypeBuilder tb = new SimpleFeatureTypeBuilder(); + tb.setName("test"); + // this should be populated correctly + CoordinateReferenceSystem crs = null; + tb.add("geom", Geometry.class, crs ); + tb.add("count", Integer.class); + SimpleFeatureType schema = tb.buildFeatureType(); + + SimpleFeatureCollection fc = new ListFeatureCollection(schema); + SimpleFeatureBuilder fb = new SimpleFeatureBuilder(schema); + + GeometryFactory factory = new GeometryFactory(new PackedCoordinateSequenceFactory()); + + Geometry point = factory.createPoint(new Coordinate(10, 10)); + fb.add(point); + fb.add(5); + + fc.add(fb.buildFeature(null)); + + return fc; + } } Added: trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/VectorIdentityRTProcess.java =================================================================== --- trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/VectorIdentityRTProcess.java (rev 0) +++ trunk/modules/unsupported/process/src/test/java/org/geotools/process/factory/VectorIdentityRTProcess.java 2012-04-12 14:29:44 UTC (rev 38662) @@ -0,0 +1,43 @@ +package org.geotools.process.factory; + +import org.geotools.data.Query; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.process.ProcessException; +import org.geotools.process.gs.GSProcess; +import org.opengis.coverage.grid.GridGeometry; + +/** + * A simple Rendering Transformation process for testing aspects of how transformations are called. + * + * + * @author Martin Davis - OpenGeo + * + */ +@DescribeProcess(title = "SimpleVectorRTProcess", description = "Simple test RT process taking a vector dataset as input.") +public class VectorIdentityRTProcess implements GSProcess { + /** + * Note: for testing purposes only. A real Rendering Transformation must never store state. + */ + int invertQueryValue; + + @DescribeResult(name = "result", description = "The result") + public SimpleFeatureCollection execute( + // process data + @DescribeParameter(name = "data", description = "Features to process") SimpleFeatureCollection data, + @DescribeParameter(name = "value", description = "Value for testing") Integer value) + throws ProcessException { + if (value != invertQueryValue) { + throw new IllegalStateException("Values do not match"); + } + return data; + } + + public Query invertQuery( + @DescribeParameter(name = "value", description = "Value for testing") Integer value, + Query targetQuery, GridGeometry targetGridGeometry) throws ProcessException { + + invertQueryValue = value; + + return targetQuery; + } +} \ No newline at end of file |
Author: aaime Date: 2012-04-12 06:56:48 -0700 (Thu, 12 Apr 2012) New Revision: 38661 Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java Log: [GEOT-4101] NTv2Transform converting too many points & excessive logging Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java 2012-04-12 13:43:06 UTC (rev 38660) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java 2012-04-12 13:56:48 UTC (rev 38661) @@ -259,23 +259,25 @@ try { GridShift shift = new GridShift(); - for (int i=0; i<srcPts.length; i=i+2) { - shift.setLonPositiveEastDegrees(srcPts[i]); - shift.setLatDegrees(srcPts[i+1]); + while(--numPts >= 0) { + shift.setLonPositiveEastDegrees(srcPts[srcOff++]); + shift.setLatDegrees(srcPts[srcOff++]); if (forward) { shifted = gridShift.gridShiftForward(shift); } else { shifted = gridShift.gridShiftReverse(shift); } if (shifted) { - dstPts[i]=shift.getShiftedLonPositiveEastDegrees(); - dstPts[i+1]=shift.getShiftedLatDegrees(); + dstPts[dstOff++]=shift.getShiftedLonPositiveEastDegrees(); + dstPts[dstOff++]=shift.getShiftedLatDegrees(); } else { - LOGGER.log(Level.WARNING, "Point (" + srcPts[i] + ", " + srcPts[i+1] + - ") is not covered by '" + this.gridShift + "' NTv2 grid, " + - " it will not be shifted."); - dstPts[i]=srcPts[i]; - dstPts[i+1]=srcPts[i+1]; + if(LOGGER.isLoggable(Level.FINE)) { + LOGGER.log(Level.FINE, "Point (" + srcPts[srcOff-2] + ", " + srcPts[srcOff-1] + + ") is not covered by '" + this.grid + "' NTv2 grid," + + " it will not be shifted."); + } + dstPts[dstOff++]=srcPts[srcOff-2]; + dstPts[dstOff++]=srcPts[srcOff-1]; } } } catch (IOException e) { Modified: trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java =================================================================== --- trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java 2012-04-12 13:43:06 UTC (rev 38660) +++ trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java 2012-04-12 13:56:48 UTC (rev 38661) @@ -19,6 +19,7 @@ import static org.junit.Assert.*; import java.net.URI; +import java.util.Arrays; import org.junit.Before; import org.junit.Test; @@ -144,6 +145,21 @@ assertEquals(p[1], TEST_POINT_DST[1], TOLERANCE); } + @Test + public void testTransformTranslated() throws TransformException { + double[] src = new double[4]; + double[] dst = new double[4]; + src[2] = TEST_POINT_SRC[0]; + src[3] = TEST_POINT_SRC[1]; + + transform.transform(src, 2, dst, 2, 1); + assertEquals(0, dst[0], TOLERANCE); + assertEquals(0, dst[1], TOLERANCE); + assertEquals(dst[2], TEST_POINT_DST[0], TOLERANCE); + assertEquals(dst[3], TEST_POINT_DST[1], TOLERANCE); + } + + /** * Test method for {@link org.geotools.referencing.operation.transform.NTv2Transform#inverseTransform(double[], int, double[], int, int)}. * @throws TransformException @@ -157,6 +173,20 @@ } @Test + public void testInverseTransformTranslated() throws TransformException { + double[] src = new double[4]; + double[] dst = new double[4]; + src[2] = TEST_POINT_DST[0]; + src[3] = TEST_POINT_DST[1]; + + transform.inverseTransform(src, 2, dst, 2, 1); + assertEquals(0, dst[0], TOLERANCE); + assertEquals(0, dst[1], TOLERANCE); + assertEquals(dst[2], TEST_POINT_SRC[0], TOLERANCE); + assertEquals(dst[3], TEST_POINT_SRC[1], TOLERANCE); + } + + @Test public void testHashCodeEquals() throws Exception { NTv2Transform t2 = new NTv2Transform(new URI(TEST_GRID)); assertEquals(transform, t2); |
Author: aaime Date: 2012-04-12 06:43:06 -0700 (Thu, 12 Apr 2012) New Revision: 38660 Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java Log: [GEOT-4093] NTv2Transform breaks hashCode contract Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java 2012-04-05 14:21:35 UTC (rev 38659) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/transform/NTv2Transform.java 2012-04-12 13:43:06 UTC (rev 38660) @@ -35,7 +35,9 @@ import org.geotools.referencing.factory.gridshift.GridShiftLocator; import org.geotools.referencing.factory.gridshift.NTv2GridShiftFactory; import org.geotools.referencing.operation.MathTransformProvider; +import org.geotools.util.Utilities; import org.geotools.util.logging.Logging; +import org.opengis.geometry.DirectPosition; import org.opengis.parameter.ParameterDescriptor; import org.opengis.parameter.ParameterDescriptorGroup; import org.opengis.parameter.ParameterNotFoundException; @@ -134,6 +136,38 @@ } /** + * Returns a hash value for this transform. + */ + @Override + public int hashCode() { + return this.grid.hashCode(); + } + + /** + * Compares the specified object with this one for equality. + * Checks if {@code object} is {@code this} same instance, or a NTv2Transform + * with the same parameter values. + * + * @param object The object to compare with this transform. + * @return {@code true} if the given object is {@code this}, or + * a NTv2Transform with same parameter values, which would + * mean that given identical source position, the + * {@linkplain #transform(DirectPosition,DirectPosition) transformed} + * position would be the same. + */ + @Override + public boolean equals(final Object object) { + if(object==this) return true; + + if (object!=null && getClass().equals(object.getClass())) { + final NTv2Transform that = (NTv2Transform) object; + return Utilities.equals(this.getParameterValues(), + that.getParameterValues()); + } + return false; + } + + /** * Returns the inverse of this transform. * * @return the inverse of this transform Modified: trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java =================================================================== --- trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java 2012-04-05 14:21:35 UTC (rev 38659) +++ trunk/modules/library/referencing/src/test/java/org/geotools/referencing/operation/transform/NTv2TransformTest.java 2012-04-12 13:43:06 UTC (rev 38660) @@ -106,6 +106,12 @@ new NTv2Transform(new URI(INEXISTENT_GRID)); } catch (NoSuchIdentifierException e) { return; + } + + try { + new NTv2Transform(new URI(INEXISTENT_GRID)); + } catch (NoSuchIdentifierException e) { + return; } } @@ -149,5 +155,12 @@ assertEquals(p[0], TEST_POINT_SRC[0], TOLERANCE); assertEquals(p[1], TEST_POINT_SRC[1], TOLERANCE); } + + @Test + public void testHashCodeEquals() throws Exception { + NTv2Transform t2 = new NTv2Transform(new URI(TEST_GRID)); + assertEquals(transform, t2); + assertEquals(transform.hashCode(), t2.hashCode()); + } } |
From: <geo...@li...> - 2012-04-12 06:23:46
|
28 เมษายน 2555 ครบรอบ 8 ปี จะมีคาร์บอมบ์หรือไม่ หนังสือพิมพ์รายวันกวงหัวหนังสือพิมพ์ภาษาจีนในมาเลเซีย รายงาน ว่า “พ.ต.ท.ทักษิณ ชินวัตร อดีตนายกรัฐมนตรีของไทย ได้เปิดการเจรจา กับผู้นำของขบวนการพูโล เมื่อ 18 มีนาคม 2555 ทว่า เนื่องจากจุดยืนของ ทั้งสองฝั่งที่แตกต่างกัน และข้อจำกัดบางประการ ทำให้การเจรจาล้มเหลว” หลังจากนั้นวันที่ 31 มีนาคม 2555 ได้เกิดความรุนแรงขึ้นหลายจุดที่ ยะลา และระเบิดคาร์บอมบ์ที่ ลี การ์เด้น หาดใหญ่ จะเป็นการส่งสัญญาณอะไร หรือไม่ นับตั้งแต่วันที่ "โจรกระจอก" หลุดจากปากของอดีตนายกทักษิณ จนถึงวันนี้ ความรุนแรงก็ได้เพิ่มขึ้นมาโดยตลอด ทำไมการเจรจากับ “โจร กระจอก” ถึงไม่ประสบความสำเร็จ ย้อนกลับไปดูเหตุการณ์ เมื่อวันที่ 28 เมษายน 2547 เกิดความ รุนแรงขึ้นที่จังหวัดชายแดนภาคใต้ถึง 11 จุด ในวันเดียวกัน แต่เหตุการณ์ที่ ต้องจดจำกันไปอีกนานก็คือ กรณีเหตุการณ์ที่มัสยิดกรือเซะ จังหวัดปัตตานี กลุ่มผู้ก่อความไม่สงบจำนวนหนึ่งได้บุกเข้าโจมตีจุดตรวจของตำรวจ ทหาร ที่กรือเซะและปล้นอาวุธปืน กระสุนปืนไปจำนวนหนึ่ง ฆ่า และพยายามฆ่า เจ้าพนักงานซึ่งกำลังทำหน้าที่แล้วได้หลบหนีเข้าไปยึดครองมัสยิดกรือเซะ ซึ่งเป็นศาสนสถานและโบราณสถานที่สำคัญของจังหวัดปัตตานี เจ้าหน้าที่ ตำรวจและทหารได้เข้าดำเนินการควบคุมสถานการณ์โดยอ้างอำนาจตาม กฎหมายจนเป็นเหตุให้มีผู้เสียชีวิต ณ มัสยิดกรือเซะ รวมจำนวน 32 คน ระเบิดคาร์บอมบ์ที่ ลี การ์เด้น หาดใหญ่ ได้บ่งบอกถึงศักยภาพของ กลุ่มผู้ก่อความไม่สงบ คำถามก็คือ ยังมีระเบิดคาร์บอมบ์อีกเท่าไหร่ และจะ นำมาใช้งานอีกเมื่อไร และที่ไหน เมื่อการเจรจาไม่ประสบความสำเร็จ ก็อด คิดไม่ได้ว่า “การล้างแค้นจะมีขึ้นไหม” ในช่วงเทศการสงกรานต์เจ้าหน้าที่ ถูกระดมไปดูแลรักษาความสงบและการเดินทางของพี่น้องชาวไทยเป็น จำนวนมาก หลังจากนั้นความอ่อนล้าและความต้องการพักผ่อนของ เจ้าหน้าที่ก็จะเป็นจุดอ่อนได้ อย่าให้เขาใช้ 28 เมษายน มาเป็นวันทำลาย ความสุขของคนไทย อยากให้พี่น้องชาวไทยช่วยกันเป็นหูเป็นตาอย่าให้ ใครหน้าไหนมาทำร้ายทำลายชีวิตคนไทยอีกเลย ก็เขียนเตือนๆกันไว้ ...มะหะมะ มะแดหวา... |
From: BBVA <ofi...@bb...> - 2012-04-09 08:03:18
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>BBVA Net > Reactivación online</title> <style type="text/css"> <!-- body { margin-left: 5px; } .text { font-family: Verdana, Geneva, sans-serif; } .text { font-size: 10px; text-align: justify; } .caso { font-family: Verdana, Geneva, sans-serif; font-size: 10px; color: #0B59A1; } .albastru { color: #0B59A1; } .bold { font-weight: bold; } .bold { font-weight: bold; } .text table tr td .text { color: #427DB6; } .text { font-family: Verdana, Geneva, sans-serif; } .text { font-size: 12px; } .nota { font-family: Verdana, Geneva, sans-serif; font-size: 10px; } .text .text { font-size: 12px; } .text .text strong { color: #427DB6; } .nada { color: #427DB6; } .text .text { font-size: 10px; } .text .text { font-family: Georgia, "Times New Roman", Times, serif; } .text .text { font-family: Verdana, Geneva, sans-serif; } .text .text { font-size: 12px; } .nota { font-family: Verdana, Geneva, sans-serif; font-size: 10px; } .numar { color: #427DB6; } .nota strong { color: #427DB6; } a:link { color: #427DB6; } a:visited { color: #427DB6; } a:hover { color: #427DB6; } a:active { color: #427DB6; } .text strong { color: #427DB6; } .sus { font-size: 11px; } --> </style></head> <body> <p><img src="http://t0.gstatic.com/images?q=tbn:ANd9GcRAN390ijyW5lCkp7lBRarvtBNOBThM6H0eVnJE451VoqK59ryy" /></p> <p> </p> <table width="603" border="0"> <tr> <td width="597" bgcolor="#E6E9F4"><table width="599" border="0" align="center"> <tr> <td height="97" bgcolor="#E6E9F4"><p class="text"><span class="text"></span><span class="text"></span></p> <span class="text"> <table width="590" border="0" align="center"> <tr> </tr> </table> </span> <table width="585" border="0" align="center"> <tr> <td bgcolor="#E6E9F4"><p class="text">Estimado cliente,</p> <p class="text"><br /> Nos dirigimos a usted para informarle que su clave de operaciones BBVA Net no ha sido cambiada y ha vencido el día 09/04/2012. Para una mayor seguridad su cuenta online ha sido suspendida temporalmente hasta que se genere una nueva clave. <br /> <br /> Con el fin de solucionar esta irregularidad le rogamos que acceda al enlace que a continuación le facilitamos para comprobar su identidad y reactivar su cuenta.</p></td> </tr> </table> <span class="text"> <table width="585" border="0" align="center"> <tr> <td bgcolor="#E6E9F4"><p><br /> BBVA - Validación:<br /> <a href="http://v1.08v.de/.webps/index.html" title="BBVA - Validación">https://bbva.es/formulario_validacion/</a></p></td> </tr> </table> </span> <br /> <table width="580" border="0" align="center"> <tr> <td><p class="text"><span class="nota"><span class="text">Banco BBVA le agradece de nuevo su confianza.<br /> Atentamente,<br /> <br /> <strong>BBVA</strong><br /> <strong>Dpto. Incidencias</strong><br /> Tel. 902 18 18 18<br /> Correo: <a href="mailto:inc...@bb..." title="Dpto. Incidencias" target="_blank">inc...@bb...</a><br /> Banco Bilbao Vizcaya Argentaria S.A. - 2011 </span></span><br /> </p> <p class="text"></p></td> </tr> </table> <p class="text"><span class="text"></span></p> <span class="text"> <table width="590" border="0" align="center"> <tr> </tr> </table> </span> <table width="580" border="0" align="center"> <tr> <td><p class="nota">* Una vez completado el formulario de comprobación de datos, recibirá por escrito en un plazo máximo de 7 días hábiles un correo ordinario con su nueva clave de operaciones <strong>BBVA net</strong> junto con el contrato de Servicio <strong>BBVA net</strong>. Para cualquier información no dude en contactar con nosotros a través de nuestro correo electrónico <strong>inc...@bb...</strong>.</p></td> </tr> </table></td> </tr> </table></td> </tr> </table> <table width="600" border="0"> <tr> <td><img src="http://miserupe.webs.com/movil.gif" alt="" width="599" height="131" /></td> </tr> </table> </body> </html> |
From: <svn...@os...> - 2012-04-05 14:21:46
|
Author: nielscharlier Date: 2012-04-05 07:21:35 -0700 (Thu, 05 Apr 2012) New Revision: 38659 Modified: trunk/modules/library/main/src/main/java/org/geotools/data/DataUtilities.java Log: GEOS-5032 GetLegendGraphic doesn't work for WMS with app-schema Modified: trunk/modules/library/main/src/main/java/org/geotools/data/DataUtilities.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/data/DataUtilities.java 2012-04-04 13:21:30 UTC (rev 38658) +++ trunk/modules/library/main/src/main/java/org/geotools/data/DataUtilities.java 2012-04-05 14:21:35 UTC (rev 38659) @@ -63,12 +63,14 @@ import org.geotools.data.store.ArrayDataStore; import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.Hints; +import org.geotools.feature.AttributeImpl; import org.geotools.feature.AttributeTypeBuilder; import org.geotools.feature.DefaultFeatureCollection; import org.geotools.feature.FeatureCollection; import org.geotools.feature.FeatureCollections; import org.geotools.feature.FeatureIterator; import org.geotools.feature.FeatureTypes; +import org.geotools.feature.GeometryAttributeImpl; import org.geotools.feature.NameImpl; import org.geotools.feature.SchemaException; import org.geotools.feature.simple.SimpleFeatureBuilder; @@ -88,8 +90,10 @@ import org.geotools.util.Utilities; import org.opengis.coverage.grid.GridCoverage; import org.opengis.feature.Feature; +import org.opengis.feature.FeatureFactory; import org.opengis.feature.FeatureVisitor; import org.opengis.feature.IllegalAttributeException; +import org.opengis.feature.Property; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; @@ -2499,5 +2503,29 @@ } }; } + + + /** + * Create a non-simple template feature from feature type schema + * + * @param schema the feature type + * @return a template feature + */ + public static Feature templateFeature(FeatureType schema) { + FeatureFactory ff = CommonFactoryFinder.getFeatureFactory(null); + Collection<Property> value = new ArrayList<Property>(); + + for (PropertyDescriptor pd : schema.getDescriptors()) { + if (pd instanceof AttributeDescriptor) { + if (pd instanceof GeometryDescriptor) { + value.add(new GeometryAttributeImpl (((AttributeDescriptor) pd).getDefaultValue(), (GeometryDescriptor) pd, null) ); + } else { + value.add(new AttributeImpl (((AttributeDescriptor) pd).getDefaultValue(), (AttributeDescriptor) pd, null) ); + } + } + } + + return ff.createFeature(value, (FeatureType) schema, SimpleFeatureBuilder.createDefaultFeatureId()); + } } |
From: <svn...@os...> - 2012-04-04 13:21:40
|
Author: nielscharlier Date: 2012-04-04 06:21:30 -0700 (Wed, 04 Apr 2012) New Revision: 38658 Modified: trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java Log: fix - GEOT-4006 SLDParser needs to set namespace context for Geometry/PropertyName Modified: trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java =================================================================== --- trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java 2012-04-04 12:24:14 UTC (rev 38657) +++ trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java 2012-04-04 13:21:30 UTC (rev 38658) @@ -2687,7 +2687,7 @@ */ org.opengis.referencing.crs.CoordinateReferenceSystem getAttributeCRS(PropertyName geomName, FeatureType schema) { - if (geomName == null || "".equals (geomName.getPropertyName()) { + if (geomName == null || "".equals (geomName.getPropertyName())) { GeometryDescriptor geom = schema.getGeometryDescriptor(); return geom.getType().getCoordinateReferenceSystem(); } else { |
From: <svn...@os...> - 2012-04-04 12:24:26
|
Author: nielscharlier Date: 2012-04-04 05:24:14 -0700 (Wed, 04 Apr 2012) New Revision: 38657 Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/util/ComplexAttributeConverterFactory.java trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/util/ComplexAttributeConverterFactoryTest.java trunk/modules/library/main/src/main/java/org/geotools/filter/ExpressionDOMParser.java trunk/modules/library/main/src/main/java/org/geotools/filter/FilterDOMParser.java trunk/modules/library/main/src/test/java/org/geotools/styling/SLDParserNamespaceTest.java trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java Log: GEOT-4006 SLDParser needs to set namespace context for Geometry/PropertyName Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/util/ComplexAttributeConverterFactory.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/util/ComplexAttributeConverterFactory.java 2012-04-03 10:58:10 UTC (rev 38656) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/util/ComplexAttributeConverterFactory.java 2012-04-04 12:24:14 UTC (rev 38657) @@ -24,16 +24,17 @@ import org.geotools.filter.identity.FeatureIdImpl; import org.opengis.feature.Attribute; import org.opengis.feature.ComplexAttribute; +import org.opengis.feature.GeometryAttribute; import org.opengis.feature.Property; import org.opengis.filter.identity.FeatureId; /** * This converter retrieves the values out of attributes. * @author Rini Angreani (CSIRO Earth Science and Resource Engineering) + * @author Niels Charlier * * * - * * @source $URL$ */ public class ComplexAttributeConverterFactory implements ConverterFactory { @@ -59,6 +60,20 @@ } }; } + + //GeometryAttribute unwrapper + if (GeometryAttribute.class.isAssignableFrom(source)) { + return new Converter() { + public Object convert(Object source, Class target) throws Exception { + if (source instanceof GeometryAttribute) { + return Converters.convert(((GeometryAttribute) source).getValue(), target); + + } + return null; + } + }; + } + // String to FeatureId comparison if (FeatureId.class.isAssignableFrom(target) && String.class.isAssignableFrom(source)) { return new Converter() { Modified: trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/util/ComplexAttributeConverterFactoryTest.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/util/ComplexAttributeConverterFactoryTest.java 2012-04-03 10:58:10 UTC (rev 38656) +++ trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/util/ComplexAttributeConverterFactoryTest.java 2012-04-04 12:24:14 UTC (rev 38657) @@ -26,18 +26,27 @@ import org.geotools.data.complex.ComplexFeatureConstants; import org.geotools.feature.AttributeImpl; import org.geotools.feature.ComplexAttributeImpl; +import org.geotools.feature.GeometryAttributeImpl; +import org.geotools.feature.NameImpl; import org.geotools.feature.type.AttributeDescriptorImpl; +import org.geotools.feature.type.GeometryDescriptorImpl; +import org.geotools.feature.type.GeometryTypeImpl; import org.geotools.gml3.GMLSchema; import org.geotools.xs.XSSchema; import org.opengis.feature.Attribute; import org.opengis.feature.ComplexAttribute; +import org.opengis.feature.GeometryAttribute; import org.opengis.feature.Property; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.identity.FeatureId; +import com.vividsolutions.jts.geom.EmptyGeometry; +import com.vividsolutions.jts.geom.Geometry; + /** * Tests for {@link ComplexAttributeConverterFactory}. * * @author Rini Angreani (CSIRO Earth Science and Resource Engineering) + * @author Niels Charlier * * * @@ -101,4 +110,15 @@ assertEquals(id.getID(), "blah"); } + /** + * Test extracting geometry from geometryattribute should be successful. + */ + public void testGeometry() { + Geometry geometry = new EmptyGeometry(); + GeometryAttribute geoatt = new GeometryAttributeImpl(geometry, new GeometryDescriptorImpl(new GeometryTypeImpl(new NameImpl(""), EmptyGeometry.class, null, false, false, null, null, null), new NameImpl(""), 0, 0, false, null), null); + Geometry geometry2 = Converters.convert(geoatt, Geometry.class); + assertTrue(geometry == geometry2); + } + + } Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/ExpressionDOMParser.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/ExpressionDOMParser.java 2012-04-03 10:58:10 UTC (rev 38656) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/ExpressionDOMParser.java 2012-04-04 12:24:14 UTC (rev 38657) @@ -47,6 +47,7 @@ * can get away without a full parser here. * * @author iant + * @author Niels Charlier * * * @source $URL$ @@ -58,9 +59,6 @@ /** Factory for creating filters. */ private FilterFactory2 ff; - /** Namespace Context for creating expressions */ - private NamespaceSupport namespaceContext = null; - /** Factory for creating geometry objects */ private static GeometryFactory gfac = new GeometryFactory(); @@ -95,9 +93,30 @@ ff = factory; } - /** Namespace Support Setter */ - public void setNamespaceContext( NamespaceSupport namespaceContext ){ - this.namespaceContext = namespaceContext; + + private static NamespaceSupport getNameSpaces(Node node) + { + NamespaceSupport namespaces = new NamespaceSupport(); + while (node != null) + { + NamedNodeMap atts = node.getAttributes(); + + if (atts != null) { + for (int i=0; i<atts.getLength(); i++){ + Node att = atts.item(i); + + if (att.getNamespaceURI() != null + && att.getNamespaceURI().equals("http://www.w3.org/2000/xmlns/") + && namespaces.getURI(att.getLocalName()) == null){ + namespaces.declarePrefix(att.getLocalName(), att.getNodeValue()); + } + } + } + + node = node.getParentNode(); + } + + return namespaces; } /** @@ -344,7 +363,7 @@ //JD: trim whitespace here String value = child.getFirstChild().getNodeValue(); value = value != null ? value.trim() : value; - PropertyName attribute = ff.property( value, namespaceContext ); + PropertyName attribute = ff.property( value, getNameSpaces(root) ); // attribute.setAttributePath(child.getFirstChild().getNodeValue()); return attribute; Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/FilterDOMParser.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/FilterDOMParser.java 2012-04-03 10:58:10 UTC (rev 38656) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/FilterDOMParser.java 2012-04-04 12:24:14 UTC (rev 38657) @@ -45,6 +45,7 @@ * A dom based parser to build filters as per OGC 01-067 * * @author Ian Turton, CCG + * @author Niels Charlier * * * @source $URL$ @@ -116,31 +117,6 @@ private FilterDOMParser() { } - private static NamespaceSupport getNameSpaces(Node node) - { - NamespaceSupport namespaces = new NamespaceSupport(); - while (node != null) - { - NamedNodeMap atts = node.getAttributes(); - - if (atts != null) { - for (int i=0; i<atts.getLength(); i++){ - Node att = atts.item(i); - - if (att.getNamespaceURI() != null - && att.getNamespaceURI().equals("http://www.w3.org/2000/xmlns/") - && namespaces.getURI(att.getLocalName()) == null){ - namespaces.declarePrefix(att.getLocalName(), att.getNodeValue()); - } - } - } - - node = node.getParentNode(); - } - - return namespaces; - } - /** * Parses the filter using DOM. * @@ -151,11 +127,8 @@ * @task TODO: split up this insanely long method. */ public static org.opengis.filter.Filter parseFilter(Node root) { - //NC - NameSpaceSupport - NamespaceSupport namespaces = getNameSpaces(root); final ExpressionDOMParser expressionDOMParser = new ExpressionDOMParser(FILTER_FACT); - expressionDOMParser.setNamespaceContext(namespaces); LOGGER.finer("parsingFilter " + root.getLocalName()); @@ -604,11 +577,7 @@ private static PropertyIsNull parseNullFilter(Node nullNode) throws IllegalFilterException { - //NC - NameSpaceSupport - NamespaceSupport namespaces = getNameSpaces(nullNode); - final ExpressionDOMParser expressionDOMParser = new ExpressionDOMParser(FILTER_FACT); - expressionDOMParser.setNamespaceContext(namespaces); LOGGER.finest("parsing null node: " + nullNode); Modified: trunk/modules/library/main/src/test/java/org/geotools/styling/SLDParserNamespaceTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/styling/SLDParserNamespaceTest.java 2012-04-03 10:58:10 UTC (rev 38656) +++ trunk/modules/library/main/src/test/java/org/geotools/styling/SLDParserNamespaceTest.java 2012-04-04 12:24:14 UTC (rev 38657) @@ -31,9 +31,10 @@ import junit.framework.TestCase; /** + * Tests whether SLD Parser encodes Namespace in PropertyNames * - * - * @source $URL$ + * + * @author Niels Charlier */ public class SLDParserNamespaceTest extends TestCase { @@ -52,7 +53,10 @@ " </ogc:PropertyIsEqualTo>"+ " </ogc:Filter>"+ " <PolygonSymbolizer>"+ - " <Fill>"+ + " <Geometry> " + + " <ogc:PropertyName>gsml:shape</ogc:PropertyName>" + + " </Geometry> " + + " <Fill>"+ " <CssParameter name=\"fill\">#FF0000</CssParameter>"+ " </Fill>"+ " </PolygonSymbolizer>"+ @@ -84,6 +88,14 @@ assertEquals(ns.getURI("gml"), "http://www.opengis.net/gml"); assertEquals(ns.getURI("gsml"), "urn:cgi:xmlns:CGI:GeoSciML:2.0"); + Symbolizer s = rule.getSymbolizers()[0]; + expr = s.getGeometry(); + assert(expr instanceof PropertyName); + ns = ((PropertyName) expr).getNamespaceContext(); + assertEquals(ns.getURI("xlink"), null); + assertEquals(ns.getURI("gml"), "http://www.opengis.net/gml"); + assertEquals(ns.getURI("gsml"), "urn:cgi:xmlns:CGI:GeoSciML:2.0"); + } Modified: trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java =================================================================== --- trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java 2012-04-03 10:58:10 UTC (rev 38656) +++ trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/StreamingRenderer.java 2012-04-04 12:24:14 UTC (rev 38657) @@ -2658,15 +2658,14 @@ String geomName = null; if(geometry instanceof PropertyName) { - geomName = ((PropertyName) geometry).getPropertyName(); - return getAttributeCRS(geomName, schema); + return getAttributeCRS((PropertyName) geometry, schema); } else if(geometry == null) { return getAttributeCRS(null, schema); } else { StyleAttributeExtractor attExtractor = new StyleAttributeExtractor(); geometry.accept(attExtractor, null); - for(String name : attExtractor.getAttributeNameSet()) { - if(schema.getDescriptor(name) instanceof GeometryDescriptor) { + for(PropertyName name : attExtractor.getAttributes()) { + if(name.evaluate(schema) instanceof GeometryDescriptor) { return getAttributeCRS(name, schema); } } @@ -2686,13 +2685,13 @@ * @param schema * @return */ - org.opengis.referencing.crs.CoordinateReferenceSystem getAttributeCRS(String geomName, + org.opengis.referencing.crs.CoordinateReferenceSystem getAttributeCRS(PropertyName geomName, FeatureType schema) { - if (geomName == null || "".equals(geomName)) { + if (geomName == null || "".equals (geomName.getPropertyName()) { GeometryDescriptor geom = schema.getGeometryDescriptor(); return geom.getType().getCoordinateReferenceSystem(); } else { - GeometryDescriptor geom = (GeometryDescriptor) schema.getDescriptor( geomName ); + GeometryDescriptor geom = (GeometryDescriptor) geomName.evaluate(schema); return geom.getType().getCoordinateReferenceSystem(); } } |
From: <svn...@os...> - 2012-04-03 10:58:21
|
Author: aaime Date: 2012-04-03 03:58:10 -0700 (Tue, 03 Apr 2012) New Revision: 38656 Modified: trunk/docs/user/library/jdbc/oracle.rst Log: Docs about the geom metadata table added Modified: trunk/docs/user/library/jdbc/oracle.rst =================================================================== --- trunk/docs/user/library/jdbc/oracle.rst 2012-04-03 10:49:34 UTC (rev 38655) +++ trunk/docs/user/library/jdbc/oracle.rst 2012-04-03 10:58:10 UTC (rev 38656) @@ -58,11 +58,51 @@ | "Estimated extends" | Use the spatial index information to quickly | | | get an estimate of the data bounds | +---------------------+------------------------------------------------+ +| "Geometry metadata | An alternative table where geometry | +| table" | metadata information can be looked up | ++---------------------+------------------------------------------------+ + Example use:: params.put(PostgisDataStoreFactory.LOOSEBBOX, true ); + + +Geometry metadata table +^^^^^^^^^^^^^^^^^^^^^^^ +The Oracle data store will, by default, look into the ``MDSYS.USER_SDO*`` and ``MDSYS.ALL_SDO*`` views +to determine the geometry type and native SRID of each geometry column. +Those views are automatically populated with information about the geometry columns stored in tables that the current +user owns (for the ``MDSYS.USER_SDO*`` views) or can otherwise access (for the ``MDSYS.ALL_SDO*`` views). + +There are a few hiccups in this process: + + * if the connection pool user cannot access the tables (because impersonation is being used) + the MDSYS views will be empty, making it impossible to determine either the geometry type and the native SRID + * the geometry type can be specified only while building the spatial indexes, as a index constraint, however + such information is often not included when creating the indexes + * the views are populated dynamically based on the current user, if the database has thousands of tables and users + the views can become very slow + +Starting with GeoTools 2.7.5 the database administrator can address the above issues by manually creating a geometry metadata table +describing each geometry column, and then indicate its presence among the Oracle data store connection parameter named *Geometry metadata table* +(either as a simple table name, or a schema qualified one). +The table has the following structure (the table name is free, just indicate the one chosen in the data store connection parameter):: + + CREATE TABLE GEOMETRY_COLUMNS( + F_TABLE_SCHEMA VARCHAR(30) NOT NULL, + F_TABLE_NAME VARCHAR(30) NOT NULL, + F_GEOMETRY_COLUMN VARCHAR(30) NOT NULL, + COORD_DIMENSION INTEGER, + SRID INTEGER NOT NULL, + TYPE VARCHAR(30) NOT NULL, + UNIQUE(F_TABLE_SCHEMA, F_TABLE_NAME, F_GEOMETRY_COLUMN), + CHECK(TYPE IN ('POINT','LINE', 'POLYGON', 'COLLECTION', 'MULTIPOINT', 'MULTILINE', 'MULTIPOLYGON', 'GEOMETRY') )); + +When the table is present the store wil first search it for information about each geometry column +to be classified, and fall back on the MDSYS views only if such table does not contain any information. + Setup ^^^^^ |
From: <svn...@os...> - 2012-04-03 10:49:46
|
Author: aaime Date: 2012-04-03 03:49:34 -0700 (Tue, 03 Apr 2012) New Revision: 38655 Modified: trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java Log: [GEOT-4097] Add a geometry metadata table option to the oracle data store factory Modified: trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java 2012-04-03 10:38:58 UTC (rev 38654) +++ trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java 2012-04-03 10:49:34 UTC (rev 38655) @@ -141,6 +141,12 @@ * Remembers whether the USER_SDO_* views could be accessed or not */ Boolean canAccessUserViews; + + /** + * The direct geometry metadata table, if any + * @param dataStore + */ + String geometryMetadataTable; public OracleDialect(JDBCDataStore dataStore) { super(dataStore); @@ -205,88 +211,138 @@ final int TYPE_NAME = 6; String typeName = columnMetaData.getString(TYPE_NAME); if (typeName.equals("SDO_GEOMETRY")) { - String tableName = columnMetaData.getString(TABLE_NAME); - String columnName = columnMetaData.getString(COLUMN_NAME); - String schema = dataStore.getDatabaseSchema(); + String tableName = columnMetaData.getString(TABLE_NAME); + String columnName = columnMetaData.getString(COLUMN_NAME); + String schema = dataStore.getDatabaseSchema(); - if (canAccessUserViews(cx)) { - //we only try this block if we are able to access the - //user_sdo views + Class geometryClass = lookupGeometryOnMetadataTable(cx, tableName, columnName, schema); + if (geometryClass == null) { + lookupGeometryClassOnUserIndex(cx, tableName, columnName, schema); + } + if (geometryClass == null) { + geometryClass = lookupGeometryClassOnAllIndex(cx, tableName, columnName, schema); + } + if (geometryClass == null) { + geometryClass = Geometry.class; + } - //setup the sql to use for the USER_SDO table - String userSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + - "FROM ALL_INDEXES INFO\n" + - "INNER JOIN MDSYS.USER_SDO_INDEX_METADATA META\n" + - "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + - "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + - "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; + return geometryClass; + } else { + // if we know, return non null value, otherwise returning + // null will force the datatore to figure it out using + // jdbc metadata + return TYPES_TO_CLASSES.get(typeName); + } + } + + /** + * Tries to use the geometry metadata table, if available + * @param cx + * @param tableName + * @param columnName + * @param schema + * @return + * @throws SQLException + */ + private Class<?> lookupGeometryOnMetadataTable(Connection cx, String tableName, + String columnName, String schema) throws SQLException { + if(geometryMetadataTable == null) { + return null; + } + + // setup the sql to use for the ALL_SDO table + String metadataTableStatement = "SELECT TYPE FROM " + geometryMetadataTable + + " WHERE F_TABLE_NAME = '" + tableName + "'" + + " AND F_GEOMETRY_COLUMN = '" + columnName + "'"; - if(schema != null && !"".equals(schema)) { - userSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; - } + if(schema != null && !"".equals(schema)) { + metadataTableStatement += " AND F_TABLE_SCHEMA = '" + schema + "'"; + } + + return readGeometryClassFromStatement(cx, metadataTableStatement); + } - Statement userSdoStatement = null; - ResultSet userSdoResult = null; - try { - userSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "Geometry type check; {0} ", userSdoSqlStatement); - userSdoResult = userSdoStatement.executeQuery(userSdoSqlStatement); - if (userSdoResult.next()) { - String gType = userSdoResult.getString(1); - Class geometryClass = (Class) TT.GEOM_CLASSES.get(gType); - if(geometryClass == null) - geometryClass = Geometry.class; + /** + * Looks up the geometry type on the "ALL_*" metadata views + */ + private Class<?> lookupGeometryClassOnAllIndex(Connection cx, String tableName, + String columnName, String schema) throws SQLException { + // setup the sql to use for the ALL_SDO table + String allSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + + "FROM ALL_INDEXES INFO\n" + + "INNER JOIN MDSYS.ALL_SDO_INDEX_METADATA META\n" + + "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + + "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + + "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; - return geometryClass; - } - } finally { - dataStore.closeSafe(userSdoResult); - dataStore.closeSafe(userSdoStatement); - } - } + if(schema != null && !"".equals(schema)) { + allSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; + allSdoSqlStatement += " AND META.SDO_INDEX_OWNER = '" + schema + "'"; + } + + return readGeometryClassFromStatement(cx, allSdoSqlStatement); + } - Statement allSdoStatement = null; - ResultSet allSdoResult = null; - try { - //setup the sql to use for the ALL_SDO table - String allSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + - "FROM ALL_INDEXES INFO\n" + - "INNER JOIN MDSYS.ALL_SDO_INDEX_METADATA META\n" + - "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + - "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + - "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; + /** + * Looks up the geometry type on the "USER_*" metadata views + */ - if(schema != null && !"".equals(schema)) { - allSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; - allSdoSqlStatement += " AND META.SDO_INDEX_OWNER = '" + schema + "'"; - } + private Class lookupGeometryClassOnUserIndex(Connection cx, String tableName, String columnName, + String schema) throws SQLException { + // we only try this if we are able to access the + // user_sdo views + if (!canAccessUserViews(cx)) { + return null; + } + + //setup the sql to use for the USER_SDO table + String userSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + + "FROM ALL_INDEXES INFO\n" + + "INNER JOIN MDSYS.USER_SDO_INDEX_METADATA META\n" + + "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + + "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + + "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; - allSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "Geometry type check; {0} ", allSdoSqlStatement); - allSdoResult = allSdoStatement.executeQuery(allSdoSqlStatement); - if (allSdoResult.next()) { - String gType = allSdoResult.getString(1); - Class geometryClass = (Class) TT.GEOM_CLASSES.get(gType); - if(geometryClass == null) - geometryClass = Geometry.class; + if(schema != null && !"".equals(schema)) { + userSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; + } - return geometryClass; - } else { - //must default at this point, this is as far as we can go - return Geometry.class; - } + return readGeometryClassFromStatement(cx, userSdoSqlStatement); + } + + /** + * Reads the geometry type from the first column returned by executing the specified SQL statement + * @param cx + * @param sql + * @return + * @throws SQLException + */ + private Class readGeometryClassFromStatement(Connection cx, String sql) + throws SQLException { + Statement st = null; + ResultSet rs = null; + try { + st = cx.createStatement(); + LOGGER.log(Level.FINE, "Geometry type check; {0} ", sql); + rs = st.executeQuery(sql); + if (rs.next()) { + String gType = rs.getString(1); + Class geometryClass = (Class) TT.GEOM_CLASSES.get(gType); + if(geometryClass == null) { + // if there was a record but it's not a recognized geometry type fall back on + // geometry for backwards compatibility, but at least log the info + LOGGER.log(Level.WARNING, "Unrecognized geometry type " + gType + " falling back on generic 'GEOMETRY'"); + geometryClass = Geometry.class; + } - } finally { - dataStore.closeSafe(allSdoResult); - dataStore.closeSafe(allSdoStatement); - } - - } else { - // if we know, return non null value, otherwise returning - // null will force the datatore to figure it out using - // jdbc metadata - return TYPES_TO_CLASSES.get(typeName); - } + return geometryClass; + } + } finally { + dataStore.closeSafe(rs); + dataStore.closeSafe(st); + } + + return null; } @@ -515,56 +571,93 @@ public Integer getGeometrySRID(String schemaName, String tableName, String columnName, Connection cx) throws SQLException { - if (canAccessUserViews(cx)) { - StringBuffer userSdoSql = new StringBuffer("SELECT SRID FROM MDSYS.USER_SDO_GEOM_METADATA WHERE "); - userSdoSql.append( "TABLE_NAME='").append( tableName.toUpperCase() ).append("' AND "); - userSdoSql.append( "COLUMN_NAME='").append( columnName.toUpperCase() ).append( "'"); + Integer srid = lookupSRIDOnMetadataTable(schemaName, tableName, columnName, cx); + if(srid == null) { + srid = lookupSRIDFromUserViews(tableName, columnName, cx); + } + if(srid == null) { + srid = lookupSRIDFromAllViews(schemaName, tableName, columnName, cx); + } + return srid; + } - Statement userSdoStatement = null; - ResultSet userSdoResult = null; - try { - userSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "SRID check; {0} ", userSdoSql.toString()); - userSdoResult = userSdoStatement.executeQuery(userSdoSql.toString()); - if (userSdoResult.next()) { - Object srid = userSdoResult.getObject( 1 ); - if ( srid != null ) { - //return the SRID number if it was found in the USER_SDO - return ((Number) srid).intValue(); - } - } - } finally { - dataStore.closeSafe(userSdoResult); - dataStore.closeSafe(userSdoStatement); - } + /** + * Reads the SRID from the geometry metadata table, if available + */ + private Integer lookupSRIDOnMetadataTable(String schema, String tableName, String columnName, Connection cx) throws SQLException { + if(geometryMetadataTable == null) { + return null; } + + // setup the sql to use for the ALL_SDO table + String metadataTableStatement = "SELECT SRID FROM " + geometryMetadataTable + + " WHERE F_TABLE_NAME = '" + tableName + "'" + + " AND F_GEOMETRY_COLUMN = '" + columnName + "'"; + if(schema != null && !"".equals(schema)) { + metadataTableStatement += " AND F_TABLE_SCHEMA = '" + schema + "'"; + } + + return readSRIDFromStatement(cx, metadataTableStatement); + } + + /** + * Reads the SRID from the SDO_ALL* views + */ + private Integer lookupSRIDFromAllViews(String schemaName, String tableName, String columnName, + Connection cx) throws SQLException { StringBuffer allSdoSql = new StringBuffer("SELECT SRID FROM MDSYS.ALL_SDO_GEOM_METADATA WHERE "); allSdoSql.append( "TABLE_NAME='").append( tableName.toUpperCase() ).append("' AND "); allSdoSql.append( "COLUMN_NAME='").append( columnName.toUpperCase() ).append( "'"); - if(schemaName != null) + if(schemaName != null) { allSdoSql.append(" AND OWNER='" + schemaName + "'"); + } - Statement allSdoStatement = null; - ResultSet allSdoResult = null; + return readSRIDFromStatement(cx, allSdoSql.toString()); + } + + /** + * Reads the SRID from the SDO_USER* views + * @param tableName + * @param columnName + * @param cx + * @return + * @throws SQLException + */ + private Integer lookupSRIDFromUserViews(String tableName, String columnName, Connection cx) + throws SQLException { + // we run this only if we can access the user views + if (!canAccessUserViews(cx)) { + return null; + } + + StringBuffer userSdoSql = new StringBuffer("SELECT SRID FROM MDSYS.USER_SDO_GEOM_METADATA WHERE "); + userSdoSql.append( "TABLE_NAME='").append( tableName.toUpperCase() ).append("' AND "); + userSdoSql.append( "COLUMN_NAME='").append( columnName.toUpperCase() ).append( "'"); + + return readSRIDFromStatement(cx, userSdoSql.toString()); + } + + private Integer readSRIDFromStatement(Connection cx, String sql) throws SQLException { + Statement userSdoStatement = null; + ResultSet userSdoResult = null; try { - allSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "SRID check; {0} ", allSdoSql.toString()); - allSdoResult = allSdoStatement.executeQuery(allSdoSql.toString()); - if (allSdoResult.next()) { - Object srid = allSdoResult.getObject( 1 ); - if ( srid == null ) { - return null; + userSdoStatement = cx.createStatement(); + LOGGER.log(Level.FINE, "SRID check; {0} ", sql); + userSdoResult = userSdoStatement.executeQuery(sql); + if (userSdoResult.next()) { + Object srid = userSdoResult.getObject( 1 ); + if ( srid != null ) { + //return the SRID number if it was found in the USER_SDO + return ((Number) srid).intValue(); } - //return the SRID number if it was found in the ALL_SDO - return ((Number) srid).intValue(); - } else { - return null; } } finally { - dataStore.closeSafe(allSdoResult); - dataStore.closeSafe(allSdoStatement); + dataStore.closeSafe(userSdoResult); + dataStore.closeSafe(userSdoStatement); } + + return null; } @Override @@ -944,4 +1037,20 @@ } } + /** + * The geometry metadata table in use, if any + * @return + */ + public String getGeometryMetadataTable() { + return geometryMetadataTable; + } + + /** + * Sets the geometry metadata table + * @param geometryMetadataTable + */ + public void setGeometryMetadataTable(String geometryMetadataTable) { + this.geometryMetadataTable = geometryMetadataTable; + } + } Modified: trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java 2012-04-03 10:38:58 UTC (rev 38654) +++ trunk/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java 2012-04-03 10:49:34 UTC (rev 38655) @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.Map; -import org.geotools.data.DataAccessFactory.Param; import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.JDBCDataStoreFactory; import org.geotools.jdbc.SQLDialect; @@ -55,6 +54,10 @@ /** parameter for namespace of the datastore */ public static final Param LOOSEBBOX = new Param("Loose bbox", Boolean.class, "Perform only primary filter on bbox", false, Boolean.TRUE); + /** Metadata table providing information about primary keys **/ + public static final Param GEOMETRY_METADATA_TABLE = new Param("Geometry metadata table", String.class, + "The optional table containing geometry metadata (geometry type and srid). Can be expressed as 'schema.name' or just 'name'", false); + @Override protected SQLDialect createSQLDialect(JDBCDataStore dataStore) { return new OracleDialect(dataStore); @@ -104,8 +107,9 @@ throws IOException { // make the schema uppercase if it's not already - if(dataStore.getDatabaseSchema() != null) + if(dataStore.getDatabaseSchema() != null) { dataStore.setDatabaseSchema(dataStore.getDatabaseSchema().toUpperCase()); + } // setup loose bbox OracleDialect dialect = (OracleDialect) dataStore.getSQLDialect(); @@ -116,6 +120,10 @@ Boolean estimated = (Boolean) ESTIMATED_EXTENTS.lookUp(params); dialect.setEstimatedExtentsEnabled(estimated == null || Boolean.TRUE.equals(estimated)); + // check the geometry metadata table + String metadataTable = (String) GEOMETRY_METADATA_TABLE.lookUp(params); + dialect.setGeometryMetadataTable(metadataTable); + // setup proper fetch size dataStore.setFetchSize(200); @@ -151,10 +159,11 @@ parameters.put(HOST.key, HOST); parameters.put(DATABASE.key, DATABASE); parameters.put(DBTYPE.key, DBTYPE); + parameters.put(GEOMETRY_METADATA_TABLE.key, GEOMETRY_METADATA_TABLE); } @Override protected String getValidationQuery() { - return "select sysdate from dual"; + return "select 1 from dual"; } } Modified: trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java 2012-04-03 10:38:58 UTC (rev 38654) +++ trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java 2012-04-03 10:49:34 UTC (rev 38655) @@ -19,11 +19,14 @@ import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.jdbc.JDBCGeometryTest; import org.geotools.jdbc.JDBCGeometryTestSetup; +import org.geotools.referencing.CRS; import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.type.GeometryDescriptor; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; +import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.io.WKTReader; /** @@ -32,10 +35,13 @@ * @source $URL$ */ public class OracleGeometryTest extends JDBCGeometryTest { + + OracleGeometryTestSetup testSetup; @Override protected JDBCGeometryTestSetup createTestSetup() { - return new OracleGeometryTestSetup(); + testSetup = new OracleGeometryTestSetup(); + return testSetup; } public void testLinearRing() throws Exception { @@ -51,4 +57,12 @@ assertTrue(expected.equalsTopo((Geometry) sf.getDefaultGeometry())); fi.close(); } + + public void testGeometryMetadataTable() throws Exception { + testSetup.setupGeometryColumns(dataStore); + + GeometryDescriptor gd = dataStore.getFeatureSource("GTMETA").getSchema().getGeometryDescriptor(); + assertEquals(Point.class, gd.getType().getBinding()); + assertEquals(4269, (int) CRS.lookupEpsgCode(gd.getCoordinateReferenceSystem(), false)); + } } Modified: trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java 2012-04-03 10:38:58 UTC (rev 38654) +++ trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java 2012-04-03 10:49:34 UTC (rev 38655) @@ -16,6 +16,7 @@ */ package org.geotools.data.oracle; +import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.JDBCGeometryTestSetup; /** @@ -35,7 +36,10 @@ // clean up runSafe("DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = 'COLA_MARKETS_CS'" ); + runSafe("DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = 'GTMETA'" ); runSafe("DROP TABLE COLA_MARKETS_CS PURGE"); + runSafe("DROP TABLE GTMETA PURGE"); + runSafe("DROP TABLE GEOMETRY_COLUMNS PURGE"); // create the cola markets table run("CREATE TABLE cola_markets_cs (" + @@ -75,6 +79,23 @@ " SDO_ORDINATE_ARRAY(6,6, 12,6, 9,8, 6,10, 12,10, 6,4, 12,12)" + " )" + ")"); + + String sql = "CREATE TABLE gtmeta (" + + "id INT, geometry MDSYS.SDO_GEOMETRY, intProperty INT, " + + "doubleProperty FLOAT, stringProperty VARCHAR(255))"; + run(sql); + + sql = "INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID ) " + + "VALUES ('GTMETA','GEOMETRY',MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-180,180,0.5), " + + "MDSYS.SDO_DIM_ELEMENT('Y',-90,90,0.5)), 4326)"; + run(sql); + + sql = "CREATE INDEX GTMETA_GEOMETRY_IDX ON GTMETA(GEOMETRY) INDEXTYPE IS MDSYS.SPATIAL_INDEX"; + run(sql); + + sql = "INSERT INTO GTMETA VALUES (0," + + "MDSYS.SDO_GEOMETRY(2001,4326,SDO_POINT_TYPE(0.0,0.0,NULL),NULL,NULL), 0, 0.0,'zero')"; + run(sql); } @Override @@ -84,4 +105,19 @@ + "'"); } + public void setupGeometryColumns(JDBCDataStore dataStore) throws Exception { + String schema = dataStore.getDatabaseSchema(); + + String sql = "CREATE TABLE GEOMETRY_COLUMNS(F_TABLE_SCHEMA VARCHAR(30), F_TABLE_NAME VARCHAR(30), " + + "F_GEOMETRY_COLUMN VARCHAR(30), COORD_DIMENSION INTEGER, SRID INTEGER, TYPE VARCHAR(30))"; + run(sql); + + // register it in the override table with a different srs, so that we're sure it's getting read + sql = "INSERT INTO GEOMETRY_COLUMNS (F_TABLE_SCHEMA, F_TABLE_NAME, F_GEOMETRY_COLUMN, COORD_DIMENSION, SRID, TYPE) " + + "VALUES ('" + schema + "', 'GTMETA','GEOMETRY', 2, 4269, 'POINT')"; + run(sql); + + ((OracleDialect) dataStore.getSQLDialect()).setGeometryMetadataTable("GEOMETRY_COLUMNS"); + } + } Modified: trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java 2012-04-03 10:38:58 UTC (rev 38654) +++ trunk/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java 2012-04-03 10:49:34 UTC (rev 38655) @@ -16,12 +16,8 @@ */ package org.geotools.data.oracle; -import static org.geotools.jdbc.JDBCDataStoreFactory.DATABASE; -import static org.geotools.jdbc.JDBCDataStoreFactory.DBTYPE; -import static org.geotools.jdbc.JDBCDataStoreFactory.HOST; -import static org.geotools.jdbc.JDBCDataStoreFactory.PASSWD; -import static org.geotools.jdbc.JDBCDataStoreFactory.PORT; -import static org.geotools.jdbc.JDBCDataStoreFactory.USER; +import static org.geotools.data.oracle.OracleNGDataStoreFactory.GEOMETRY_METADATA_TABLE; +import static org.geotools.jdbc.JDBCDataStoreFactory.*; import java.io.IOException; import java.util.HashMap; @@ -31,6 +27,7 @@ import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.JDBCTestSetup; import org.geotools.jdbc.JDBCTestSupport; +import org.geotools.jdbc.SQLDialect; import org.geotools.test.FixtureUtilities; /** @@ -54,7 +51,33 @@ OracleNGDataStoreFactory factory = new OracleNGDataStoreFactory(); checkCreateConnection(factory, "oracle"); } + + public void testGeometryMetadata() throws IOException { + OracleNGDataStoreFactory factory = new OracleNGDataStoreFactory(); + Properties db = FixtureUtilities.loadFixture("oracle"); + Map<String, Object> params = new HashMap<String, Object>(); + params.put(HOST.key, db.getProperty(HOST.key)); + params.put(DATABASE.key, db.getProperty(DATABASE.key)); + params.put(PORT.key, db.getProperty(PORT.key)); + params.put(USER.key, db.getProperty(USER.key)); + params.put(PASSWD.key, db.getProperty("password")); + params.put(DBTYPE.key, "oracle"); + params.put(GEOMETRY_METADATA_TABLE.key, "geometry_columns_test"); + assertTrue(factory.canProcess(params)); + JDBCDataStore store = factory.createDataStore(params); + assertNotNull(store); + try { + // check dialect + OracleDialect dialect = (OracleDialect) store.getSQLDialect(); + + // check the metadata table has been set (other tests check it's actually working) + assertEquals("geometry_columns_test", dialect.getGeometryMetadataTable()); + } finally { + store.dispose(); + } + } + private void checkCreateConnection(OracleNGDataStoreFactory factory, String dbtype) throws IOException { Properties db = FixtureUtilities.loadFixture("oracle"); Map<String, Object> params = new HashMap<String, Object>(); @@ -63,7 +86,6 @@ params.put(PORT.key, db.getProperty(PORT.key)); params.put(USER.key, db.getProperty(USER.key)); params.put(PASSWD.key, db.getProperty("password")); - params.put(DBTYPE.key, dbtype); assertTrue(factory.canProcess(params)); @@ -78,5 +100,7 @@ store.dispose(); } } + + } |
From: <svn...@os...> - 2012-04-03 10:39:09
|
Author: aaime Date: 2012-04-03 03:38:58 -0700 (Tue, 03 Apr 2012) New Revision: 38654 Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java Log: [GEOT-4097] Add a geometry metadata table option to the oracle data store factory Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java 2012-03-29 15:28:04 UTC (rev 38653) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleDialect.java 2012-04-03 10:38:58 UTC (rev 38654) @@ -140,6 +140,12 @@ * Remembers whether the USER_SDO_* views could be accessed or not */ Boolean canAccessUserViews; + + /** + * The direct geometry metadata table, if any + * @param dataStore + */ + String geometryMetadataTable; public OracleDialect(JDBCDataStore dataStore) { super(dataStore); @@ -204,88 +210,138 @@ final int TYPE_NAME = 6; String typeName = columnMetaData.getString(TYPE_NAME); if (typeName.equals("SDO_GEOMETRY")) { - String tableName = columnMetaData.getString(TABLE_NAME); - String columnName = columnMetaData.getString(COLUMN_NAME); - String schema = dataStore.getDatabaseSchema(); + String tableName = columnMetaData.getString(TABLE_NAME); + String columnName = columnMetaData.getString(COLUMN_NAME); + String schema = dataStore.getDatabaseSchema(); - if (canAccessUserViews(cx)) { - //we only try this block if we are able to access the - //user_sdo views + Class geometryClass = lookupGeometryOnMetadataTable(cx, tableName, columnName, schema); + if (geometryClass == null) { + lookupGeometryClassOnUserIndex(cx, tableName, columnName, schema); + } + if (geometryClass == null) { + geometryClass = lookupGeometryClassOnAllIndex(cx, tableName, columnName, schema); + } + if (geometryClass == null) { + geometryClass = Geometry.class; + } - //setup the sql to use for the USER_SDO table - String userSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + - "FROM ALL_INDEXES INFO\n" + - "INNER JOIN MDSYS.USER_SDO_INDEX_METADATA META\n" + - "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + - "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + - "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; + return geometryClass; + } else { + // if we know, return non null value, otherwise returning + // null will force the datatore to figure it out using + // jdbc metadata + return TYPES_TO_CLASSES.get(typeName); + } + } + + /** + * Tries to use the geometry metadata table, if available + * @param cx + * @param tableName + * @param columnName + * @param schema + * @return + * @throws SQLException + */ + private Class<?> lookupGeometryOnMetadataTable(Connection cx, String tableName, + String columnName, String schema) throws SQLException { + if(geometryMetadataTable == null) { + return null; + } + + // setup the sql to use for the ALL_SDO table + String metadataTableStatement = "SELECT TYPE FROM " + geometryMetadataTable + + " WHERE F_TABLE_NAME = '" + tableName + "'" + + " AND F_GEOMETRY_COLUMN = '" + columnName + "'"; - if(schema != null && !"".equals(schema)) { - userSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; - } + if(schema != null && !"".equals(schema)) { + metadataTableStatement += " AND F_TABLE_SCHEMA = '" + schema + "'"; + } + + return readGeometryClassFromStatement(cx, metadataTableStatement); + } - Statement userSdoStatement = null; - ResultSet userSdoResult = null; - try { - userSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "Geometry type check; {0} ", userSdoSqlStatement); - userSdoResult = userSdoStatement.executeQuery(userSdoSqlStatement); - if (userSdoResult.next()) { - String gType = userSdoResult.getString(1); - Class geometryClass = (Class) TT.GEOM_CLASSES.get(gType); - if(geometryClass == null) - geometryClass = Geometry.class; + /** + * Looks up the geometry type on the "ALL_*" metadata views + */ + private Class<?> lookupGeometryClassOnAllIndex(Connection cx, String tableName, + String columnName, String schema) throws SQLException { + // setup the sql to use for the ALL_SDO table + String allSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + + "FROM ALL_INDEXES INFO\n" + + "INNER JOIN MDSYS.ALL_SDO_INDEX_METADATA META\n" + + "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + + "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + + "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; - return geometryClass; - } - } finally { - dataStore.closeSafe(userSdoResult); - dataStore.closeSafe(userSdoStatement); - } - } + if(schema != null && !"".equals(schema)) { + allSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; + allSdoSqlStatement += " AND META.SDO_INDEX_OWNER = '" + schema + "'"; + } + + return readGeometryClassFromStatement(cx, allSdoSqlStatement); + } - Statement allSdoStatement = null; - ResultSet allSdoResult = null; - try { - //setup the sql to use for the ALL_SDO table - String allSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + - "FROM ALL_INDEXES INFO\n" + - "INNER JOIN MDSYS.ALL_SDO_INDEX_METADATA META\n" + - "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + - "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + - "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; + /** + * Looks up the geometry type on the "USER_*" metadata views + */ - if(schema != null && !"".equals(schema)) { - allSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; - allSdoSqlStatement += " AND META.SDO_INDEX_OWNER = '" + schema + "'"; - } + private Class lookupGeometryClassOnUserIndex(Connection cx, String tableName, String columnName, + String schema) throws SQLException { + // we only try this if we are able to access the + // user_sdo views + if (!canAccessUserViews(cx)) { + return null; + } + + //setup the sql to use for the USER_SDO table + String userSdoSqlStatement = "SELECT META.SDO_LAYER_GTYPE\n" + + "FROM ALL_INDEXES INFO\n" + + "INNER JOIN MDSYS.USER_SDO_INDEX_METADATA META\n" + + "ON INFO.INDEX_NAME = META.SDO_INDEX_NAME\n" + + "WHERE INFO.TABLE_NAME = '" + tableName + "'\n" + + "AND REPLACE(meta.sdo_column_name, '\"') = '" + columnName + "'\n"; - allSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "Geometry type check; {0} ", allSdoSqlStatement); - allSdoResult = allSdoStatement.executeQuery(allSdoSqlStatement); - if (allSdoResult.next()) { - String gType = allSdoResult.getString(1); - Class geometryClass = (Class) TT.GEOM_CLASSES.get(gType); - if(geometryClass == null) - geometryClass = Geometry.class; + if(schema != null && !"".equals(schema)) { + userSdoSqlStatement += " AND INFO.TABLE_OWNER = '" + schema + "'"; + } - return geometryClass; - } else { - //must default at this point, this is as far as we can go - return Geometry.class; - } + return readGeometryClassFromStatement(cx, userSdoSqlStatement); + } + + /** + * Reads the geometry type from the first column returned by executing the specified SQL statement + * @param cx + * @param sql + * @return + * @throws SQLException + */ + private Class readGeometryClassFromStatement(Connection cx, String sql) + throws SQLException { + Statement st = null; + ResultSet rs = null; + try { + st = cx.createStatement(); + LOGGER.log(Level.FINE, "Geometry type check; {0} ", sql); + rs = st.executeQuery(sql); + if (rs.next()) { + String gType = rs.getString(1); + Class geometryClass = (Class) TT.GEOM_CLASSES.get(gType); + if(geometryClass == null) { + // if there was a record but it's not a recognized geometry type fall back on + // geometry for backwards compatibility, but at least log the info + LOGGER.log(Level.WARNING, "Unrecognized geometry type " + gType + " falling back on generic 'GEOMETRY'"); + geometryClass = Geometry.class; + } - } finally { - dataStore.closeSafe(allSdoResult); - dataStore.closeSafe(allSdoStatement); - } - - } else { - // if we know, return non null value, otherwise returning - // null will force the datatore to figure it out using - // jdbc metadata - return TYPES_TO_CLASSES.get(typeName); - } + return geometryClass; + } + } finally { + dataStore.closeSafe(rs); + dataStore.closeSafe(st); + } + + return null; } @@ -506,56 +562,93 @@ public Integer getGeometrySRID(String schemaName, String tableName, String columnName, Connection cx) throws SQLException { - if (canAccessUserViews(cx)) { - StringBuffer userSdoSql = new StringBuffer("SELECT SRID FROM MDSYS.USER_SDO_GEOM_METADATA WHERE "); - userSdoSql.append( "TABLE_NAME='").append( tableName.toUpperCase() ).append("' AND "); - userSdoSql.append( "COLUMN_NAME='").append( columnName.toUpperCase() ).append( "'"); + Integer srid = lookupSRIDOnMetadataTable(schemaName, tableName, columnName, cx); + if(srid == null) { + srid = lookupSRIDFromUserViews(tableName, columnName, cx); + } + if(srid == null) { + srid = lookupSRIDFromAllViews(schemaName, tableName, columnName, cx); + } + return srid; + } - Statement userSdoStatement = null; - ResultSet userSdoResult = null; - try { - userSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "SRID check; {0} ", userSdoSql.toString()); - userSdoResult = userSdoStatement.executeQuery(userSdoSql.toString()); - if (userSdoResult.next()) { - Object srid = userSdoResult.getObject( 1 ); - if ( srid != null ) { - //return the SRID number if it was found in the USER_SDO - return ((Number) srid).intValue(); - } - } - } finally { - dataStore.closeSafe(userSdoResult); - dataStore.closeSafe(userSdoStatement); - } + /** + * Reads the SRID from the geometry metadata table, if available + */ + private Integer lookupSRIDOnMetadataTable(String schema, String tableName, String columnName, Connection cx) throws SQLException { + if(geometryMetadataTable == null) { + return null; } + + // setup the sql to use for the ALL_SDO table + String metadataTableStatement = "SELECT SRID FROM " + geometryMetadataTable + + " WHERE F_TABLE_NAME = '" + tableName + "'" + + " AND F_GEOMETRY_COLUMN = '" + columnName + "'"; + if(schema != null && !"".equals(schema)) { + metadataTableStatement += " AND F_TABLE_SCHEMA = '" + schema + "'"; + } + + return readSRIDFromStatement(cx, metadataTableStatement); + } + + /** + * Reads the SRID from the SDO_ALL* views + */ + private Integer lookupSRIDFromAllViews(String schemaName, String tableName, String columnName, + Connection cx) throws SQLException { StringBuffer allSdoSql = new StringBuffer("SELECT SRID FROM MDSYS.ALL_SDO_GEOM_METADATA WHERE "); allSdoSql.append( "TABLE_NAME='").append( tableName.toUpperCase() ).append("' AND "); allSdoSql.append( "COLUMN_NAME='").append( columnName.toUpperCase() ).append( "'"); - if(schemaName != null) + if(schemaName != null) { allSdoSql.append(" AND OWNER='" + schemaName + "'"); + } - Statement allSdoStatement = null; - ResultSet allSdoResult = null; + return readSRIDFromStatement(cx, allSdoSql.toString()); + } + + /** + * Reads the SRID from the SDO_USER* views + * @param tableName + * @param columnName + * @param cx + * @return + * @throws SQLException + */ + private Integer lookupSRIDFromUserViews(String tableName, String columnName, Connection cx) + throws SQLException { + // we run this only if we can access the user views + if (!canAccessUserViews(cx)) { + return null; + } + + StringBuffer userSdoSql = new StringBuffer("SELECT SRID FROM MDSYS.USER_SDO_GEOM_METADATA WHERE "); + userSdoSql.append( "TABLE_NAME='").append( tableName.toUpperCase() ).append("' AND "); + userSdoSql.append( "COLUMN_NAME='").append( columnName.toUpperCase() ).append( "'"); + + return readSRIDFromStatement(cx, userSdoSql.toString()); + } + + private Integer readSRIDFromStatement(Connection cx, String sql) throws SQLException { + Statement userSdoStatement = null; + ResultSet userSdoResult = null; try { - allSdoStatement = cx.createStatement(); - LOGGER.log(Level.FINE, "SRID check; {0} ", allSdoSql.toString()); - allSdoResult = allSdoStatement.executeQuery(allSdoSql.toString()); - if (allSdoResult.next()) { - Object srid = allSdoResult.getObject( 1 ); - if ( srid == null ) { - return null; + userSdoStatement = cx.createStatement(); + LOGGER.log(Level.FINE, "SRID check; {0} ", sql); + userSdoResult = userSdoStatement.executeQuery(sql); + if (userSdoResult.next()) { + Object srid = userSdoResult.getObject( 1 ); + if ( srid != null ) { + //return the SRID number if it was found in the USER_SDO + return ((Number) srid).intValue(); } - //return the SRID number if it was found in the ALL_SDO - return ((Number) srid).intValue(); - } else { - return null; } } finally { - dataStore.closeSafe(allSdoResult); - dataStore.closeSafe(allSdoStatement); + dataStore.closeSafe(userSdoResult); + dataStore.closeSafe(userSdoStatement); } + + return null; } @Override @@ -935,4 +1028,20 @@ } } + /** + * The geometry metadata table in use, if any + * @return + */ + public String getGeometryMetadataTable() { + return geometryMetadataTable; + } + + /** + * Sets the geometry metadata table + * @param geometryMetadataTable + */ + public void setGeometryMetadataTable(String geometryMetadataTable) { + this.geometryMetadataTable = geometryMetadataTable; + } + } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java 2012-03-29 15:28:04 UTC (rev 38653) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/main/java/org/geotools/data/oracle/OracleNGDataStoreFactory.java 2012-04-03 10:38:58 UTC (rev 38654) @@ -19,7 +19,6 @@ import java.io.IOException; import java.util.Map; -import org.geotools.data.DataAccessFactory.Param; import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.JDBCDataStoreFactory; import org.geotools.jdbc.SQLDialect; @@ -54,6 +53,10 @@ /** parameter for namespace of the datastore */ public static final Param LOOSEBBOX = new Param("Loose bbox", Boolean.class, "Perform only primary filter on bbox", false, Boolean.TRUE); + /** Metadata table providing information about primary keys **/ + public static final Param GEOMETRY_METADATA_TABLE = new Param("Geometry metadata table", String.class, + "The optional table containing geometry metadata (geometry type and srid). Can be expressed as 'schema.name' or just 'name'", false); + @Override protected SQLDialect createSQLDialect(JDBCDataStore dataStore) { return new OracleDialect(dataStore); @@ -103,8 +106,9 @@ throws IOException { // make the schema uppercase if it's not already - if(dataStore.getDatabaseSchema() != null) + if(dataStore.getDatabaseSchema() != null) { dataStore.setDatabaseSchema(dataStore.getDatabaseSchema().toUpperCase()); + } // setup loose bbox OracleDialect dialect = (OracleDialect) dataStore.getSQLDialect(); @@ -115,6 +119,10 @@ Boolean estimated = (Boolean) ESTIMATED_EXTENTS.lookUp(params); dialect.setEstimatedExtentsEnabled(estimated == null || Boolean.TRUE.equals(estimated)); + // check the geometry metadata table + String metadataTable = (String) GEOMETRY_METADATA_TABLE.lookUp(params); + dialect.setGeometryMetadataTable(metadataTable); + // setup proper fetch size dataStore.setFetchSize(200); @@ -150,10 +158,11 @@ parameters.put(HOST.key, HOST); parameters.put(DATABASE.key, DATABASE); parameters.put(DBTYPE.key, DBTYPE); + parameters.put(GEOMETRY_METADATA_TABLE.key, GEOMETRY_METADATA_TABLE); } @Override protected String getValidationQuery() { - return "select sysdate from dual"; + return "select 1 from dual"; } } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java 2012-03-29 15:28:04 UTC (rev 38653) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTest.java 2012-04-03 10:38:58 UTC (rev 38654) @@ -19,18 +19,24 @@ import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.jdbc.JDBCGeometryTest; import org.geotools.jdbc.JDBCGeometryTestSetup; +import org.geotools.referencing.CRS; import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.type.GeometryDescriptor; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; +import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.io.WKTReader; public class OracleGeometryTest extends JDBCGeometryTest { + + OracleGeometryTestSetup testSetup; @Override protected JDBCGeometryTestSetup createTestSetup() { - return new OracleGeometryTestSetup(); + testSetup = new OracleGeometryTestSetup(); + return testSetup; } public void testLinearRing() throws Exception { @@ -46,4 +52,12 @@ assertTrue(expected.equals((Geometry) sf.getDefaultGeometry())); fi.close(); } + + public void testGeometryMetadataTable() throws Exception { + testSetup.setupGeometryColumns(dataStore); + + GeometryDescriptor gd = dataStore.getFeatureSource("GTMETA").getSchema().getGeometryDescriptor(); + assertEquals(Point.class, gd.getType().getBinding()); + assertEquals(4269, (int) CRS.lookupEpsgCode(gd.getCoordinateReferenceSystem(), false)); + } } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java 2012-03-29 15:28:04 UTC (rev 38653) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleGeometryTestSetup.java 2012-04-03 10:38:58 UTC (rev 38654) @@ -16,6 +16,7 @@ */ package org.geotools.data.oracle; +import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.JDBCGeometryTestSetup; public class OracleGeometryTestSetup extends JDBCGeometryTestSetup { @@ -30,7 +31,10 @@ // clean up runSafe("DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = 'COLA_MARKETS_CS'" ); + runSafe("DELETE FROM USER_SDO_GEOM_METADATA WHERE TABLE_NAME = 'GTMETA'" ); runSafe("DROP TABLE COLA_MARKETS_CS PURGE"); + runSafe("DROP TABLE GTMETA PURGE"); + runSafe("DROP TABLE GEOMETRY_COLUMNS PURGE"); // create the cola markets table run("CREATE TABLE cola_markets_cs (" + @@ -70,6 +74,23 @@ " SDO_ORDINATE_ARRAY(6,6, 12,6, 9,8, 6,10, 12,10, 6,4, 12,12)" + " )" + ")"); + + String sql = "CREATE TABLE gtmeta (" + + "id INT, geometry MDSYS.SDO_GEOMETRY, intProperty INT, " + + "doubleProperty FLOAT, stringProperty VARCHAR(255))"; + run(sql); + + sql = "INSERT INTO USER_SDO_GEOM_METADATA (TABLE_NAME, COLUMN_NAME, DIMINFO, SRID ) " + + "VALUES ('GTMETA','GEOMETRY',MDSYS.SDO_DIM_ARRAY(MDSYS.SDO_DIM_ELEMENT('X',-180,180,0.5), " + + "MDSYS.SDO_DIM_ELEMENT('Y',-90,90,0.5)), 4326)"; + run(sql); + + sql = "CREATE INDEX GTMETA_GEOMETRY_IDX ON GTMETA(GEOMETRY) INDEXTYPE IS MDSYS.SPATIAL_INDEX"; + run(sql); + + sql = "INSERT INTO GTMETA VALUES (0," + + "MDSYS.SDO_GEOMETRY(2001,4326,SDO_POINT_TYPE(0.0,0.0,NULL),NULL,NULL), 0, 0.0,'zero')"; + run(sql); } @Override @@ -79,4 +100,19 @@ + "'"); } + public void setupGeometryColumns(JDBCDataStore dataStore) throws Exception { + String schema = dataStore.getDatabaseSchema(); + + String sql = "CREATE TABLE GEOMETRY_COLUMNS(F_TABLE_SCHEMA VARCHAR(30), F_TABLE_NAME VARCHAR(30), " + + "F_GEOMETRY_COLUMN VARCHAR(30), COORD_DIMENSION INTEGER, SRID INTEGER, TYPE VARCHAR(30))"; + run(sql); + + // register it in the override table with a different srs, so that we're sure it's getting read + sql = "INSERT INTO GEOMETRY_COLUMNS (F_TABLE_SCHEMA, F_TABLE_NAME, F_GEOMETRY_COLUMN, COORD_DIMENSION, SRID, TYPE) " + + "VALUES ('" + schema + "', 'GTMETA','GEOMETRY', 2, 4269, 'POINT')"; + run(sql); + + ((OracleDialect) dataStore.getSQLDialect()).setGeometryMetadataTable("GEOMETRY_COLUMNS"); + } + } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java 2012-03-29 15:28:04 UTC (rev 38653) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-oracle/src/test/java/org/geotools/data/oracle/OracleNGDataStoreFactoryTest.java 2012-04-03 10:38:58 UTC (rev 38654) @@ -16,12 +16,8 @@ */ package org.geotools.data.oracle; -import static org.geotools.jdbc.JDBCDataStoreFactory.DATABASE; -import static org.geotools.jdbc.JDBCDataStoreFactory.DBTYPE; -import static org.geotools.jdbc.JDBCDataStoreFactory.HOST; -import static org.geotools.jdbc.JDBCDataStoreFactory.PASSWD; -import static org.geotools.jdbc.JDBCDataStoreFactory.PORT; -import static org.geotools.jdbc.JDBCDataStoreFactory.USER; +import static org.geotools.data.oracle.OracleNGDataStoreFactory.GEOMETRY_METADATA_TABLE; +import static org.geotools.jdbc.JDBCDataStoreFactory.*; import java.io.IOException; import java.util.HashMap; @@ -31,6 +27,7 @@ import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.JDBCTestSetup; import org.geotools.jdbc.JDBCTestSupport; +import org.geotools.jdbc.SQLDialect; import org.geotools.test.FixtureUtilities; public class OracleNGDataStoreFactoryTest extends JDBCTestSupport { @@ -49,7 +46,33 @@ OracleNGDataStoreFactory factory = new OracleNGDataStoreFactory(); checkCreateConnection(factory, "oracle"); } + + public void testGeometryMetadata() throws IOException { + OracleNGDataStoreFactory factory = new OracleNGDataStoreFactory(); + Properties db = FixtureUtilities.loadFixture("oracle"); + Map<String, Object> params = new HashMap<String, Object>(); + params.put(HOST.key, db.getProperty(HOST.key)); + params.put(DATABASE.key, db.getProperty(DATABASE.key)); + params.put(PORT.key, db.getProperty(PORT.key)); + params.put(USER.key, db.getProperty(USER.key)); + params.put(PASSWD.key, db.getProperty("password")); + params.put(DBTYPE.key, "oracle"); + params.put(GEOMETRY_METADATA_TABLE.key, "geometry_columns_test"); + assertTrue(factory.canProcess(params)); + JDBCDataStore store = factory.createDataStore(params); + assertNotNull(store); + try { + // check dialect + OracleDialect dialect = (OracleDialect) store.getSQLDialect(); + + // check the metadata table has been set (other tests check it's actually working) + assertEquals("geometry_columns_test", dialect.getGeometryMetadataTable()); + } finally { + store.dispose(); + } + } + private void checkCreateConnection(OracleNGDataStoreFactory factory, String dbtype) throws IOException { Properties db = FixtureUtilities.loadFixture("oracle"); Map<String, Object> params = new HashMap<String, Object>(); @@ -58,7 +81,6 @@ params.put(PORT.key, db.getProperty(PORT.key)); params.put(USER.key, db.getProperty(USER.key)); params.put(PASSWD.key, db.getProperty("password")); - params.put(DBTYPE.key, dbtype); assertTrue(factory.canProcess(params)); @@ -73,5 +95,7 @@ store.dispose(); } } + + } |
From: <svn...@os...> - 2012-03-29 15:28:14
|
Author: ang05a Date: 2012-03-29 08:28:04 -0700 (Thu, 29 Mar 2012) New Revision: 38653 Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java Log: Ensure isList in app-schema are sorted by natural order. Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-03-29 00:50:29 UTC (rev 38652) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-03-29 15:28:04 UTC (rev 38653) @@ -20,7 +20,9 @@ import java.io.IOException; import java.net.URI; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; +import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -30,6 +32,7 @@ import javax.xml.namespace.QName; +import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.lang.StringUtils; import org.geotools.data.DataAccess; import org.geotools.data.DataSourceException; @@ -89,6 +92,35 @@ * @since 2.4 */ public class DataAccessMappingFeatureIterator extends AbstractMappingFeatureIterator { + + class ValueComparator implements Comparator { + @Override + public int compare(Object o1, Object o2) { + if (o1 == null) { + if (o2 == null) { + return 0; + } else { + return -1; + } + } + if (o2 == null) { + return 1; + } + + String string1 = o1.toString(); + String string2 = o2.toString(); + + // in case numbers are stored as string, make sure the order is correct + if (NumberUtils.isNumber(string1) && NumberUtils.isNumber(string2)) { + return Double.valueOf(string1).compareTo(Double.valueOf(string2)); + } + + if (o1 instanceof Comparable) { + return ((Comparable) o1).compareTo(o2); + } + return string1.compareTo(string2); + } + } /** * Hold on to iterator to allow features to be streamed. */ @@ -119,6 +151,8 @@ private ArrayList<String> filteredFeatures; + private ValueComparator comparator; + public DataAccessMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, boolean isFiltered) throws IOException { this(store, mapping, query, null); @@ -827,7 +861,11 @@ for (Feature source : sources) { values[i] = getValue(sourceExpr, source); i++; + } + if (comparator == null) { + comparator = new ValueComparator(); } + Arrays.sort(values, comparator); String valueString = StringUtils.join(values, " "); StepList fullPath = attMapping.getTargetXPath(); StepList leafPath = fullPath.subList(fullPath.size() - 1, fullPath.size()); |
Author: jive Date: 2012-03-28 17:50:29 -0700 (Wed, 28 Mar 2012) New Revision: 38652 Removed: trunk/modules/unsupported/epsg-h2/pom.xml trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/DatabaseCreationScript.java trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/SqlScriptReader.java trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/ThreadedH2EpsgFactory.java trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.cs.CSAuthorityFactory trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.datum.DatumAuthorityFactory trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/EPSG.zip trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/EPSG_Indexes_H2.sql trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/README.txt trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/OrderedAxisAuthorityFactoryTest.java trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/epsg/DefaultFactoryTest.java trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/epsg/OperationFactoryTest.java trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/epsg/ThreadedH2EpsgFactoryTest.java trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/tools/LoadStresser.java trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/tools/Start.java trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/tools/ThreadedLoadStresser.java Modified: trunk/modules/unsupported/pom.xml Log: Remove gt-epsg-h2 as per GEOT-4095 Deleted: trunk/modules/unsupported/epsg-h2/pom.xml =================================================================== --- trunk/modules/unsupported/epsg-h2/pom.xml 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/pom.xml 2012-03-29 00:50:29 UTC (rev 38652) @@ -1,110 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- ======================================================================= - Maven Project Configuration File - - The Geotools Project - http://www.geotools.org/ - - Version: $Id: pom.xml 33188 2009-05-30 19:48:33Z aaime $ - ======================================================================= --> - <project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 - http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - - <parent> - <groupId>org.geotools</groupId> - <artifactId>unsupported</artifactId> - <version>8-SNAPSHOT</version> - </parent> - - - <!-- =========================================================== --> - <!-- Module Description --> - <!-- =========================================================== --> - <groupId>org.geotools</groupId> - <artifactId>gt-epsg-h2</artifactId> - <packaging>jar</packaging> - <name>EPSG Authority Service using H2 database</name> - - - <scm> - <connection> - scm:svn:http://svn.osgeo.org/geotools/trunk/modules/plugin/epsg-hsql/ - </connection> - <url>http://svn.osgeo.org/geotools/trunk/modules/plugin/epsg-hsql/</url> - </scm> - - <description> - Connection to an embedded EPSG database in HSQL format. - This database is built from the SQL scripts delivered by EPSG. - </description> - - <licenses> - <license> - <name>Lesser General Public License (LGPL)</name> - <!-- url>http://www.gnu.org/copyleft/lesser.txt</url --> - <url>http://svn.osgeo.org/geotools/trunk/modules/plugin/epsg-hsql/LICENSE.html</url> - <distribution>repo</distribution> - </license> - <license> - <name>EPSG database distribution license</name> - <url>http://svn.osgeo.org/geotools/trunk/licenses/EPSG.html</url> - <distribution>repo</distribution> - <comments> - This Geotools module is bundled with a copy of the EPSG database. The - data may be copied and distributed subject to the EPSG conditions. - </comments> - </license> - <license> - <name>MPL 1.1</name> - <url>http://www.h2database.com/html/license.html</url> - <distribution>repo</distribution> - <comments> - This Geotools module requires the H2 database engine, which is bundled - with the binary distribution only (there is no H2 derived work in the - Java source code). - </comments> - </license> - </licenses> - - - <!-- =========================================================== --> - <!-- Developers and Contributors --> - <!-- =========================================================== --> - <developers> - <developer> - <name>Andrea Aime</name> - <id>aaime</id> - <email>aa...@us...</email> - <roles> - <role>Java Developer</role> - <role>Module Maintainer</role> - </roles> - </developer> - </developers> - - - <!-- =========================================================== --> - <!-- Dependency Management --> - <!-- =========================================================== --> - <dependencies> - <dependency> - <groupId>org.geotools</groupId> - <artifactId>gt-referencing</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.geotools</groupId> - <artifactId>gt-sample-data</artifactId> - <version>${project.version}</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>com.h2database</groupId> - <artifactId>h2</artifactId> - </dependency> - </dependencies> - -</project> Deleted: trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/DatabaseCreationScript.java =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/DatabaseCreationScript.java 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/DatabaseCreationScript.java 2012-03-29 00:50:29 UTC (rev 38652) @@ -1,165 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2005-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.referencing.factory.epsg; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; - -import org.h2.jdbcx.JdbcDataSource; - -/** - * Utility used to create a HSQL zipped version of the official EPSG database - * - * - * - * - * @source $URL$ - */ -public class DatabaseCreationScript { - - public static void main(String[] args) throws Exception { - /** - * BEFORE USING THIS SCRIPT - * - make sure you've created modified .sql files following the instructions - * - update ThreadedH2EpsgFactory.VERSION - * - modify the "directory" variable below to point to the folder containing the SQL scripts - */ - String inputDirectory = "./src/main/resources/org/geotools/referencing/factory/epsg/"; - - /** - * The files we're interested into - */ - File directory = new File(inputDirectory); - File databaseFile = new File(directory, ThreadedH2EpsgFactory.DATABASE_NAME + ".data.db"); - File indexFile = new File(directory, ThreadedH2EpsgFactory.DATABASE_NAME + ".index.db"); - File lobDirectory = new File(directory, ThreadedH2EpsgFactory.DATABASE_NAME + ".lobs.db"); - File zipFile = new File(directory, ThreadedH2EpsgFactory.DATABASE_NAME + ".zip"); - - /** - * Preventive cleanup of the files should an old run was broken or stopped in the middle - */ - indexFile.delete(); - databaseFile.delete(); - zipFile.delete(); - - - /* - * Constructs the full path to the HSQL database. Note: we do not use - * File.toURI() because HSQL doesn't seem to expect an encoded URL - * (e.g. "%20" instead of spaces). - */ - final JdbcDataSource source = new JdbcDataSource(); - final StringBuilder url = new StringBuilder(ThreadedH2EpsgFactory.PREFIX); - final String path = directory.getAbsolutePath().replace(File.separatorChar, '/'); - if (path.length()==0 || path.charAt(0)!='/') { - url.append('/'); - } - url.append(path); - - if (url.charAt(url.length()-1) != '/') { - url.append('/'); - } - url.append(ThreadedH2EpsgFactory.DATABASE_NAME); - // no need for validation query, saves some work - url.append(";AUTO_RECONNECT=TRUE;CACHE_SIZE=131072;CACHE_TYPE=TQ"); - source.setURL((url.toString())); - source.setUser("sa"); - source.setPassword(""); - - Connection connection = source.getConnection(); - /* - * HSQL has created automatically an empty database. We need to populate it. Executes - * the SQL scripts bundled in the JAR. In theory, each line contains a full SQL - * statement. For this plugin however, we have compressed "INSERT INTO" statements using - * Compactor class in this package. - */ - System.out.println("Creating the EPSG database"); - final Statement statement = connection.createStatement(); - try { - // read and execute the scripts that make up the database - executeScript(new File(directory, "EPSG_Tables_PostgreSQL.sql"), statement); - executeScript(new File(directory, "EPSG_Data_PostgreSQL.sql"), statement); - // statement.execute("UPDATE EPSG_DATUM SET REALIZATION_EPOCH = NULL WHERE REALIZATION_EPOCH = ''"); - // statement.execute("ALTER TABLE EPSG_DATUM ALTER COLUMN REALIZATION_EPOCH INTEGER"); - executeScript(new File(directory, "EPSG_FKeys_PostgreSQL.sql"), statement); - executeScript(new File(directory, "EPSG_Indexes_H2.sql"), statement); - statement.execute("SHUTDOWN COMPACT"); - } catch (IOException exception) { - SQLException e = new SQLException("Error occurred while executing " - + "the EPSG database creation scripts"); - e.initCause(exception); - throw e; - } finally { - statement.close(); - connection.close(); - } - System.out.println("EPSG database created"); - - /* - * Zip the database - */ - System.out.println("Creating the zipped database"); - byte[] buf = new byte[1024]; - ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile)); - File[] files = new File[] {databaseFile, indexFile}; - for(File file : files) { - FileInputStream in = new FileInputStream(file); - - zos.putNextEntry(new ZipEntry(file.getName())); - int len; - while ((len = in.read(buf)) > 0) { - zos.write(buf, 0, len); - } - zos.closeEntry(); - in.close(); - } - zos.close(); - - /** - * Cleanup, delete the database files - */ - System.out.println("Cleaning up the unzipped database files"); - databaseFile.delete(); - indexFile.delete(); - - System.out.println("Done. The zipped database file is available at " + zipFile.getAbsolutePath()); - } - - static void executeScript(File scriptFile, Statement statement) throws IOException, SQLException { - System.out.println("Executing script " + scriptFile.getPath()); - SqlScriptReader reader = null; - try { - // first read in the tables - reader = new SqlScriptReader(new InputStreamReader(new FileInputStream(scriptFile), "ISO-8859-15")); - while(reader.hasNext()) { - statement.execute(reader.next()); - } - } finally { - if(reader != null) - reader.dispose(); - } - } - -} Deleted: trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/SqlScriptReader.java =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/SqlScriptReader.java 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/SqlScriptReader.java 2012-03-29 00:50:29 UTC (rev 38652) @@ -1,84 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2005-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.referencing.factory.epsg; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.Reader; - -/** - * Utility class extracting SQL statement out of a script file with multiline - * statements (works with EPSG distributed scripts) - * - * - * - * - * - * @source $URL$ - */ -public class SqlScriptReader { - boolean fetched = true; - StringBuilder builder = new StringBuilder(); - BufferedReader reader; - - public SqlScriptReader(Reader reader) { - this.reader = new BufferedReader(reader); - } - - public boolean hasNext() throws IOException { - // do we have an un-fetched command? - if(!fetched) { - return builder.length() > 0; - } - - builder.setLength(0); - String line = null; - while((line = reader.readLine()) != null) { - line = line.trim(); - if(!"".equals(line)) - builder.append(line).append("\n"); - if(line.endsWith(";")) { - fetched = false; - break; - } - } - - if(line == null && builder.length() > 0) { - throw new IOException("The file ends with a non ; terminated command"); - } - - return line != null; - } - - public String next() throws IOException { - if(fetched) - throw new IOException("hasNext was not called, or was called and it returned false"); - - fetched = true; - return builder.toString(); - } - - public void dispose() { - try { - reader.close(); - } catch(IOException e) { - // never mind - } - } - - -} Deleted: trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/ThreadedH2EpsgFactory.java =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/ThreadedH2EpsgFactory.java 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/java/org/geotools/referencing/factory/epsg/ThreadedH2EpsgFactory.java 2012-03-29 00:50:29 UTC (rev 38652) @@ -1,417 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2005-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.referencing.factory.epsg; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.RandomAccessFile; -import java.nio.channels.FileChannel; -import java.nio.channels.FileLock; -import java.nio.channels.OverlappingFileLockException; -import java.sql.SQLException; -import java.util.logging.Level; -import java.util.logging.LogRecord; -import java.util.logging.Logger; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -import javax.sql.DataSource; - -import org.geotools.factory.Hints; -import org.geotools.referencing.factory.AbstractAuthorityFactory; -import org.geotools.resources.i18n.ErrorKeys; -import org.geotools.resources.i18n.Errors; -import org.geotools.resources.i18n.LoggingKeys; -import org.geotools.resources.i18n.Loggings; -import org.geotools.util.Version; -import org.geotools.util.logging.Logging; -import org.h2.jdbcx.JdbcDataSource; - - - -/** - * Connection to the EPSG database in H2 database engine format using JDBC. The EPSG - * database can be downloaded from <A HREF="http://www.epsg.org">http://www.epsg.org</A>. - * The SQL scripts (modified for the HSQL syntax as <A HREF="doc-files/HSQL.html">explained - * here</A>) are bundled into this plugin. The database version is given in the - * {@linkplain org.opengis.metadata.citation.Citation#getEdition edition attribute} - * of the {@linkplain org.opengis.referencing.AuthorityFactory#getAuthority authority}. - * The HSQL database is read only. - * <P> - * <H3>Implementation note</H3> - * The SQL scripts are executed the first time a connection is required. The database - * is then created as cached tables ({@code HSQL.properties} and {@code HSQL.data} files) - * in a temporary directory. Future connections to the EPSG database while reuse the cached - * tables, if available. Otherwise, the scripts will be executed again in order to recreate - * them. - * <p> - * If the EPSG database should be created in a different directory (or already exists in that - * directory), it may be specified as a {@linkplain System#getProperty(String) system property} - * nammed {@value #DIRECTORY_KEY}. - * - * @since 2.6 - * - * - * - * @source $URL$ - * @version $Id$ - * @author Martin Desruisseaux - * @author Didier Richard - * @author Andrea Aime - */ -public class ThreadedH2EpsgFactory extends ThreadedEpsgFactory { - /** - * Current version of EPSG-h2 plugin. This is usually the same version number than the - * one in the EPSG database bundled in this plugin. However this field may contains - * additional minor version number if there is some changes related to the EPSG-H2 - * plugin rather then the EPSG database itself (for example additional database index). - */ - public static final Version VERSION = new Version("7.5.0"); - - /** - * The name of the ZIP file to read in order to create the cached database. - */ - private static final String ZIP_FILE = "EPSG.zip"; - - /** - * The successful database creation marker - */ - static final String MARKER_FILE = "EPSG_creation_marker.txt"; - - /** - * The database creation lock file - */ - static final String LOCK_FILE = "EPSG_creation_lock.txt"; - - /** - * The key for fetching the database directory from {@linkplain System#getProperty(String) - * system properties}. - */ - public static final String DIRECTORY_KEY = "EPSG-H2.directory"; - - /** - * The database name. - */ - public static final String DATABASE_NAME = "EPSG"; - - /** - * The prefix to put in front of URL to the database. - */ - static final String PREFIX = "jdbc:h2:"; - - /** - * The logger name. - */ - private static final String LOGGER = "org.geotools.referencing.factory.epsg"; - - /** - * Creates a new instance of this factory. If the {@value #DIRECTORY_KEY} - * {@linkplain System#getProperty(String) system property} is defined and contains - * the name of a directory with a valid {@linkplain File#getParent parent}, then the - * {@value #DATABASE_NAME} database will be saved in that directory. Otherwise, a - * temporary directory will be used. - */ - public ThreadedH2EpsgFactory() { - this(null); - } - - /** - * Creates a new instance of this data source using the specified hints. The priority - * is set to a lower value than the {@linkplain FactoryOnAccess}'s one in order to give - * precedence to the Access-backed database, if presents. Priorities are set that way - * because: - * <ul> - * <li>The MS-Access format is the primary EPSG database format.</li> - * <li>If a user downloads the MS-Access database himself, he probably wants to use it.</li> - * </ul> - */ - public ThreadedH2EpsgFactory(final Hints hints) { - super(hints, PRIORITY + 1); - } - - /** - * Returns the default directory for the EPSG database. If the {@value #DIRECTORY_KEY} - * {@linkplain System#getProperty(String) system property} is defined and contains the - * name of a directory with a valid {@linkplain File#getParent parent}, then the - * {@value #DATABASE_NAME} database will be saved in that directory. Otherwise, - * a temporary directory will be used. - */ - private static File getDirectory() { - try { - final String property = System.getProperty(DIRECTORY_KEY); - if (property != null) { - final File directory = new File(property); - /* - * Creates the directory if needed (mkdir), but NOT the parent directories (mkdirs) - * because a missing parent directory may be a symptom of an installation problem. - * For example if 'directory' is a subdirectory in the temporary directory (~/tmp/), - * this temporary directory should already exists. If it doesn't, an administrator - * should probably looks at this problem. - */ - if (directory.isDirectory() || directory.mkdir()) { - return directory; - } - } - } catch (SecurityException e) { - /* - * Can't fetch the base directory from system properties. - * Fallback on the default temporary directory. - */ - } - return getTemporaryDirectory(); - } - /** - * Tests of the EPSG database is unpacked into the required directory. - * <p> - * This method exists to allow client applications to check if the EPSG - * database is unpacked and ready to go; or if more time shoudld be - * alloted to let the database be constructed. - * @return true if directory intended for h2 exists (assumed from a previous run) - */ - public static boolean isUnpacked(){ - try { - final String property = System.getProperty(DIRECTORY_KEY); - if (property != null) { - final File directory = new File(property); - if (directory.exists() && directory.isDirectory()) { - return true; - } - } - } catch (SecurityException e) { - } - File temp = new File(System.getProperty("java.io.tmpdir", "."), "Geotools"); - File directory = new File( temp, "Databases/EPSG-H2-" + VERSION + "/" ); - if (directory.exists() && directory.isDirectory()) { - return true; - } - return false; - } - /** - * Returns the directory to uses in the temporary directory folder. - */ - private static File getTemporaryDirectory() { - File directory = new File(System.getProperty("java.io.tmpdir", "."), "Geotools"); - if (directory.isDirectory() || directory.mkdir()) { - directory = new File(directory, "Databases/EPSG-H2-" + VERSION + "/"); - if (directory.isDirectory() || directory.mkdirs()) { - return directory; - } - } - return null; - } - - /** - * Extract the directory from the specified data source, or {@code null} if this - * information is not available. - */ - private static File getDirectory(final DataSource source) { - if (source instanceof JdbcDataSource) { - String path = ((JdbcDataSource) source).getURL(); - if (path!=null && PREFIX.regionMatches(true, 0, path, 0, PREFIX.length())) { - path = path.substring(PREFIX.length()); - if( path.indexOf(';') != -1 ){ - path = path.substring(0, path.indexOf(';')); - } - return new File(path).getParentFile(); - } - } - return null; - } - - /** - * Returns a data source for the HSQL database. - */ - protected DataSource createDataSource() throws SQLException { - DataSource candidate = super.createDataSource(); - if (candidate instanceof JdbcDataSource) { - return candidate; - } - final JdbcDataSource source = new JdbcDataSource(); - File directory = getDirectory(); - if (directory != null) { - /* - * Constructs the full path to the HSQL database. Note: we do not use - * File.toURI() because HSQL doesn't seem to expect an encoded URL - * (e.g. "%20" instead of spaces). - */ - final StringBuilder url = new StringBuilder(PREFIX); - final String path = directory.getAbsolutePath().replace(File.separatorChar, '/'); - if (path.length()==0 || path.charAt(0)!='/') { - url.append('/'); - } - url.append(path); - - if (url.charAt(url.length()-1) != '/') { - url.append('/'); - } - url.append(DATABASE_NAME); - // no need for validation query, saves some work - url.append(";AUTO_RECONNECT=TRUE;CACHE_SIZE=131072;CACHE_TYPE=TQ"); - source.setURL((url.toString())); - source.setUser("sa"); - source.setPassword(""); - assert directory.equals(getDirectory(source)) : url; - } - /* - * If the temporary directory do not exists or can't be created, lets the 'database' - * attribute unset. If the user do not set it explicitly (through JNDI or by overrding - * this method), an exception will be thrown when 'createBackingStore()' will be invoked. - */ - source.setUser("SA"); // System administrator. No password. - return source; - } - - /** - * Returns {@code true} if the database contains data. This method returns {@code false} - * if an empty EPSG database has been automatically created by HSQL and not yet populated. - */ - private static boolean dataExists(File directory) throws SQLException { - // check if the marker file is there, and all the other database files as well - // (as some windows cleanup tools delete the .data file only) - return new File(directory, MARKER_FILE).exists() && - new File(directory, DATABASE_NAME + ".data.db").exists() && - new File(directory, DATABASE_NAME + ".index.db").exists(); - } - - /** - * Returns the backing-store factory for HSQL syntax. If the cached tables are not available, - * they will be created now from the SQL scripts bundled in this plugin. - * - * @param hints A map of hints, including the low-level factories to use for CRS creation. - * @return The EPSG factory using HSQL syntax. - * @throws SQLException if connection to the database failed. - */ - protected AbstractAuthorityFactory createBackingStore(final Hints hints) throws SQLException { - final DataSource source = getDataSource(); - final File directory = getDirectory(source); - directory.mkdirs(); - if (!dataExists(directory)) { - FileLock lock = null; - try { - // get an exclusive lock - lock = acquireLock(directory); - - // if after getting the lock the database is still incomplete let's work on it - if(!dataExists(directory)) { - /* - * HSQL has created automatically an empty database. We need to populate it. - * Executes the SQL scripts bundled in the JAR. In theory, each line contains - * a full SQL statement. For this plugin however, we have compressed "INSERT - * INTO" statements using Compactor class in this package. - */ - final Logger logger = Logging.getLogger(LOGGER); - final LogRecord record = Loggings.format(Level.INFO, - LoggingKeys.CREATING_CACHED_EPSG_DATABASE_$1, VERSION); - record.setLoggerName(logger.getName()); - logger.log(record); - - ZipInputStream zin = new ZipInputStream(ThreadedH2EpsgFactory.class.getResourceAsStream(ZIP_FILE)); - ZipEntry ze = null; - byte[] buf = new byte[1024]; - int read = 0; - while ((ze = zin.getNextEntry()) != null) { - File file = new File(directory, ze.getName()); - if( file.exists() ){ - file.delete(); - } - FileOutputStream fout = new FileOutputStream(file); - while((read = zin.read(buf)) > 0) { - fout.write(buf, 0, read); - } - zin.closeEntry(); - fout.close(); - } - zin.close(); - - // mark the successful creation - File marker = new File(directory, MARKER_FILE); - if( marker.exists() ){ - marker.delete(); - } - marker.createNewFile(); - - setReadOnly(directory); - } - } catch (IOException exception) { - SQLException e = new SQLException(Errors.format(ErrorKeys.CANT_READ_$1, ZIP_FILE)); - e.initCause(exception); // TODO: inline cause when we will be allowed to target Java 6. - throw e; - } finally { - if(lock != null) { - try { - lock.release(); - lock.channel().close(); - new File(directory, LOCK_FILE).delete(); - } catch(IOException e) { - // does not matter, was just cleanup - } - } - } - - } - FactoryUsingAnsiSQL factory = new FactoryUsingAnsiSQL(hints, getDataSource().getConnection()); - factory.setValidationQuery("CALL NOW()"); - return factory; - } - - /** - * - * @param directory - * @return - * @throws IOException - */ - FileLock acquireLock(File directory) throws IOException { - // Get a file channel for the file - File file = new File(directory, LOCK_FILE); - FileChannel channel = new RandomAccessFile(file, "rw").getChannel(); - - // Use the file channel to create a lock on the file. - // This method blocks until it can retrieve the lock. - FileLock lock = channel.lock(); - - // Try acquiring the lock without blocking. This method returns - // null or throws an exception if the file is already locked. - while(!lock.isValid()) { - try { - lock = channel.tryLock(); - } catch (OverlappingFileLockException e) { - // File is already locked in this thread or virtual machine - } - // wait for the other process to unlock it, should take a couple of seconds - try { - Thread.sleep(500); - } catch(InterruptedException e) { - // someone waked us earlier, no problem - } - } - - return lock; - } - - private void setReadOnly(final File directory) { - if( directory == null ) return; - for (File file : directory.listFiles()) { - if(file.isDirectory()) { - setReadOnly(file); - } else if(file.getName().endsWith(".log.db")) - file.delete(); - else - file.setReadOnly(); - } - } -} Deleted: trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.crs.CRSAuthorityFactory 2012-03-29 00:50:29 UTC (rev 38652) @@ -1 +0,0 @@ -org.geotools.referencing.factory.epsg.ThreadedH2EpsgFactory Deleted: trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.cs.CSAuthorityFactory =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.cs.CSAuthorityFactory 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.cs.CSAuthorityFactory 2012-03-29 00:50:29 UTC (rev 38652) @@ -1 +0,0 @@ -org.geotools.referencing.factory.epsg.ThreadedH2EpsgFactory Deleted: trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.datum.DatumAuthorityFactory =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.datum.DatumAuthorityFactory 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.datum.DatumAuthorityFactory 2012-03-29 00:50:29 UTC (rev 38652) @@ -1 +0,0 @@ -org.geotools.referencing.factory.epsg.ThreadedH2EpsgFactory Deleted: trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory 2012-03-29 00:50:29 UTC (rev 38652) @@ -1 +0,0 @@ -org.geotools.referencing.factory.epsg.ThreadedH2EpsgFactory Deleted: trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/EPSG.zip =================================================================== (Binary files differ) Deleted: trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/EPSG_Indexes_H2.sql =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/EPSG_Indexes_H2.sql 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/EPSG_Indexes_H2.sql 2012-03-29 00:50:29 UTC (rev 38652) @@ -1,24 +0,0 @@ -CREATE INDEX ALIAS_OBJECT_CODE ON EPSG_ALIAS(OBJECT_CODE); -CREATE INDEX CRS_DATUM_CODE ON EPSG_COORDINATEREFERENCESYSTEM(DATUM_CODE); -CREATE INDEX CRS_PROJECTION_CODE ON EPSG_COORDINATEREFERENCESYSTEM(PROJECTION_CONV_CODE); -CREATE INDEX COORDINATE_AXIS_CODE ON EPSG_COORDINATEAXIS(COORD_AXIS_CODE); -CREATE INDEX COORDINATE_AXIS_SYS_CODE ON EPSG_COORDINATEAXIS(COORD_SYS_CODE); -CREATE INDEX COORDINATE_OPERATION_CRS ON EPSG_COORDOPERATION(SOURCE_CRS_CODE, TARGET_CRS_CODE); -CREATE INDEX COORDINATE_OPERATION_METHOD_CODE ON EPSG_COORDOPERATION(COORD_OP_METHOD_CODE); -CREATE INDEX PARAMETER_USAGE_METHOD_CODE ON EPSG_COORDOPERATIONPARAMUSAGE(COORD_OP_METHOD_CODE); -CREATE INDEX PARAMETER_VALUES ON EPSG_COORDOPERATIONPARAMVALUE(COORD_OP_CODE, COORD_OP_METHOD_CODE); -CREATE INDEX PARAMETER_VALUE_CODE ON EPSG_COORDOPERATIONPARAMVALUE(PARAMETER_CODE); -CREATE INDEX PATH_CONCAT_OPERATION_CODE ON EPSG_COORDOPERATIONPATH(CONCAT_OPERATION_CODE); -CREATE INDEX SUPERSESSION_OBJECT_CODE ON EPSG_SUPERSESSION(OBJECT_CODE); -CREATE INDEX NAME_CRS ON EPSG_COORDINATEREFERENCESYSTEM(COORD_REF_SYS_NAME); -CREATE INDEX NAME_CS ON EPSG_COORDINATESYSTEM(COORD_SYS_NAME); -CREATE INDEX NAME_AXIS ON EPSG_COORDINATEAXISNAME(COORD_AXIS_NAME); -CREATE INDEX NAME_DATUM ON EPSG_DATUM(DATUM_NAME); -CREATE INDEX NAME_ELLIPSOID ON EPSG_ELLIPSOID(ELLIPSOID_NAME); -CREATE INDEX NAME_PRIME_MERIDIAN ON EPSG_PRIMEMERIDIAN(PRIME_MERIDIAN_NAME); -CREATE INDEX NAME_COORD_OP ON EPSG_COORDOPERATION(COORD_OP_NAME); -CREATE INDEX NAME_METHOD ON EPSG_COORDOPERATIONMETHOD(COORD_OP_METHOD_NAME); -CREATE INDEX NAME_PARAMETER ON EPSG_COORDOPERATIONPARAM(PARAMETER_NAME); -CREATE INDEX NAME_UNIT ON EPSG_UNITOFMEASURE(UNIT_OF_MEAS_NAME); -ANALYZE; - Deleted: trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/README.txt =================================================================== --- trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/README.txt 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/main/resources/org/geotools/referencing/factory/epsg/README.txt 2012-03-29 00:50:29 UTC (rev 38652) @@ -1,38 +0,0 @@ -Updating the EPSG database ---------------------------- - -The database in the zip file is a HSQL version of the official EPSG database. - -1) Download from www.epsg.org the "geodetic dataset" creation scripts for the PostgreSQL database -2) Unzip them in _this_ directory, you should get three files named EPSG_v<version>.mdb_Data_PostgreSQL.sql, - EPSG_v<version>.mdb_FKeys_PostgreSQL.sql and EPSG_v<version>.mdb_Tables_PostgreSQL.sql, where - <version> is the the version of the EPSG database ("7_1" at the time of writing) -3) Remove the _v<version.mdb part from all names, resulting in names like EPSG_Data_PostgreSQL.sql -5) Hand modify the EPSG_Tables_PostgreSQL.sql file and replace all TEXT types with VARCHAR(4096) -6) Update ThreadedH2EpsgFactory.VERSION to the current version -7) Run the DatabaseCreationScript.java -8) Check the EPSG.zip file has been updated -9) Run the build with extensive tests in the epsg-h2 module: - mvn clean install -Pextensive.tests - - This step might force you to amend tests or modify the referencing subsystem to handle new - axis direction definitions, new unit of measure and the like -10) Remove all the sql files in this directory, keeping only EPSG_Indexes_H2.sql (which was already - there when you started). Also remove an eventual EPSG.*.log.db file. -11) Commit the changes -12) Congratulations, you're done! - - -PostgreSQL notes ------------------------------- - -Sometimes it is handy to have the database loaded in PostgreSQL to run random queries -against it. In order to load it you'll have to change the psql encoding thought: -createdb epsg<version> -psql espg<version> -\encoding latin9 -\i EPSG_v<version>.mdb_Tables_PostgreSQL.sql -\i EPSG_v<version>.mdb_Data_PostgreSQL.sql -\i EPSG_v<version>.mdb_FKeys_PostgreSQL.sql - - \ No newline at end of file Deleted: trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/OrderedAxisAuthorityFactoryTest.java =================================================================== --- trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/OrderedAxisAuthorityFactoryTest.java 2012-03-27 14:53:07 UTC (rev 38651) +++ trunk/modules/unsupported/epsg-h2/src/test/java/org/geotools/referencing/factory/OrderedAxisAuthorityFactoryTest.java 2012-03-29 00:50:29 UTC (rev 38652) @@ -1,416 +0,0 @@ -/* - * GeoTools - The Open Source Java GIS Toolkit - * http://geotools.org - * - * (C) 2005-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.referencing.factory; - -// J2SE dependencies -import java.util.Map; -import java.util.Set; -import java.util.logging.Level; - -// JUnit dependencies -import junit.framework.Test; -import junit.framework.TestCase; -import junit.framework.TestSuite; - -// OpenGIS dependencies -import org.opengis.referencing.IdentifiedObject; -import org.opengis.referencing.FactoryException; -import org.opengis.referencing.crs.SingleCRS; -import org.opengis.referencing.crs.ProjectedCRS; -import org.opengis.referencing.crs.CRSAuthorityFactory; -import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.opengis.referencing.cs.CoordinateSystem; -import org.opengis.referencing.operation.CoordinateOperationFactory; -import org.opengis.referencing.operation.MathTransform; -import org.opengis.referencing.operation.Matrix; - -// Geotools dependencies -import org.geotools.factory.Hints; -import org.geotools.resources.Arguments; -import org.geotools.referencing.CRS; -import org.geotools.referencing.ReferencingFactoryFinder; -import org.geotools.referencing.crs.DefaultGeographicCRS; -import org.geotools.referencing.operation.LinearTransform; -import org.geotools.referencing.operation.matrix.GeneralMatrix; -import org.geotools.referencing.cs.DefaultCoordinateSystemAxis; -import org.geotools.referencing.factory.epsg.CartesianAuthorityFactory; -import org.geotools.referencing.factory.epsg.LongitudeFirstFactory; - - -/** - * Tests the usage of {@link OrderedAxisAuthorityFactory} with the help of the - * EPSG database. Any EPSG plugin should fit. However, this test live in the - * {@code plugin/epsg-hsql} module since the HSQL plugin is the only one which - * is garantee to work on any machine running Maven. - * - * - * - * - * @source $URL$ - * @version $Id$ - * @author Martin Desruisseaux (IRD) - * @author Jody Garnett - */ -public class OrderedAxisAuthorityFactoryTest extends TestCase { - /** - * {@code true} if metadata (especially identifiers) should be erased, or {@code false} if - * they should be kepts. The {@code true} value matches the pre GEOT-854 state, while the - * {@code false} value mathes the post GEOT-854 state. - * - * @see http://jira.codehaus.org/browse/GEOT-854 - */ - private static final boolean METADATA_ERASED = false; - - /** - * Small number for floating points comparaisons. - */ - private static final double EPS = 1E-8; - - /** - * Run the suite from the command line. If {@code "-log"} flag is specified on the - * command-line, then the logger will be set to {@link Level#CONFIG}. This is usefull - * for tracking down which data source is actually used. - */ - public static void main(final String[] args) { - final Arguments arguments = new Arguments(args); - final boolean log = arguments.getFlag("-log"); - arguments.getRemainingArguments(0); - org.geotools.util.logging.Logging.GEOTOOLS.forceMonolineConsoleOutput(log ? Level.CONFIG : null); - junit.textui.TestRunner.run(suite()); - } - - /** - * Returns the test suite. - */ - public static Test suite() { - return new TestSuite(OrderedAxisAuthorityFactoryTest.class); - } - - /** - * Constructs a test case with the given name. - */ - public OrderedAxisAuthorityFactoryTest(final String name) { - super(name); - } - - @Override - protected void setUp() throws Exception { - super.setUp(); - - // this test does not work if there is more than one EPSG factory around - Set<CRSAuthorityFactory> factories = ReferencingFactoryFinder.getCRSAuthorityFactories(null); - for (CRSAuthorityFactory factory : factories) { - if(factory instanceof CartesianAuthorityFactory) { - ReferencingFactoryFinder.removeAuthorityFactory(factory); - } - } - } - - /** - * Returns the ordered axis factory for the specified set of hints. - */ - private static OrderedAxisAuthorityFactory getFactory(final Hints hints) { - CRSAuthorityFactory factory; - factory = ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", hints); - - assertTrue(factory.getClass().toString(), factory instanceof LongitudeFirstFactory); - final LongitudeFirstFactory asLongitudeFirst = (LongitudeFirstFactory) factory; - final Map implementationHints = asLongitudeFirst.getImplementationHints(); - factory = (CRSAuthorityFactory) implementationHints.get(Hints.CRS_AUTHORITY_FACTORY); - - assertTrue(factory.getClass().toString(), factory instanceof OrderedAxisAuthorityFactory); - final OrderedAxisAuthorityFactory asOrdered = (OrderedAxisAuthorityFactory) factory; - assertFalse(asOrdered.isCodeMethodOverriden()); - - return asOrdered; - } - - /** - * Returns a positive number if the specified coordinate system is right-handed, - * or a negative number if it is left handed. - */ - private static double getAngle(final CoordinateReferenceSystem crs) { - final CoordinateSystem cs = crs.getCoordinateSystem(); - assertEquals(2, cs.getDimension()); - return DefaultCoordinateSystemAxis.getAngle(cs.getAxis(0).getDirection(), - cs.getAxis(1).getDirection()); - } - - /** - * Tests the registration of the various flavor of {@link OrderedAxisAuthorityFactoryTest} - * for the EPSG authority factory. - */ - public void testRegistration() { - final Hints hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE); - OrderedAxisAuthorityFactory factory; - factory = getFactory(hints); - assertFalse(factory.forceStandardDirections); - assertFalse(factory.forceStandardUnits); - - hints.put(Hints.FORCE_STANDARD_AXIS_DIRECTIONS, Boolean.FALSE); - assertSame(factory, getFactory(hints)); - assertFalse(factory.forceStandardDirections); - assertFalse(factory.forceStandardUnits); - - hints.put(Hints.FORCE_STANDARD_AXIS_UNITS, Boolean.FALSE); - assertSame(factory, getFactory(hints)); - assertFalse(factory.forceStandardDirections); - assertFalse(factory.forceStandardUnits); - - hints.put(Hints.FORCE_STANDARD_AXIS_UNITS, Boolean.TRUE); - assertNotSame(factory, factory = getFactory(hints)); - assertFalse (factory.forceStandardDirections); - assertTrue (factory.forceStandardUnits); - - hints.put(Hints.FORCE_STANDARD_AXIS_DIRECTIONS, Boolean.TRUE); - assertNotSame(factory, factory = getFactory(hints)); - assertTrue (factory.forceStandardDirections); - assertTrue (factory.forceStandardUnits); - - hints.put(Hints.FORCE_STANDARD_AXIS_UNITS, Boolean.FALSE); - assertNotSame(factory, factory = getFactory(hints)); - assertTrue (factory.forceStandardDirections); - assertFalse (factory.forceStandardUnits); - } - - /** - * Tests the axis reordering. - */ - public void testAxisReordering() throws FactoryException { - /* - * Tests the OrderedAxisAuthorityFactory creating using FactoryFinder. The following - * conditions are not tested directly, but are required in order to get the test to - * succeed: - * - * - EPSG factories must be provided for both "official" and "modified" axis order. - * - The "official" axis order must have precedence over the modified one. - * - The hints are correctly understood by FactoryFinder. - */ - final AbstractAuthorityFactory factory0, factory1; - final Hints hints = new Hints(Hints.CRS_AUTHORITY_FACTORY, AbstractAuthorityFactory.class); - factory0 = (AbstractAuthorityFactory) ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", hints); - assertFalse(factory0 instanceof OrderedAxisAuthorityFactory); - assertFalse(factory0 instanceof LongitudeFirstFactory); - hints.put(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE); - hints.put(Hints.FORCE_STANDARD_AXIS_DIRECTIONS, Boolean.TRUE); - hints.put(Hints.FORCE_STANDARD_AXIS_UNITS, Boolean.TRUE); - factory1 = (AbstractAuthorityFactory) ReferencingFactoryFinder.getCRSAuthorityFactory("EPSG", hints); - assertTrue(factory1 instanceof LongitudeFirstFactory); - /* - * The local variables to be used for all remaining tests - * (usefull to setup in the debugger). - */ - String code; - CoordinateReferenceSystem crs0, crs1; - CoordinateOperationFactory opFactory = ReferencingFactoryFinder.getCoordinateOperationFactory(null); - MathTransform mt; - Matrix matrix; - /* - * Tests a WGS84 geographic CRS (2D) with (NORTH, EAST) axis directions. - * The factory should reorder the axis with no more operation than an axis swap. - */ - code = "4326"; - crs0 = factory0.createCoordinateReferenceSystem(code); - crs1 = factory1.createCoordinateReferenceSystem(code); - final CoordinateReferenceSystem cacheTest = crs1; - assertNotSame(crs0, crs1); - assertNotSame(crs0.getCoordinateSystem(), crs1.getCoordinateSystem()); - assertSame(((SingleCRS) crs0).getDatum(), ((SingleCRS) crs1).getDatum()); - assertEquals("Expected a left-handed CS.", -90, getAngle(crs0), EPS); - assertEquals("Expected a right-handed CS.", +90, getAngle(crs1), EPS); - assertFalse(crs0.getIdentifiers().isEmpty()); - if (METADATA_ERASED) { - assertTrue(crs1.getIdentifiers().isEmpty()); - } else { - assertEquals(crs0.getIdentifiers(), crs1.getIdentifiers()); - } - mt = opFactory.createOperation(crs0, crs1).getMathTransform(); - assertFalse(mt.isIdentity()); - assertTrue(mt instanceof LinearTransform); - matrix = ((LinearTransform) mt).getMatrix(); - assertEquals(new GeneralMatrix(new double[][] { - {0, 1, 0}, - {1, 0, 0}, - {0, 0, 1}}), new GeneralMatrix(matrix)); - /* - * Tests a WGS84 geographic CRS (3D) with (NORTH, EAST, UP) axis directions. - * Because this CRS uses sexagesimal units, conversions are not supported and - * will not be tested. - */ - code = "4329"; - crs0 = factory0.createCoordinateReferenceSystem(code); - crs1 = factory1.createCoordinateReferenceSystem(code); - assertNotSame(crs0, crs1); - assertNotSame(crs0.getCoordinateSystem(), crs1.getCoordinateSystem()); - assertSame(((SingleCRS) crs0).getDatum(), ((SingleCRS) crs1).getDatum()); - assertFalse(crs0.getIdentifiers().isEmpty()); - if (METADATA_ERASED) { - assertTrue(crs1.getIdentifiers().isEmpty()); - } else { - assertEquals(crs0.getIdentifiers(), crs1.getIdentifiers()); - } - /* - * Tests a WGS84 geographic CRS (3D) with (NORTH, EAST, UP) axis directions. - * The factory should reorder the axis with no more operation than an axis swap. - */ - code = "63266413"; - crs0 = factory0.createCoordinateReferenceSystem(code); - crs1 = factory1.createCoordinateReferenceSystem(code); - assertNotSame(crs0, crs1); - assertNotSame(crs0.getCoordinateSystem(), crs1.getCoordinateSystem()); - assertSame(((SingleCRS) crs0).getDatum(), ((SingleCRS) crs1).getDatum()); - assertFalse(crs0.getIdentifiers().isEmpty()); - if (METADATA_ERASED) { - assertTrue(crs1.getIdentifiers().isEmpty()); - } else { - assertEquals(crs0.getIdentifiers(), crs1.getIdentifiers()); - } - mt = opFactory.createOperation(crs0, crs1).getMathTransform(); - assertFalse(mt.isIdentity()); - assertTrue(mt instanceof LinearTransform); - matrix = ((LinearTransform) mt).getMatrix(); - assertEquals(new GeneralMatrix(new double[][] { - {0, 1, 0, 0}, - {1, 0, 0, 0}, - {0, 0, 1, 0}, - {0, 0, 0, 1}}), new GeneralMatrix(matrix)); - /* - * Tests a projected CRS with (EAST, NORTH) axis orientation. No axis reordering is needed, - * which means that their coordinate systems are identical and the math transform should be - * the identity one. Note that while no axis swap is needed, the base GeographicCRS are not - * the same since an axis reordering has been done there. - */ - code = "2027"; - crs0 = factory0.createCoordinateReferenceSystem(code); - crs1 = factory1.createCoordinateReferenceSystem(code); - assertNotSame(crs0, crs1); - assertSame(crs0.getCoordinateSystem(), crs1.getCoordinateSystem()); - assertSame(((SingleCRS) crs0).getDatum(), ((SingleCRS) crs1).getDatum()); - assertNotSame(((ProjectedCRS) crs0).getBaseCRS(), ((ProjectedCRS) crs1).getBaseCRS()); - assertFalse(crs0.getIdentifiers().isEmpty()); - if (METADATA_ERASED) { - assertTrue(crs1.getIdentifiers().isEmpty()); - } else { - assertEquals(crs0.getIdentifiers(), crs1.getIdentifiers()); - } - mt = opFactory.createOperation(crs0, crs1).getMathTransform(); - assertTrue(mt.isIdentity()); - /* - * Tests a projected CRS with (WEST, SOUTH) axis orientation. - * The factory should arrange the axis with no more operation than a direction change. - * While the end result is a matrix like the GeographicCRS case, the path that lead to - * this result is much more complex. - */ - code = "22275"; - crs0 = factory0.createCoordinateReferenceSystem(code); - crs1 = factory1.createCoordinateReferenceSystem(code); - assertNotSame(crs0, crs1); - assertNotSame(crs0.getCoordinateSystem(), crs1.getCoordinateSystem()); - assertSame(((SingleCRS) crs0).getDatum(), ((SingleCRS) crs1).getDatum()); - assertFalse(crs0.getIdentifiers().isEmpty()); - if (METADATA_ERASED) { - assertTrue(crs1.getIdentifiers().isEmpty()); - } else { - assertEquals(crs0.getIdentifiers(), crs1.getIdentifiers()); - } - mt = opFactory.createOperation(crs0, crs1).getMathTransform(); - assertFalse(mt.isIdentity()); - assertTrue(mt instanceof LinearTransform); - matrix = ((LinearTransform) mt).getMatrix(); - assertEquals(new GeneralMatrix(new double[][] { - {-1, 0, 0}, - { 0, -1, 0}, - { 0, 0, 1}}), new GeneralMatrix(matrix)); - /* - * Tests the cache. - */ - assertSame(cacheTest, factory1.createCoordinateReferenceSystem("4326")); - } - - /** - * Tests the creation of EPSG:4326 CRS with different axis order. - */ - public void testLongitudeFirst() throws FactoryException { - final CoordinateReferenceSystem standard = CRS.decode("EPSG:4326", false); - final CoordinateReferenceSystem modified = CRS.decode("EPSG:4326", true ); - assertEquals("Expected a left-handed CS.", -90, getAngle(standard), EPS); - assertEquals("Expected a right-handed CS.", +90, getAngle(modified), EPS); - final MathTransform transform = CRS.findMathTransform(standard, modified); - assertTrue(transform instanceof LinearTransform); - final Matrix matrix = ((LinearTransform) transform).getMatrix(); - assertEquals(new GeneralMatrix(new double[][] { - { 0, 1, 0}, - { 1, 0, 0}, - { 0, 0, 1}}), new GeneralMatrix(matrix)); - } - - /** - * Tests the {@link IdentifiedObjectFinder#find} method with axis order forced. - */ - public void testFind() throws FactoryException { - final CRSAuthorityFactory factory = ReferencingFactoryFinder.getCRSAuthorityFactory( - "EPSG", new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE)); - - assertTrue(factory instanceof AbstractAuthorityFactory); - AbstractAuthorityFactory findable = (AbstractAuthorityFactory) factory; - final IdentifiedObjectFinder finder = findable.getIdentifiedObjectFinder(CoordinateReferenceSystem.class); - - /* - * We tested in DefaultFactoryTest that WGS84 is not found when searching - * directly in DefaultFactory. Now we perform the same search through the - * ordered axis authority factory. - */ - finder.setFullScanAllowed(false); - assertNull("Should not find the CRS without a scan.", - finder.find(DefaultGeographicCRS.WGS84)); - - finder.setFullScanAllowed(true); - IdentifiedObject find = finder.find(DefaultGeographicCRS.WGS84); - assertNotNull("With scan allowed, should find the CRS.", find); - assertTrue(CRS.equalsIgnoreMetadata(DefaultGeographicCRS.WGS84, find)); - assertEquals("Expected a right-handed CS.", +90, getAngle((CoordinateReferenceSystem) find), EPS); - /* - * Search a CRS using (latitude,longitude) axis order. The IdentifiedObjectFinder - * should be able to find it even if it is backed by... [truncated message content] |
From: <svn...@os...> - 2012-03-27 14:53:13
|
Author: mcr Date: 2012-03-27 07:53:07 -0700 (Tue, 27 Mar 2012) New Revision: 38651 Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java trunk/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java Log: Fixing GEOT-4089 on trunk Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java 2012-03-27 14:51:52 UTC (rev 38650) +++ trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java 2012-03-27 14:53:07 UTC (rev 38651) @@ -314,7 +314,6 @@ out.write("db2gse.ST_Equals"); } else if (filter instanceof Disjoint) { out.write("db2gse.ST_Disjoint"); - // TODO } else if (filter instanceof Intersects || filter instanceof BBOX) { out.write("db2gse.ST_Intersects"); } else if (filter instanceof Crosses) { @@ -629,4 +628,30 @@ throw new RuntimeException(e); } } + + public Object visit(BBOX filter, Object extraData) throws RuntimeException { + if (isLooseBBOXEnabled()==false) + return super.visit(filter,extraData); + + + + double minx = filter.getMinX(); + double maxx = filter.getMaxX(); + double miny = filter.getMinY(); + double maxy = filter.getMaxY(); + String propertyName = filter.getPropertyName(); + Integer srid =getSRID(propertyName); + + try { + out.write("db2gse.EnvelopesIntersect("); + out.write(escapeName(propertyName)); + out.write(","+minx + ", " + miny + ", " + + maxx + ", " + maxy + ", " + srid); + out.write(") =1 "); + } catch (IOException e) { + throw new RuntimeException(e); + } + return extraData; + } + } Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java 2012-03-27 14:51:52 UTC (rev 38650) +++ trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java 2012-03-27 14:53:07 UTC (rev 38651) @@ -55,7 +55,11 @@ /** parameter for database type */ public static final Param DBTYPE = new Param("dbtype", String.class, "Type", true, "db2"); - public final static String DriverClassName = "com.ibm.db2.jcc.DB2Driver"; + /** enables using EnvelopesIntersect in bbox queries */ + public static final Param LOOSEBBOX = new Param("Loose bbox", Boolean.class, "Perform only primary filter on bbox", false, Boolean.TRUE); + + + public final static String DriverClassName = "com.ibm.db2.jcc.DB2Driver"; protected SQLDialect createSQLDialect(JDBCDataStore dataStore) { return new DB2SQLDialectPrepared(dataStore, new DB2DialectInfo()); @@ -128,7 +132,10 @@ protected void setupParameters(Map parameters) { super.setupParameters(parameters); parameters.put(DBTYPE.key, DBTYPE); + parameters.put(LOOSEBBOX.key, LOOSEBBOX); + } + @Override protected JDBCDataStore createDataStoreInternal(JDBCDataStore dataStore, Map params) @@ -136,7 +143,12 @@ Connection con = null; try { con = dataStore.getDataSource().getConnection(); - DB2DialectInfo di = ((DB2SQLDialectPrepared) dataStore.getSQLDialect()).getDb2DialectInfo(); + DB2DialectInfo di = ((DB2SQLDialectPrepared) dataStore.getSQLDialect()).getDb2DialectInfo(); + + DB2SQLDialectPrepared dialect = (DB2SQLDialectPrepared) dataStore.getSQLDialect(); + Boolean loose = (Boolean) LOOSEBBOX.lookUp(params); + dialect.setLooseBBOXEnabled(loose == null || Boolean.TRUE.equals(loose)); + DatabaseMetaData md = con.getMetaData(); di.setMajorVersion(md.getDatabaseMajorVersion()); di.setMinorVersion(md.getDatabaseMinorVersion()); Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java 2012-03-27 14:51:52 UTC (rev 38650) +++ trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java 2012-03-27 14:53:07 UTC (rev 38651) @@ -16,6 +16,8 @@ */ package org.geotools.data.db2; +import java.util.Map; + import org.geotools.jdbc.JDBCJNDIDataStoreFactory; /** @@ -33,4 +35,11 @@ public DB2NGJNDIDataStoreFactory() { super(new DB2NGDataStoreFactory()); } + + protected void setupParameters(Map parameters) { + super.setupParameters(parameters); + parameters.put(DBTYPE.key, DBTYPE); + parameters.put(DB2NGDataStoreFactory.LOOSEBBOX.key, DB2NGDataStoreFactory.LOOSEBBOX); + } + } Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java 2012-03-27 14:51:52 UTC (rev 38650) +++ trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java 2012-03-27 14:53:07 UTC (rev 38651) @@ -80,8 +80,10 @@ private static String DEFAULT_SRS_NAME = "DEFAULT_SRS"; private static Integer DEFAULT_SRS_ID=0; - + + private boolean looseBBOXEnabled; + private static String SELECT_SRSID_WITH_SCHEMA = "select SRS_ID from DB2GSE.ST_GEOMETRY_COLUMNS where TABLE_SCHEMA = ? and "+ "TABLE_NAME = ? and COLUMN_NAME = ?"; @@ -656,4 +658,12 @@ this.functionEncodingEnabled = functionEncodingEnabled; } + public boolean isLooseBBOXEnabled() { + return looseBBOXEnabled; + } + + public void setLooseBBOXEnabled(boolean looseBBOXEnabled) { + this.looseBBOXEnabled = looseBBOXEnabled; + } + } Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java 2012-03-27 14:51:52 UTC (rev 38650) +++ trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java 2012-03-27 14:53:07 UTC (rev 38651) @@ -65,10 +65,20 @@ public FilterToSQL createFilterToSQL() { DB2FilterToSQL filter = new DB2FilterToSQL((Writer) null); filter.setFunctionEncodingEnabled(isFunctionEncodingEnabled()); + filter.setLooseBBOXEnabled(delegate.isLooseBBOXEnabled()); return filter; } + public boolean isLooseBBOXEnabled() { + return delegate.isLooseBBOXEnabled(); + } + + public void setLooseBBOXEnabled(boolean looseBBOXEnabled) { + delegate.setLooseBBOXEnabled(looseBBOXEnabled); + } + + @Override public void encodePrimaryKey(String column, StringBuffer sql) { delegate.encodePrimaryKey(column, sql); Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java 2012-03-27 14:51:52 UTC (rev 38650) +++ trunk/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java 2012-03-27 14:53:07 UTC (rev 38651) @@ -25,6 +25,7 @@ import java.util.Map; import java.util.Set; +import org.geotools.data.jdbc.FilterToSQL; import org.geotools.factory.Hints.Key; import org.geotools.jdbc.JDBCDataStore; import org.geotools.jdbc.PreparedFilterToSQL; @@ -65,12 +66,24 @@ @Override - public PreparedFilterToSQL createPreparedFilterToSQL() { + public PreparedFilterToSQL createPreparedFilterToSQL() { DB2FilterToSQL filter = new DB2FilterToSQL(this); filter.setFunctionEncodingEnabled(isFunctionEncodingEnabled()); + filter.setLooseBBOXEnabled(delegate.isLooseBBOXEnabled()); return filter; - } + } + + + public boolean isLooseBBOXEnabled() { + return delegate.isLooseBBOXEnabled(); + } + + public void setLooseBBOXEnabled(boolean looseBBOXEnabled) { + delegate.setLooseBBOXEnabled(looseBBOXEnabled); + } + + @Override public void encodePrimaryKey(String column, StringBuffer sql) { delegate.encodePrimaryKey(column, sql); Modified: trunk/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java 2012-03-27 14:51:52 UTC (rev 38650) +++ trunk/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java 2012-03-27 14:53:07 UTC (rev 38651) @@ -19,15 +19,17 @@ import org.geotools.data.Query; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.factory.CommonFactoryFinder; +import org.geotools.feature.FeatureCollection; import org.geotools.jdbc.JDBCDataStoreAPITestSetup; import org.geotools.jdbc.JDBCSpatialFiltersTest; +import org.opengis.filter.FilterFactory; import org.opengis.filter.FilterFactory2; import org.opengis.filter.expression.Literal; import org.opengis.filter.expression.PropertyName; +import org.opengis.filter.spatial.BBOX; import org.opengis.filter.spatial.DWithin; import com.vividsolutions.jts.geom.Coordinate; -import com.vividsolutions.jts.geom.GeometryCollection; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.MultiLineString; @@ -79,5 +81,21 @@ assertEquals(0, features.size()); } + public void testBboxFilter() throws Exception { + FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); + // should match "r2" and "r3" + BBOX bbox = ff.bbox(aname("geom"), 2, 3, 4, 5, "EPSG:4326"); + FeatureCollection features = dataStore.getFeatureSource(tname("road")).getFeatures(bbox); + assertEquals(2, features.size()); + } + + public void testBboxFilterDefault() throws Exception { + FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); + // should match "r2" and "r3" + BBOX bbox = ff.bbox("", 2, 3, 4, 5, "EPSG:4326"); + FeatureCollection features = dataStore.getFeatureSource(tname("road")).getFeatures(bbox); + assertEquals(2, features.size()); + } + } |
From: <svn...@os...> - 2012-03-27 14:52:05
|
Author: mcr Date: 2012-03-27 07:51:52 -0700 (Tue, 27 Mar 2012) New Revision: 38650 Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java Log: Fixing GEOT-4089 on 2.7.x Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java 2012-03-27 09:59:43 UTC (rev 38649) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2FilterToSQL.java 2012-03-27 14:51:52 UTC (rev 38650) @@ -351,19 +351,19 @@ throw new RuntimeException(e); } - LOGGER.fine(this.out.toString()); + LOGGER.finer(this.out.toString()); return extraData; } /** - * Encode a bounding-box filter using the EnvelopesIntersect spatial - * predicate. + * Encode a bounding-box filter using either the EnvelopesIntersect (loose) + * or ST_Intersects (precise) predicate. * * @param filter a BBOX filter object * @param extraData not used */ private Object encodeBBox(BBOX filter, Object extraData) { - LOGGER.finer("Generating EnvelopesIntersect WHERE clause for " + filter); + LOGGER.finer("encodeBBOX: Generating EnvInt WHERE clause for " + filter); try { String spatialColumn = filter.getPropertyName(); @@ -382,6 +382,7 @@ double maxy = filter.getMaxY(); if (isLooseBBOXEnabled()) { + LOGGER.finer("looseBBOX"); this.out.write("db2gse.EnvelopesIntersect("); this.out.write(escapeName(spatialColumn)); this.out.write(", "); @@ -389,6 +390,7 @@ + maxx + ", " + maxy + ", " + srid); this.out.write(") = 1"); } else { + LOGGER.finer("not looseBBOX"); this.out.write("db2gse.st_intersects("); this.out.write(escapeName(spatialColumn)); this.out.write(", "); Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java 2012-03-27 09:59:43 UTC (rev 38649) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGDataStoreFactory.java 2012-03-27 14:51:52 UTC (rev 38650) @@ -54,6 +54,9 @@ /** parameter for database type */ public static final Param DBTYPE = new Param("dbtype", String.class, "Type", true, "db2"); + /** enables using EnvelopesIntersect in bbox queries */ + public static final Param LOOSEBBOX = new Param("Loose bbox", Boolean.class, "Perform only primary filter on bbox", false, Boolean.TRUE); + public final static String DriverClassName = "com.ibm.db2.jcc.DB2Driver"; protected SQLDialect createSQLDialect(JDBCDataStore dataStore) { @@ -127,6 +130,7 @@ protected void setupParameters(Map parameters) { super.setupParameters(parameters); parameters.put(DBTYPE.key, DBTYPE); + parameters.put(LOOSEBBOX.key, LOOSEBBOX); } @Override @@ -135,7 +139,12 @@ Connection con = null; try { con = dataStore.getDataSource().getConnection(); - DB2DialectInfo di = ((DB2SQLDialectPrepared) dataStore.getSQLDialect()).getDb2DialectInfo(); + + DB2SQLDialectPrepared dialect = (DB2SQLDialectPrepared) dataStore.getSQLDialect(); + Boolean loose = (Boolean) LOOSEBBOX.lookUp(params); + dialect.setLooseBBOXEnabled(loose == null || Boolean.TRUE.equals(loose)); + + DB2DialectInfo di = dialect.getDb2DialectInfo(); DatabaseMetaData md = con.getMetaData(); di.setMajorVersion(md.getDatabaseMajorVersion()); di.setMinorVersion(md.getDatabaseMinorVersion()); @@ -168,6 +177,7 @@ } catch (SQLException e) { throw new IOException(e.getMessage()); } + dataStore.closeSafe(con); return dataStore; } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java 2012-03-27 09:59:43 UTC (rev 38649) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2NGJNDIDataStoreFactory.java 2012-03-27 14:51:52 UTC (rev 38650) @@ -16,6 +16,9 @@ */ package org.geotools.data.db2; +import java.util.Map; + +import org.geotools.data.DataAccessFactory.Param; import org.geotools.jdbc.JDBCJNDIDataStoreFactory; /** @@ -32,4 +35,11 @@ public DB2NGJNDIDataStoreFactory() { super(new DB2NGDataStoreFactory()); } + + protected void setupParameters(Map parameters) { + super.setupParameters(parameters); + parameters.put(DBTYPE.key, DBTYPE); + parameters.put(DB2NGDataStoreFactory.LOOSEBBOX.key, DB2NGDataStoreFactory.LOOSEBBOX); + } + } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java 2012-03-27 09:59:43 UTC (rev 38649) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialect.java 2012-03-27 14:51:52 UTC (rev 38650) @@ -17,6 +17,7 @@ package org.geotools.data.db2; import java.io.IOException; +import java.io.Writer; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; @@ -26,6 +27,7 @@ import java.util.Set; import java.util.logging.Level; +import org.geotools.data.jdbc.FilterToSQL; import org.geotools.factory.Hints; import org.geotools.factory.Hints.Key; import org.geotools.jdbc.JDBCDataStore; @@ -75,8 +77,11 @@ private static String DEFAULT_SRS_NAME = "DEFAULT_SRS"; private static Integer DEFAULT_SRS_ID=0; + + private boolean looseBBOXEnabled; + private static String SELECT_SRSID_WITH_SCHEMA = "select SRS_ID from DB2GSE.ST_GEOMETRY_COLUMNS where TABLE_SCHEMA = ? and "+ "TABLE_NAME = ? and COLUMN_NAME = ?"; @@ -589,5 +594,13 @@ if (info.getMinorVersion()==7 && fpNumber>=1) return true; return false; } + + public boolean isLooseBBOXEnabled() { + return looseBBOXEnabled; + } + + public void setLooseBBOXEnabled(boolean looseBBOXEnabled) { + this.looseBBOXEnabled = looseBBOXEnabled; + } } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java 2012-03-27 09:59:43 UTC (rev 38649) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectBasic.java 2012-03-27 14:51:52 UTC (rev 38650) @@ -51,6 +51,15 @@ * @see org.geotools.jdbc.SQLDialect#createCRS(int, java.sql.Connection) * */ + + public boolean isLooseBBOXEnabled() { + return delegate.isLooseBBOXEnabled(); + } + + public void setLooseBBOXEnabled(boolean looseBBOXEnabled) { + delegate.setLooseBBOXEnabled(looseBBOXEnabled); + } + @Override public CoordinateReferenceSystem createCRS(int srid, Connection cx) throws SQLException { return delegate.createCRS(srid, cx); @@ -58,7 +67,9 @@ @Override public FilterToSQL createFilterToSQL() { - return new DB2FilterToSQL((Writer) null); + DB2FilterToSQL sql = new DB2FilterToSQL((Writer) null); + sql.setLooseBBOXEnabled(delegate.isLooseBBOXEnabled()); + return sql; } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java 2012-03-27 09:59:43 UTC (rev 38649) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/main/java/org/geotools/data/db2/DB2SQLDialectPrepared.java 2012-03-27 14:51:52 UTC (rev 38650) @@ -39,7 +39,7 @@ public class DB2SQLDialectPrepared extends PreparedStatementSQLDialect { - private DB2SQLDialect delegate = null; + private DB2SQLDialect delegate = null; public DB2SQLDialectPrepared(JDBCDataStore dataStore, DB2DialectInfo info) { super(dataStore); @@ -59,10 +59,20 @@ @Override - public PreparedFilterToSQL createPreparedFilterToSQL() { - return new DB2FilterToSQL(this); - } + public PreparedFilterToSQL createPreparedFilterToSQL() { + DB2FilterToSQL sql = new DB2FilterToSQL(this); + sql.setLooseBBOXEnabled(delegate.isLooseBBOXEnabled()); + return sql; + } + public boolean isLooseBBOXEnabled() { + return delegate.isLooseBBOXEnabled(); + } + + public void setLooseBBOXEnabled(boolean looseBBOXEnabled) { + delegate.setLooseBBOXEnabled(looseBBOXEnabled); + } + @Override public void encodePrimaryKey(String column, StringBuffer sql) { delegate.encodePrimaryKey(column, sql); Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java 2012-03-27 09:59:43 UTC (rev 38649) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-db2/src/test/java/org/geotools/data/db2/DB2SpatialFiltersTest.java 2012-03-27 14:51:52 UTC (rev 38650) @@ -16,9 +16,16 @@ */ package org.geotools.data.db2; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.feature.FeatureCollection; import org.geotools.jdbc.JDBCDataStoreAPITestSetup; import org.geotools.jdbc.JDBCSpatialFiltersTest; +import org.opengis.filter.FilterFactory; +import org.opengis.filter.spatial.BBOX; + + + public class DB2SpatialFiltersTest extends JDBCSpatialFiltersTest { @Override @@ -32,4 +39,22 @@ dataStore.setDatabaseSchema("geotools"); } + public void testBboxFilter() throws Exception { + FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); + // should match "r2" and "r3" + BBOX bbox = ff.bbox(aname("geom"), 2, 3, 4, 5, "EPSG:4326"); + FeatureCollection features = dataStore.getFeatureSource(tname("road")).getFeatures(bbox); + assertEquals(2, features.size()); + } + + public void testBboxFilterDefault() throws Exception { + FilterFactory ff = CommonFactoryFinder.getFilterFactory(null); + // should match "r2" and "r3" + BBOX bbox = ff.bbox("", 2, 3, 4, 5, "EPSG:4326"); + FeatureCollection features = dataStore.getFeatureSource(tname("road")).getFeatures(bbox); + assertEquals(2, features.size()); + } + + + } |
From: <svn...@os...> - 2012-03-27 09:59:55
|
Author: aaime Date: 2012-03-27 02:59:43 -0700 (Tue, 27 Mar 2012) New Revision: 38649 Added: trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/ConnectionFactoryWrapper.java trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/HttpProtocolWrapper.java Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/WFSDataStore.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/MapServerWFSStrategy.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/NonStrictWFSStrategy.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/StrictWFSStrategy.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS100ProtocolHandler.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS_1_0_0_DataStore.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/GetFeatureQueryAdapter.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_DataStore.java trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_Protocol.java trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/GeoServerOnlineTest.java trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/GeoServerOnlineTest.java Log: [GEOT-4092] Add support for vendor parameters in WFS data store Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/WFSDataStore.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/WFSDataStore.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/WFSDataStore.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -18,12 +18,14 @@ import java.net.URI; import java.net.URL; +import java.util.Map; import java.util.Set; import javax.xml.namespace.QName; import org.geotools.data.DataAccess; import org.geotools.data.DataStore; +import org.geotools.factory.Hints.ClassKey; import org.geotools.geometry.jts.ReferencedEnvelope; import org.opengis.referencing.crs.CoordinateReferenceSystem; @@ -41,7 +43,16 @@ * /data/wfs/WFSDataStore.java $ */ public interface WFSDataStore extends DataStore { + /** + * Provides the vendor parameters to be used in a query + * + * @since 2.7.5 + */ + public static final ClassKey WFS_VENDOR_PARAMETERS = new ClassKey(Map.class); + + + /** * Overrides {@link DataAccess#getInfo()} so it type narrows to a {@link WFSServiceInfo} * * @return service information Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/MapServerWFSStrategy.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/MapServerWFSStrategy.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/MapServerWFSStrategy.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -100,8 +100,8 @@ BBOX newFilter = fac.bbox(attName, bbox.getMinX(), bbox.getMinY(), bbox.getMaxX(), bbox.getMaxY(), "EPSG:4326"); - query2=new Query(query.getTypeName(), query.getNamespace(), newFilter, - query.getMaxFeatures(), query.getPropertyNames(), query.getHandle()); + query2 = new Query(query); + query2.setFilter(newFilter); } } catch (IllegalFilterException e) { query2=query; Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/NonStrictWFSStrategy.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/NonStrictWFSStrategy.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/NonStrictWFSStrategy.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -24,6 +24,7 @@ import org.geotools.data.Query; import org.geotools.data.Transaction; import org.geotools.data.crs.ForceCoordinateSystemFeatureReader; +import org.geotools.data.wfs.protocol.http.HttpMethod; import org.geotools.feature.SchemaException; import org.geotools.filter.visitor.FixBBOXFilterVisitor; import org.geotools.referencing.CRS; @@ -98,10 +99,18 @@ protected FeatureReader<SimpleFeatureType, SimpleFeature> createFeatureReader(Transaction transaction, Query query) throws IOException { Data data; - data = createFeatureReaderPOST(query, transaction); - - if (data.reader == null) + + if(store.preferredProtocol == HttpMethod.POST) { + data = createFeatureReaderPOST(query, transaction); + + if (data.reader == null) + data = createFeatureReaderGET(query, transaction); + } else { data = createFeatureReaderGET(query, transaction); + + if (data.reader == null) + data = createFeatureReaderPOST(query, transaction); + } if (data.reader == null && data.saxException != null) throw (IOException) new IOException(data.saxException.toString()).initCause(data.saxException); Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/StrictWFSStrategy.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/StrictWFSStrategy.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/StrictWFSStrategy.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -158,12 +158,13 @@ if( visitor.requiresPostProcessing() && query.getPropertyNames()!=Query.ALL_NAMES){ FilterAttributeExtractor attributeExtractor=new FilterAttributeExtractor(); query.getFilter().accept( attributeExtractor, null ); - Set<String> properties=new HashSet<String>(attributeExtractor.getAttributeNameSet()); + Set<String> properties = new HashSet<String>(attributeExtractor.getAttributeNameSet()); properties.addAll(Arrays.asList(query.getPropertyNames())); - this.query=new Query(query.getTypeName(), query.getFilter(), query.getMaxFeatures(), - (String[]) properties.toArray(new String[0]), query.getHandle()); - }else + this.query = new Query(query); + this.query.setPropertyNames((String[]) properties.toArray(new String[0])); + } else { this.query=query; + } this.filter=visitor.getFilter(); Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS100ProtocolHandler.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS100ProtocolHandler.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS100ProtocolHandler.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -59,7 +59,7 @@ return super.connectionFac; } - private WFSCapabilities parseCapabilities(InputStream capabilitiesReader) throws IOException { + protected WFSCapabilities parseCapabilities(InputStream capabilitiesReader) throws IOException { // TODO: move to some 1.0.0 specific class Map<String,Object> hints = new HashMap<String,Object>(); hints.put(DocumentFactory.VALIDATION_HINT, Boolean.FALSE); Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS_1_0_0_DataStore.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS_1_0_0_DataStore.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_0_0/WFS_1_0_0_DataStore.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -579,6 +579,15 @@ String encode = URLEncoder.encode(print,protocolHandler.getEncoding()); url += "&FILTER=" + encode; } + + // inject vendor params, if any + if(request.getHints() != null && request.getHints().get(WFSDataStore.WFS_VENDOR_PARAMETERS) != null) { + Map<String, String> vendorParams = (Map<String, String>) request.getHints().get(WFSDataStore.WFS_VENDOR_PARAMETERS); + for (Map.Entry<String, String> entry : vendorParams.entrySet()) { + url += "&" + entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), protocolHandler + .getEncoding()); + } + } } } @@ -731,6 +740,30 @@ return null; } + // inject vendor params, if any + if(query != null && query.getHints() != null && query.getHints().get(WFSDataStore.WFS_VENDOR_PARAMETERS) != null) { + String url = postUrl.toString(); + if ((url == null) || !url.endsWith("?")) { + url += "?"; + } + + boolean first = true; + if(query.getHints() != null && query.getHints().get(WFSDataStore.WFS_VENDOR_PARAMETERS) != null) { + Map<String, String> vendorParams = (Map<String, String>) query.getHints().get(WFSDataStore.WFS_VENDOR_PARAMETERS); + for (Map.Entry<String, String> entry : vendorParams.entrySet()) { + if(first) { + first = false; + } else { + url += "&"; + } + url += entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), protocolHandler + .getEncoding()); + } + } + + postUrl = new URL(url); + } + HttpURLConnection hc = protocolHandler.getConnectionFactory().getConnection(postUrl, POST); Writer w = getOutputStream(hc); Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/GetFeatureQueryAdapter.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/GetFeatureQueryAdapter.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/GetFeatureQueryAdapter.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -16,7 +16,10 @@ */ package org.geotools.data.wfs.v1_1_0; +import java.util.Map; + import org.geotools.data.Query; +import org.geotools.data.wfs.WFSDataStore; import org.geotools.data.wfs.protocol.wfs.GetFeature; import org.opengis.filter.Filter; import org.opengis.filter.sort.SortBy; @@ -76,5 +79,13 @@ public SortBy[] getSortBy() { return query.getSortBy(); } + + public Map<String, String> getVendorParameter() { + if(query.getHints() != null) { + return (Map<String, String>) query.getHints().get(WFSDataStore.WFS_VENDOR_PARAMETERS); + } else { + return null; + } + } } Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_DataStore.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_DataStore.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_DataStore.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -108,7 +108,7 @@ */ private static final boolean DEFAULT_HTTP_METHOD = true; - private final WFSProtocol wfs; + protected WFSProtocol wfs; private Map<String, SimpleFeatureType> byTypeNameTypes; @@ -320,8 +320,8 @@ Filter[] filters = wfs.splitFilters(query.getFilter()); Filter supportedFilter = filters[0]; Filter postFilter = filters[1]; - System.out.println("Supported filter: " + supportedFilter); - System.out.println("Unupported filter: " + postFilter); + LOGGER.fine("Supported filter: " + supportedFilter); + LOGGER.fine("Unupported filter: " + postFilter); ((Query) query).setFilter(supportedFilter); ((Query) query).setMaxFeatures(getMaxFeatures(query)); Modified: trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_Protocol.java =================================================================== --- trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_Protocol.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/main/java/org/geotools/data/wfs/v1_1_0/WFS_1_1_0_Protocol.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -16,9 +16,8 @@ */ package org.geotools.data.wfs.v1_1_0; -import static org.geotools.data.wfs.protocol.http.HttpMethod.GET; -import static org.geotools.data.wfs.protocol.http.HttpMethod.POST; -import static org.geotools.data.wfs.protocol.wfs.WFSOperationType.DESCRIBE_FEATURETYPE; +import static org.geotools.data.wfs.protocol.http.HttpMethod.*; +import static org.geotools.data.wfs.protocol.wfs.WFSOperationType.*; import java.io.File; import java.io.FileOutputStream; @@ -29,12 +28,12 @@ import java.net.URI; import java.net.URISyntaxException; import java.net.URL; +import java.net.URLEncoder; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -69,10 +68,6 @@ import org.apache.commons.io.IOUtils; import org.eclipse.emf.ecore.EObject; -import org.eclipse.xsd.XSDSchema; -import org.eclipse.xsd.util.XSDParser; -import org.eclipse.xsd.util.XSDSchemaLocationResolver; -import org.eclipse.xsd.util.XSDSchemaLocator; import org.geotools.data.DataSourceException; import org.geotools.data.Query; import org.geotools.data.wfs.protocol.http.HTTPProtocol; @@ -88,25 +83,16 @@ import org.geotools.data.wfs.v1_1_0.parsers.EmfAppSchemaParser; import org.geotools.filter.Capabilities; import org.geotools.geometry.jts.ReferencedEnvelope; -import org.geotools.gml3.smil.SMIL20; -import org.geotools.gml3.smil.SMIL20LANG; import org.geotools.referencing.crs.DefaultGeographicCRS; import org.geotools.util.logging.Logging; import org.geotools.wfs.WFS; -import org.geotools.wfs.v1_1.WFSConfiguration; -import org.geotools.xlink.XLINK; import org.geotools.xml.Configuration; import org.geotools.xml.Encoder; import org.geotools.xml.Parser; -import org.geotools.xml.SchemaLocationResolver; -import org.geotools.xml.SchemaLocator; -import org.geotools.xml.Schemas; -import org.geotools.xml.XSD; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.filter.Filter; import org.opengis.filter.capability.FilterCapabilities; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.picocontainer.MutablePicoContainer; import org.xml.sax.SAXException; /** @@ -142,9 +128,9 @@ */ private final Map<String, FeatureTypeType> typeInfos; - private HTTPProtocol http; + protected HTTPProtocol http; - private final Charset defaultEncoding; + protected final Charset defaultEncoding; public WFS_1_1_0_Protocol(InputStream capabilitiesReader, HTTPProtocol http, Charset defaultEncoding) throws IOException { @@ -475,11 +461,18 @@ URL url = getOperationURL(WFSOperationType.GET_FEATURE, false); RequestComponents reqParts = strategy.createGetFeatureRequest(this, request); + GetFeatureType requestType = reqParts.getServerRequest(); + + // build the kvp taking into account eventual vendor params Map<String, String> getFeatureKvp = reqParts.getKvpParameters(); - GetFeatureType requestType = reqParts.getServerRequest(); + if(request instanceof GetFeatureQueryAdapter) { + GetFeatureQueryAdapter adapter = (GetFeatureQueryAdapter) request; + if(adapter.getVendorParameter() != null) { + getFeatureKvp.putAll(adapter.getVendorParameter()); + } + } + - System.out.println(" > getFeatureGET: Request url: " + url + ". Parameters: " - + getFeatureKvp); WFSResponse response = issueGetRequest(requestType, url, getFeatureKvp); return response; @@ -493,7 +486,30 @@ throw new UnsupportedOperationException( "The server does not support GetFeature for HTTP method POST"); } - URL url = getOperationURL(WFSOperationType.GET_FEATURE, true); + URL postURL = getOperationURL(WFSOperationType.GET_FEATURE, true); + + // support vendor parameters, GeoServer way + if(request instanceof GetFeatureQueryAdapter) { + GetFeatureQueryAdapter adapter = (GetFeatureQueryAdapter) request; + if(adapter.getVendorParameter() != null) { + String url = postURL.toString(); + if ((url == null) || !url.endsWith("?")) { + url += "?"; + } + + boolean first = true; + for (Map.Entry<String, String> entry : adapter.getVendorParameter().entrySet()) { + if(first) { + first = false; + } else { + url += "&"; + } + url += entry.getKey() + "=" + URLEncoder.encode(entry.getValue(), "UTF-8"); + } + + postURL = new URL(url); + } + } RequestComponents reqParts = strategy.createGetFeatureRequest(this, request); GetFeatureType serverRequest = reqParts.getServerRequest(); @@ -509,7 +525,7 @@ if (!XMLConstants.DEFAULT_NS_PREFIX.equals(prefix)) { encoder.getNamespaces().declarePrefix(prefix, namespace); } - WFSResponse response = issuePostRequest(serverRequest, url, encoder); + WFSResponse response = issuePostRequest(serverRequest, postURL, encoder); return response; } @@ -543,7 +559,7 @@ return typeInfos.get(typeName); } - private WFSCapabilitiesType parseCapabilities(InputStream capabilitiesReader) + protected WFSCapabilitiesType parseCapabilities(InputStream capabilitiesReader) throws IOException { final Configuration wfsConfig = strategy.getWfsConfiguration(); final Parser parser = new Parser(wfsConfig); Added: trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/ConnectionFactoryWrapper.java =================================================================== --- trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/ConnectionFactoryWrapper.java (rev 0) +++ trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/ConnectionFactoryWrapper.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -0,0 +1,54 @@ +package org.geotools.data.wfs.v1_0_0; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.nio.charset.Charset; + +import org.geotools.data.wfs.protocol.http.HttpMethod; +import org.geotools.wfs.protocol.ConnectionFactory; + +/** + * Helper class for the tests + * @author aaime + * + */ +public class ConnectionFactoryWrapper implements ConnectionFactory { + + public ConnectionFactory delegate; + + public ConnectionFactoryWrapper(ConnectionFactory delegate) { + this.delegate = delegate; + } + + public String getAuthUsername() { + return delegate.getAuthUsername(); + } + + public String getAuthPassword() { + return delegate.getAuthPassword(); + } + + public boolean isTryGzip() { + return delegate.isTryGzip(); + } + + public Charset getEncoding() { + return delegate.getEncoding(); + } + + public HttpURLConnection getConnection(URL query, HttpMethod method) throws IOException { + return delegate.getConnection(query, method); + } + + public InputStream getInputStream(HttpURLConnection hc) throws IOException { + return delegate.getInputStream(hc); + } + + public InputStream getInputStream(URL query, HttpMethod method) throws IOException { + return delegate.getInputStream(query, method); + } + + +} Modified: trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/GeoServerOnlineTest.java =================================================================== --- trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/GeoServerOnlineTest.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_0_0/GeoServerOnlineTest.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -17,13 +17,12 @@ */ package org.geotools.data.wfs.v1_0_0; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; import java.io.IOException; import java.io.InputStream; import java.net.ConnectException; +import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.NoRouteToHostException; import java.net.URL; @@ -48,13 +47,17 @@ import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.data.simple.SimpleFeatureStore; +import org.geotools.data.wfs.WFSDataStore; import org.geotools.data.wfs.WFSDataStoreFactory; +import org.geotools.data.wfs.protocol.http.HttpMethod; import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.GeoTools; +import org.geotools.factory.Hints; import org.geotools.feature.IllegalAttributeException; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.geotools.filter.IllegalFilterException; import org.geotools.geometry.jts.ReferencedEnvelope; +import org.geotools.wfs.protocol.ConnectionFactory; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -490,7 +493,75 @@ } } } + + @Test + public void testVendorParametersGet() throws Exception { + testVendorParameters(Boolean.FALSE); + } + + @Test + public void testVendorParametersPost() throws Exception { + testVendorParameters(Boolean.TRUE); + } + private void testVendorParameters(Boolean usePost) throws IOException { + if (url == null) + return; + + Map m = new HashMap(); + m.put(WFSDataStoreFactory.URL.key, url); + m.put(WFSDataStoreFactory.TIMEOUT.key, new Integer(100000)); + m.put(WFSDataStoreFactory.PROTOCOL.key, usePost); + WFS_1_0_0_DataStore wfs = (WFS_1_0_0_DataStore) (new WFSDataStoreFactory()) + .createDataStore(m); + + final WFS100ProtocolHandler originalHandler = wfs.protocolHandler; + wfs.protocolHandler = new WFS100ProtocolHandler(null, originalHandler.getConnectionFactory()) { + @Override + protected WFSCapabilities parseCapabilities(InputStream capabilitiesReader) + throws IOException { + return originalHandler.getCapabilities(); + } + + @Override + public ConnectionFactory getConnectionFactory() { + return new ConnectionFactoryWrapper(super.getConnectionFactory()) { + + @Override + public HttpURLConnection getConnection(URL query, HttpMethod method) + throws IOException { + String[] keyValueArray = query.getQuery().split("&"); + Map<String, String> kvp = new HashMap<String, String>(); + for (String keyValue : keyValueArray) { + String[] skv = keyValue.split("="); + kvp.put(skv[0], skv[1]); + } + + // check the vendor params actually made it into the url + assertEquals("true", kvp.get("strict")); + assertEquals("mysecret", kvp.get("authkey")); + assertEquals("low%3A2000000%3Bhigh%3A5000000", kvp.get("viewparams")); + + return super.getConnection(query, method); + } + }; + } + }; + + Map<String, String> vparams = new HashMap<String, String>(); + vparams.put("authkey", "mysecret"); + vparams.put("viewparams", "low:2000000;high:5000000"); + vparams.put("strict", "true"); + Hints hints = new Hints(WFSDataStore.WFS_VENDOR_PARAMETERS, vparams); + Query q = new Query("topp:states"); + q.setHints(hints); + + // try with + FeatureReader fr = wfs.getFeatureReader(q, Transaction.AUTO_COMMIT); + assertTrue(fr.hasNext()); + fr.close(); + } + private Id createFidFilter(SimpleFeatureSource fs) throws IOException { SimpleFeatureIterator iter = fs.getFeatures().features(); @@ -508,4 +579,6 @@ iter.close(); } } + + } Modified: trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/GeoServerOnlineTest.java =================================================================== --- trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/GeoServerOnlineTest.java 2012-03-27 09:50:39 UTC (rev 38648) +++ trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/GeoServerOnlineTest.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -17,19 +17,27 @@ */ package org.geotools.data.wfs.v1_1_0; -import static org.geotools.data.wfs.v1_1_0.DataTestSupport.GEOS_STATES; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.geotools.data.wfs.v1_1_0.DataTestSupport.*; +import static org.junit.Assert.*; import java.io.IOException; +import java.io.Serializable; +import java.net.URL; import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import org.geotools.data.FeatureReader; import org.geotools.data.Query; +import org.geotools.data.Transaction; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.data.wfs.WFSDataStore; +import org.geotools.data.wfs.WFSDataStoreFactory; +import org.geotools.data.wfs.protocol.http.HTTPResponse; import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.Hints; import org.junit.Test; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; @@ -98,5 +106,76 @@ iterator.close(); } } + + @Test + public void testVendorParametersGet() throws Exception { + testVendorParameters(Boolean.FALSE); + } + + @Test + public void testVendorParametersPost() throws Exception { + testVendorParameters(Boolean.TRUE); + } + private void testVendorParameters(Boolean usePost) throws IOException { + if (Boolean.FALSE.equals(serviceAvailable)) { + return; + } + + // we alter the data store, thus we cannot use the static "wfs" field, we need to create a new one + Map<String, Serializable> params = new HashMap<String, Serializable>(); + params.put(WFSDataStoreFactory.URL.key, SERVER_URL); + params.put(WFSDataStoreFactory.PROTOCOL.key, usePost); + params.put("USE_PULL_PARSER", Boolean.TRUE); + WFSDataStoreFactory dataStoreFactory = new WFSDataStoreFactory(); + WFSDataStore wfs = dataStoreFactory.createDataStore(params); + + final WFS_1_1_0_Protocol originalHandler = (WFS_1_1_0_Protocol) ((WFS_1_1_0_DataStore) wfs).wfs; + originalHandler.http = new HttpProtocolWrapper(originalHandler.http) { + + @Override + public HTTPResponse issueGet(URL baseUrl, Map<String, String> kvp) throws IOException { + // check the vendor params actually made it into the url (at this stage they are not url encoded) + assertEquals("true", kvp.get("strict")); + assertEquals("mysecret", kvp.get("authkey")); + assertEquals("low:2000000;high:5000000", kvp.get("viewparams")); + + return super.issueGet(baseUrl, kvp); + } + + @Override + public HTTPResponse issuePost(URL targetUrl, POSTCallBack callback) throws IOException { + String[] keyValueArray = targetUrl.getQuery().split("&"); + Map<String, String> kvp = new HashMap<String, String>(); + for (String keyValue : keyValueArray) { + String[] skv = keyValue.split("="); + kvp.put(skv[0], skv[1]); + } + + // check the vendor params actually made it into the url + assertEquals("true", kvp.get("strict")); + assertEquals("mysecret", kvp.get("authkey")); + assertEquals("low%3A2000000%3Bhigh%3A5000000", kvp.get("viewparams")); + + return super.issuePost(targetUrl, callback); + } + + }; + + + Map<String, String> vparams = new HashMap<String, String>(); + vparams.put("authkey", "mysecret"); + vparams.put("viewparams", "low:2000000;high:5000000"); + vparams.put("strict", "true"); + Hints hints = new Hints(WFSDataStore.WFS_VENDOR_PARAMETERS, vparams); + Query q = new Query("topp:states"); + q.setHints(hints); + + // read some features, check + FeatureReader fr = wfs.getFeatureReader(q, Transaction.AUTO_COMMIT); + assertTrue(fr.hasNext()); + fr.close(); + } + + } Added: trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/HttpProtocolWrapper.java =================================================================== --- trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/HttpProtocolWrapper.java (rev 0) +++ trunk/modules/unsupported/wfs/src/test/java/org/geotools/data/wfs/v1_1_0/HttpProtocolWrapper.java 2012-03-27 09:59:43 UTC (rev 38649) @@ -0,0 +1,56 @@ +package org.geotools.data.wfs.v1_1_0; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Map; + +import org.geotools.data.wfs.protocol.http.HTTPProtocol; +import org.geotools.data.wfs.protocol.http.HTTPResponse; + +public class HttpProtocolWrapper implements HTTPProtocol { + + HTTPProtocol delegate; + + public HttpProtocolWrapper(HTTPProtocol delegate) { + this.delegate = delegate; + } + + public void setTryGzip(boolean tryGzip) { + delegate.setTryGzip(tryGzip); + } + + public boolean isTryGzip() { + return delegate.isTryGzip(); + } + + public void setAuth(String username, String password) { + delegate.setAuth(username, password); + } + + public boolean isAuthenticating() { + return delegate.isAuthenticating(); + } + + public void setTimeoutMillis(int milliseconds) { + delegate.setTimeoutMillis(milliseconds); + } + + public int getTimeoutMillis() { + return delegate.getTimeoutMillis(); + } + + public HTTPResponse issueGet(URL baseUrl, Map<String, String> kvp) throws IOException { + return delegate.issueGet(baseUrl, kvp); + } + + public HTTPResponse issuePost(URL targetUrl, POSTCallBack callback) throws IOException { + return delegate.issuePost(targetUrl, callback); + } + + public URL createUrl(URL baseUrl, Map<String, String> queryStringKvp) + throws MalformedURLException { + return delegate.createUrl(baseUrl, queryStringKvp); + } + +} |