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-05-13 13:15:40 -0700 (Sun, 13 May 2012) New Revision: 38721 Added: branches/2.7.x/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz Modified: branches/2.7.x/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java branches/2.7.x/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java Log: [GEOT-4144] ImageWorker.writePNG will write out paletted 16bit PNG files (which cannot exist, out of spec) Modified: branches/2.7.x/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java =================================================================== --- branches/2.7.x/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java 2012-05-13 20:13:17 UTC (rev 38720) +++ branches/2.7.x/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java 2012-05-13 20:15:40 UTC (rev 38721) @@ -2414,9 +2414,20 @@ // we have to reduce colors forceIndexColorModelForGIF(true); } else if(!(image.getColorModel() instanceof ComponentColorModel) && !(image.getColorModel() instanceof IndexColorModel)) { - // png supports gray, rgb, rgba and paletted, but not, for example, double and float values + // png supports gray, rgb, rgba and paletted 8 bit, but not, for example, double and float values, or 16 bits palettes forceComponentColorModel(); } + + // PNG does not support all kinds of index color models + if(image.getColorModel() instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel) image.getColorModel(); + // PNG supports up to 256 colors, beyond that we have to expand to RGB + if(icm.getMapSize() > 256) { + forceComponentColorModel(true, true); + rescaleToBytes(); + } + } + if(LOGGER.isLoggable(Level.FINER)) LOGGER.finer("Encoded input image for png writer"); Modified: branches/2.7.x/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java =================================================================== --- branches/2.7.x/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java 2012-05-13 20:13:17 UTC (rev 38720) +++ branches/2.7.x/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java 2012-05-13 20:15:40 UTC (rev 38721) @@ -16,12 +16,7 @@ */ package org.geotools.image; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.awt.Color; import java.awt.Transparency; @@ -43,6 +38,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Random; +import java.util.zip.GZIPInputStream; import javax.imageio.ImageIO; import javax.media.jai.ImageLayout; @@ -396,7 +392,65 @@ readWorker.setImage(ImageIO.read(outFile)); assertTrue(readWorker.getRenderedImage().getColorModel() instanceof IndexColorModel); } + + @Test + public void test16BitPNG() throws Exception { + // the resource has been compressed since the palette is way larger than the image itself, + // and the palette does not get compressed + InputStream gzippedStream = ImageWorkerTest.class.getResource("test-data/sf-sfdem.tif.gz").openStream(); + GZIPInputStream is = new GZIPInputStream(gzippedStream); + try { + BufferedImage bi = ImageIO.read(is); + IndexColorModel icm = (IndexColorModel) bi.getColorModel(); + assertEquals(65536, icm.getMapSize()); + + final File outFile = TestData.temp(this, "temp.png"); + ImageWorker worker = new ImageWorker(bi); + worker.writePNG(outFile, "FILTERED", 0.75f, true, false); + worker.dispose(); + + // make sure we can read it + BufferedImage back = ImageIO.read(outFile); + + // we expect a RGB one + ComponentColorModel ccm = (ComponentColorModel) back.getColorModel(); + assertEquals(3, ccm.getNumColorComponents()); + } finally { + is.close(); + } + } + + /** + * Testing TIFF capabilities. + * + * @throws IOException If an error occured while writting the image. + */ + @Test + public void testTIFFWrite() throws IOException { + assertTrue("Assertions should be enabled.", ImageWorker.class.desiredAssertionStatus()); + // Get the image of the world with transparency. + final ImageWorker worker = new ImageWorker(worldImage); + show(worker, "Input file"); + // ///////////////////////////////////////////////////////////////////// + // tiff deflated untiled + // ///////////////////////////////////////////////////////////////////// + final File outFile = TestData.temp(this, "temp.tiff"); + worker.writeTIFF(outFile, "Deflate", 0.75f, -1, -1); + final ImageWorker readWorker = new ImageWorker(ImageIO.read(outFile)); + show(readWorker, "Tiff untiled"); + + // ///////////////////////////////////////////////////////////////////// + // tiff deflated compressed tiled + // ///////////////////////////////////////////////////////////////////// + worker.setImage(worldImage); + worker.writeTIFF(outFile, "Deflate", 0.75f, 32, 32); + readWorker.setImage(ImageIO.read(outFile)); + show(readWorker, "Tiff jpeg compressed, tiled"); + + outFile.delete(); + } + /** * Tests the conversion between RGB and indexed color model. */ Added: branches/2.7.x/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz =================================================================== --- branches/2.7.x/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz (rev 0) +++ branches/2.7.x/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz 2012-05-13 20:15:40 UTC (rev 38721) @@ -0,0 +1,55 @@ + O |
Author: aaime Date: 2012-05-13 13:13:17 -0700 (Sun, 13 May 2012) New Revision: 38720 Added: trunk/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz Modified: trunk/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java trunk/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java Log: [GEOT-4144] ImageWorker.writePNG will write out paletted 16bit PNG files (which cannot exist, out of spec) Modified: trunk/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java =================================================================== --- trunk/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java 2012-05-12 16:50:22 UTC (rev 38719) +++ trunk/modules/library/coverage/src/main/java/org/geotools/image/ImageWorker.java 2012-05-13 20:13:17 UTC (rev 38720) @@ -2415,9 +2415,20 @@ // we have to reduce colors forceIndexColorModelForGIF(true); } else if(!(image.getColorModel() instanceof ComponentColorModel) && !(image.getColorModel() instanceof IndexColorModel)) { - // png supports gray, rgb, rgba and paletted, but not, for example, double and float values + // png supports gray, rgb, rgba and paletted 8 bit, but not, for example, double and float values, or 16 bits palettes forceComponentColorModel(); } + + // PNG does not support all kinds of index color models + if(image.getColorModel() instanceof IndexColorModel) { + IndexColorModel icm = (IndexColorModel) image.getColorModel(); + // PNG supports up to 256 colors, beyond that we have to expand to RGB + if(icm.getMapSize() > 256) { + forceComponentColorModel(true, true); + rescaleToBytes(); + } + } + if(LOGGER.isLoggable(Level.FINER)) LOGGER.finer("Encoded input image for png writer"); Modified: trunk/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java =================================================================== --- trunk/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java 2012-05-12 16:50:22 UTC (rev 38719) +++ trunk/modules/library/coverage/src/test/java/org/geotools/image/ImageWorkerTest.java 2012-05-13 20:13:17 UTC (rev 38720) @@ -16,12 +16,7 @@ */ package org.geotools.image; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.*; import java.awt.Color; import java.awt.Transparency; @@ -43,6 +38,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.Random; +import java.util.zip.GZIPInputStream; import javax.imageio.ImageIO; import javax.media.jai.ImageLayout; @@ -398,6 +394,33 @@ assertTrue(readWorker.getRenderedImage().getColorModel() instanceof IndexColorModel); } + @Test + public void test16BitPNG() throws Exception { + // the resource has been compressed since the palette is way larger than the image itself, + // and the palette does not get compressed + InputStream gzippedStream = ImageWorkerTest.class.getResource("test-data/sf-sfdem.tif.gz").openStream(); + GZIPInputStream is = new GZIPInputStream(gzippedStream); + try { + BufferedImage bi = ImageIO.read(is); + IndexColorModel icm = (IndexColorModel) bi.getColorModel(); + assertEquals(65536, icm.getMapSize()); + + final File outFile = TestData.temp(this, "temp.png"); + ImageWorker worker = new ImageWorker(bi); + worker.writePNG(outFile, "FILTERED", 0.75f, true, false); + worker.dispose(); + + // make sure we can read it + BufferedImage back = ImageIO.read(outFile); + + // we expect a RGB one + ComponentColorModel ccm = (ComponentColorModel) back.getColorModel(); + assertEquals(3, ccm.getNumColorComponents()); + } finally { + is.close(); + } + } + /** * Testing TIFF capabilities. * Added: trunk/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz =================================================================== --- trunk/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz (rev 0) +++ trunk/modules/library/coverage/src/test/resources/org/geotools/image/test-data/sf-sfdem.tif.gz 2012-05-13 20:13:17 UTC (rev 38720) @@ -0,0 +1,55 @@ + O |
Author: aaime Date: 2012-05-12 09:50:22 -0700 (Sat, 12 May 2012) New Revision: 38719 Added: branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java Modified: branches/2.7.x/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java Log: [GEOT-4113] Shp publish into postgis datastore with MULTIPOLYGON EMPTY value violates check constraint. Modified: branches/2.7.x/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java =================================================================== --- branches/2.7.x/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java 2012-05-12 16:37:03 UTC (rev 38718) +++ branches/2.7.x/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -85,6 +85,10 @@ * The <tt>srid</tt> parameter is the spatial reference system identifier * of the geometry, or 0 if not known. * </p> + * <p> + * Attention should be paid to emtpy geometries (<code>g.isEmtpy() == true</code>) as + * they cannot be encoded in WKB and several databases fail to handle them property. + * Common treatment is to equate them to NULL</p> */ public abstract void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException; Added: branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java =================================================================== --- branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java (rev 0) +++ branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -0,0 +1,97 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.jdbc; + +import org.geotools.data.DefaultTransaction; +import org.geotools.data.FeatureWriter; +import org.geotools.data.Transaction; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.geometry.jts.JTSFactoryFinder; +import org.geotools.referencing.CRS; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.referencing.crs.CoordinateReferenceSystem; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKTReader; + +/** + * + * + * @source $URL: + * http://svn.osgeo.org/geotools/trunk/modules/library/jdbc/src/test/java/org/geotools/ + * jdbc/JDBCEmptyGeometryTest.java $ + */ +public abstract class JDBCEmptyGeometryTest extends JDBCTestSupport { + + @Override + protected abstract JDBCEmptyGeometryTestSetup createTestSetup(); + + public void testEmptyPoint() throws Exception { + testInsertEmptyGeometry("POINT"); + } + + public void testEmptyLine() throws Exception { + testInsertEmptyGeometry("LINESTRING"); + } + + public void testEmptyPolygon() throws Exception { + testInsertEmptyGeometry("POLYGON"); + } + + public void testEmptyMultiPoint() throws Exception { + testInsertEmptyGeometry("MULTIPOINT"); + } + + public void testEmptyMultiLine() throws Exception { + testInsertEmptyGeometry("MULTILINESTRING"); + } + + public void testEmptyMultiPolygon() throws Exception { + testInsertEmptyGeometry("MULTIPOLYGON"); + } + + private void testInsertEmptyGeometry(String type) throws Exception { + WKTReader reader = new WKTReader(); + Geometry emptyGeometry = reader.read(type.toUpperCase() + " EMPTY"); + + Transaction tx = new DefaultTransaction(); + FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriterAppend( + tname("empty"), tx); + SimpleFeature feature = writer.next(); + feature.setAttribute(aname("id"), new Integer(100)); + feature.setAttribute(aname("geom_" + type.toLowerCase()), emptyGeometry); + feature.setAttribute(aname("name"), new String("empty " + type)); + writer.write(); + writer.close(); + tx.commit(); + tx.close(); + + SimpleFeatureCollection fc = dataStore.getFeatureSource(tname("empty")).getFeatures(); + assertEquals(1, fc.size()); + SimpleFeatureIterator fi = fc.features(); + SimpleFeature nf = fi.next(); + fi.close(); + Geometry geometry = (Geometry) nf.getDefaultGeometry(); + // either null or empty, we don't really care + assertTrue(geometry == null || geometry.isEmpty()); + } +} Added: branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java =================================================================== --- branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java (rev 0) +++ branches/2.7.x/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -0,0 +1,50 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.jdbc; + +import java.sql.SQLException; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java $ + */ +public abstract class JDBCEmptyGeometryTestSetup extends JDBCDelegatingTestSetup { + + protected JDBCEmptyGeometryTestSetup(JDBCTestSetup delegate) { + super(delegate); + } + + protected final void setUpData() throws Exception { + //kill all the data + try { + dropEmptyGeometryTable(); + } catch (SQLException e) { + } + + //create all the data + createEmptyGeometryTable(); + } + + protected abstract void createEmptyGeometryTable() throws Exception; + + /** + * Drops the "empty" table previously created + */ + protected abstract void dropEmptyGeometryTable() throws Exception; + +} Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java 2012-05-12 16:37:03 UTC (rev 38718) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -340,11 +340,15 @@ public void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException { - sql.append("ST_GeomFromText ('"); - sql.append(new WKTWriter().write(value)); - sql.append("',"); - sql.append(srid); - sql.append(")"); + if(value == null || value.isEmpty()) { + sql.append("ST_GeomFromText ('"); + sql.append(new WKTWriter().write(value)); + sql.append("',"); + sql.append(srid); + sql.append(")"); + } else { + sql.append("NULL"); + } } Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java 2012-05-12 16:37:03 UTC (rev 38718) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -189,7 +189,7 @@ @Override public void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException { - if (value != null) { + if (value != null && !value.isEmpty()) { sql.append("ST_GeomFromText ('"); sql.append(new WKTWriter().write(value)); sql.append("',"); Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java 2012-05-12 16:37:03 UTC (rev 38718) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -174,7 +174,7 @@ public void setGeometryValue(Geometry g, int srid, Class binding, PreparedStatement ps, int column) throws SQLException { - if ( g == null ) { + if ( g == null || g.isEmpty() ) { ps.setNull( column, Types.BLOB ); return; } Added: branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java (rev 0) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -0,0 +1,34 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.h2; + +import org.geotools.jdbc.JDBCEmptyGeometryTest; +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java $ + */ +public class H2EmptyGeometryTest extends JDBCEmptyGeometryTest { + + @Override + protected JDBCEmptyGeometryTestSetup createTestSetup() { + return new H2EmptyGeometryTestSetup(new H2TestSetup()); + } + +} \ No newline at end of file Added: branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java (rev 0) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -0,0 +1,63 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.h2; + +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; +import org.geotools.jdbc.JDBCTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISBooleanTestSetup.java $ + */ +public class H2EmptyGeometryTestSetup extends JDBCEmptyGeometryTestSetup { + + public H2EmptyGeometryTestSetup(JDBCTestSetup delegate) { + super(delegate); + } + + @Override + protected void createEmptyGeometryTable() throws Exception { + //create table schema + run("CREATE TABLE \"geotools\".\"empty\"(" // + + "\"fid\" serial primary key, " // + + "\"id\" integer, " // + + "\"geom_point\" POINT, " // + + "\"geom_linestring\" LINESTRING, " // + + "\"geom_polygon\" POLYGON, " // + + "\"geom_multipoint\" MULTIPOINT, " // + + "\"geom_multilinestring\" MULTILINESTRING, " // + + "\"geom_multipolygon\" MULTIPOLYGON, " // + + "\"name\" varchar" // + + ")"); + + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_point', 4326, 'POINT', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_linestring', 4326, 'LINESTRING', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_polygon', 4326, 'POLYGON', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_multipoint', 4326, 'MULTIPOINT', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_multilinestring', 4326, 'MULTILINESTRING', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_multipolygon', 4326, 'MULTIPOLYGON', 2)"); + } + + @Override + protected void dropEmptyGeometryTable() throws Exception { + run( "DROP TABLE \"geotools\".\"empty\""); + + } + + +} Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java 2012-05-12 16:37:03 UTC (rev 38718) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -718,7 +718,7 @@ @Override public void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException { - if(value == null) { + if (value == null || value.isEmpty()) { sql.append("NULL"); } else { if (value instanceof LinearRing) { Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java 2012-05-12 16:37:03 UTC (rev 38718) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -189,7 +189,7 @@ @Override public void setGeometryValue(Geometry g, int srid, Class binding, PreparedStatement ps, int column) throws SQLException { - if (g != null) { + if (g != null && !g.isEmpty()) { if (g instanceof LinearRing ) { //postgis does not handle linear rings, convert to just a line string g = g.getFactory().createLineString(((LinearRing) g).getCoordinateSequence()); Added: branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java (rev 0) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -0,0 +1,34 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.postgis; + +import org.geotools.jdbc.JDBCEmptyGeometryTest; +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java $ + */ +public class PostGISEmptyGeometryTest extends JDBCEmptyGeometryTest { + + @Override + protected JDBCEmptyGeometryTestSetup createTestSetup() { + return new PostGISEmptyGeometryTestSetup(new PostGISTestSetup()); + } + +} \ No newline at end of file Added: branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java (rev 0) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -0,0 +1,63 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.postgis; + +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; +import org.geotools.jdbc.JDBCTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISBooleanTestSetup.java $ + */ +public class PostGISEmptyGeometryTestSetup extends JDBCEmptyGeometryTestSetup { + + public PostGISEmptyGeometryTestSetup(JDBCTestSetup delegate) { + super(delegate); + } + + @Override + protected void createEmptyGeometryTable() throws Exception { + //create table schema + run("CREATE TABLE \"empty\"(" // + + "\"fid\" serial primary key, " // + + "\"id\" integer, " // + + "\"geom_point\" geometry, " // + + "\"geom_linestring\" geometry, " // + + "\"geom_polygon\" geometry, " // + + "\"geom_multipoint\" geometry, " // + + "\"geom_multilinestring\" geometry, " // + + "\"geom_multipolygon\" geometry, " // + + "\"name\" varchar," // + + "CONSTRAINT enforce_geotype_geom_1 CHECK (geometrytype(geom_point) = 'POINT'::text OR geom_point IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_2 CHECK (geometrytype(geom_linestring) = 'LINESTRING'::text OR geom_linestring IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_3 CHECK (geometrytype(geom_polygon) = 'POLYGON'::text OR geom_polygon IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_4 CHECK (geometrytype(geom_multipoint) = 'MULTIPOINT'::text OR geom_multipoint IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_5 CHECK (geometrytype(geom_multilinestring) = 'MULTILINESTRING'::text OR geom_multilinestring IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_6 CHECK (geometrytype(geom_multipolygon) = 'MULTIPOLYGON'::text OR geom_multipolygon IS NULL)" // + + ")"); + + } + + @Override + protected void dropEmptyGeometryTable() throws Exception { + run( "DROP TABLE \"empty\""); + + } + + +} Modified: branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java 2012-05-12 16:37:03 UTC (rev 38718) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -69,11 +69,12 @@ run("INSERT INTO \"ft1\" VALUES(0, GeometryFromText('POINT(0 0)', 4326), 0, 0.0, 'zero')"); run("INSERT INTO \"ft1\" VALUES(1, GeometryFromText('POINT(1 1)', 4326), 1, 1.1, 'one')"); run("INSERT INTO \"ft1\" VALUES(2, GeometryFromText('POINT(2 2)', 4326), 2, 2.2, 'two')"); - // advance the sequence to 2 + // advance the sequence to 2 run("SELECT nextval(pg_get_serial_sequence('ft1','id'))"); run("SELECT nextval(pg_get_serial_sequence('ft1','id'))"); // analyze so that the stats will be up to date run("ANALYZE \"ft1\""); + } Added: branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java =================================================================== --- branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java (rev 0) +++ branches/2.7.x/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java 2012-05-12 16:50:22 UTC (rev 38719) @@ -0,0 +1,35 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.postgis.ps; + +import org.geotools.data.postgis.PostGISEmptyGeometryTestSetup; +import org.geotools.jdbc.JDBCEmptyGeometryTest; +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java $ + */ +public class PostGISEmptyGeometryTest extends JDBCEmptyGeometryTest { + + @Override + protected JDBCEmptyGeometryTestSetup createTestSetup() { + return new PostGISEmptyGeometryTestSetup(new PostGISPSTestSetup()); + } + +} \ No newline at end of file |
Author: aaime Date: 2012-05-12 09:37:03 -0700 (Sat, 12 May 2012) New Revision: 38718 Added: trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java Modified: trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java Log: [GEOT-4113] Shp publish into postgis datastore with MULTIPOLYGON EMPTY value violates check constraint. Modified: trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java =================================================================== --- trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java 2012-05-12 16:10:08 UTC (rev 38717) +++ trunk/modules/library/jdbc/src/main/java/org/geotools/jdbc/BasicSQLDialect.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -90,6 +90,10 @@ * The <tt>srid</tt> parameter is the spatial reference system identifier * of the geometry, or 0 if not known. * </p> + * <p> + * Attention should be paid to emtpy geometries (<code>g.isEmtpy() == true</code>) as + * they cannot be encoded in WKB and several databases fail to handle them property. + * Common treatment is to equate them to NULL</p> */ public abstract void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException; Added: trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java =================================================================== --- trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java (rev 0) +++ trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTest.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -0,0 +1,97 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.jdbc; + +import org.geotools.data.DefaultTransaction; +import org.geotools.data.FeatureWriter; +import org.geotools.data.Transaction; +import org.geotools.data.simple.SimpleFeatureCollection; +import org.geotools.data.simple.SimpleFeatureIterator; +import org.geotools.geometry.jts.JTSFactoryFinder; +import org.geotools.referencing.CRS; +import org.opengis.feature.simple.SimpleFeature; +import org.opengis.feature.simple.SimpleFeatureType; +import org.opengis.referencing.crs.CoordinateReferenceSystem; + +import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.Point; +import com.vividsolutions.jts.io.ParseException; +import com.vividsolutions.jts.io.WKTReader; + +/** + * + * + * @source $URL: + * http://svn.osgeo.org/geotools/trunk/modules/library/jdbc/src/test/java/org/geotools/ + * jdbc/JDBCEmptyGeometryTest.java $ + */ +public abstract class JDBCEmptyGeometryTest extends JDBCTestSupport { + + @Override + protected abstract JDBCEmptyGeometryTestSetup createTestSetup(); + + public void testEmptyPoint() throws Exception { + testInsertEmptyGeometry("POINT"); + } + + public void testEmptyLine() throws Exception { + testInsertEmptyGeometry("LINESTRING"); + } + + public void testEmptyPolygon() throws Exception { + testInsertEmptyGeometry("POLYGON"); + } + + public void testEmptyMultiPoint() throws Exception { + testInsertEmptyGeometry("MULTIPOINT"); + } + + public void testEmptyMultiLine() throws Exception { + testInsertEmptyGeometry("MULTILINESTRING"); + } + + public void testEmptyMultiPolygon() throws Exception { + testInsertEmptyGeometry("MULTIPOLYGON"); + } + + private void testInsertEmptyGeometry(String type) throws Exception { + WKTReader reader = new WKTReader(); + Geometry emptyGeometry = reader.read(type.toUpperCase() + " EMPTY"); + + Transaction tx = new DefaultTransaction(); + FeatureWriter<SimpleFeatureType, SimpleFeature> writer = dataStore.getFeatureWriterAppend( + tname("empty"), tx); + SimpleFeature feature = writer.next(); + feature.setAttribute(aname("id"), new Integer(100)); + feature.setAttribute(aname("geom_" + type.toLowerCase()), emptyGeometry); + feature.setAttribute(aname("name"), new String("empty " + type)); + writer.write(); + writer.close(); + tx.commit(); + tx.close(); + + SimpleFeatureCollection fc = dataStore.getFeatureSource(tname("empty")).getFeatures(); + assertEquals(1, fc.size()); + SimpleFeatureIterator fi = fc.features(); + SimpleFeature nf = fi.next(); + fi.close(); + Geometry geometry = (Geometry) nf.getDefaultGeometry(); + // either null or empty, we don't really care + assertTrue(geometry == null || geometry.isEmpty()); + } +} Added: trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java =================================================================== --- trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java (rev 0) +++ trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -0,0 +1,50 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.jdbc; + +import java.sql.SQLException; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/library/jdbc/src/test/java/org/geotools/jdbc/JDBCEmptyGeometryTestSetup.java $ + */ +public abstract class JDBCEmptyGeometryTestSetup extends JDBCDelegatingTestSetup { + + protected JDBCEmptyGeometryTestSetup(JDBCTestSetup delegate) { + super(delegate); + } + + protected final void setUpData() throws Exception { + //kill all the data + try { + dropEmptyGeometryTable(); + } catch (SQLException e) { + } + + //create all the data + createEmptyGeometryTable(); + } + + protected abstract void createEmptyGeometryTable() throws Exception; + + /** + * Drops the "empty" table previously created + */ + protected abstract void dropEmptyGeometryTable() throws Exception; + +} Modified: trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java 2012-05-12 16:10:08 UTC (rev 38717) +++ trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2Dialect.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -349,11 +349,15 @@ public void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException { - sql.append("ST_GeomFromText ('"); - sql.append(new WKTWriter().write(value)); - sql.append("',"); - sql.append(srid); - sql.append(")"); + if(value == null || value.isEmpty()) { + sql.append("ST_GeomFromText ('"); + sql.append(new WKTWriter().write(value)); + sql.append("',"); + sql.append(srid); + sql.append(")"); + } else { + sql.append("NULL"); + } } Modified: trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java 2012-05-12 16:10:08 UTC (rev 38717) +++ trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectBasic.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -190,7 +190,7 @@ @Override public void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException { - if (value != null) { + if (value != null && !value.isEmpty()) { sql.append("ST_GeomFromText ('"); sql.append(new WKTWriter().write(value)); sql.append("',"); Modified: trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java 2012-05-12 16:10:08 UTC (rev 38717) +++ trunk/modules/plugin/jdbc/jdbc-h2/src/main/java/org/geotools/data/h2/H2DialectPrepared.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -175,7 +175,7 @@ public void setGeometryValue(Geometry g, int srid, Class binding, PreparedStatement ps, int column) throws SQLException { - if ( g == null ) { + if ( g == null || g.isEmpty() ) { ps.setNull( column, Types.BLOB ); return; } Added: trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java (rev 0) +++ trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTest.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -0,0 +1,34 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.h2; + +import org.geotools.jdbc.JDBCEmptyGeometryTest; +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java $ + */ +public class H2EmptyGeometryTest extends JDBCEmptyGeometryTest { + + @Override + protected JDBCEmptyGeometryTestSetup createTestSetup() { + return new H2EmptyGeometryTestSetup(new H2TestSetup()); + } + +} \ No newline at end of file Added: trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java (rev 0) +++ trunk/modules/plugin/jdbc/jdbc-h2/src/test/java/org/geotools/data/h2/H2EmptyGeometryTestSetup.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -0,0 +1,63 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.h2; + +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; +import org.geotools.jdbc.JDBCTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISBooleanTestSetup.java $ + */ +public class H2EmptyGeometryTestSetup extends JDBCEmptyGeometryTestSetup { + + public H2EmptyGeometryTestSetup(JDBCTestSetup delegate) { + super(delegate); + } + + @Override + protected void createEmptyGeometryTable() throws Exception { + //create table schema + run("CREATE TABLE \"geotools\".\"empty\"(" // + + "\"fid\" serial primary key, " // + + "\"id\" integer, " // + + "\"geom_point\" POINT, " // + + "\"geom_linestring\" LINESTRING, " // + + "\"geom_polygon\" POLYGON, " // + + "\"geom_multipoint\" MULTIPOINT, " // + + "\"geom_multilinestring\" MULTILINESTRING, " // + + "\"geom_multipolygon\" MULTIPOLYGON, " // + + "\"name\" varchar" // + + ")"); + + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_point', 4326, 'POINT', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_linestring', 4326, 'LINESTRING', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_polygon', 4326, 'POLYGON', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_multipoint', 4326, 'MULTIPOINT', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_multilinestring', 4326, 'MULTILINESTRING', 2)"); + run("CALL AddGeometryColumn('geotools', 'empty', 'geom_multipolygon', 4326, 'MULTIPOLYGON', 2)"); + } + + @Override + protected void dropEmptyGeometryTable() throws Exception { + run( "DROP TABLE \"geotools\".\"empty\""); + + } + + +} Modified: trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java 2012-05-12 16:10:08 UTC (rev 38717) +++ trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISDialect.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -736,7 +736,7 @@ @Override public void encodeGeometryValue(Geometry value, int srid, StringBuffer sql) throws IOException { - if(value == null) { + if (value == null || value.isEmpty()) { sql.append("NULL"); } else { if (value instanceof LinearRing) { Modified: trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java 2012-05-12 16:10:08 UTC (rev 38717) +++ trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostGISPSDialect.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -193,7 +193,7 @@ @Override public void setGeometryValue(Geometry g, int srid, Class binding, PreparedStatement ps, int column) throws SQLException { - if (g != null) { + if (g != null && !g.isEmpty()) { if (g instanceof LinearRing ) { //postgis does not handle linear rings, convert to just a line string g = g.getFactory().createLineString(((LinearRing) g).getCoordinateSequence()); Added: trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java (rev 0) +++ trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -0,0 +1,34 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.postgis; + +import org.geotools.jdbc.JDBCEmptyGeometryTest; +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java $ + */ +public class PostGISEmptyGeometryTest extends JDBCEmptyGeometryTest { + + @Override + protected JDBCEmptyGeometryTestSetup createTestSetup() { + return new PostGISEmptyGeometryTestSetup(new PostGISTestSetup()); + } + +} \ No newline at end of file Added: trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java (rev 0) +++ trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTestSetup.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -0,0 +1,63 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.postgis; + +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; +import org.geotools.jdbc.JDBCTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISBooleanTestSetup.java $ + */ +public class PostGISEmptyGeometryTestSetup extends JDBCEmptyGeometryTestSetup { + + public PostGISEmptyGeometryTestSetup(JDBCTestSetup delegate) { + super(delegate); + } + + @Override + protected void createEmptyGeometryTable() throws Exception { + //create table schema + run("CREATE TABLE \"empty\"(" // + + "\"fid\" serial primary key, " // + + "\"id\" integer, " // + + "\"geom_point\" geometry, " // + + "\"geom_linestring\" geometry, " // + + "\"geom_polygon\" geometry, " // + + "\"geom_multipoint\" geometry, " // + + "\"geom_multilinestring\" geometry, " // + + "\"geom_multipolygon\" geometry, " // + + "\"name\" varchar," // + + "CONSTRAINT enforce_geotype_geom_1 CHECK (geometrytype(geom_point) = 'POINT'::text OR geom_point IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_2 CHECK (geometrytype(geom_linestring) = 'LINESTRING'::text OR geom_linestring IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_3 CHECK (geometrytype(geom_polygon) = 'POLYGON'::text OR geom_polygon IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_4 CHECK (geometrytype(geom_multipoint) = 'MULTIPOINT'::text OR geom_multipoint IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_5 CHECK (geometrytype(geom_multilinestring) = 'MULTILINESTRING'::text OR geom_multilinestring IS NULL)," // + + "CONSTRAINT enforce_geotype_geom_6 CHECK (geometrytype(geom_multipolygon) = 'MULTIPOLYGON'::text OR geom_multipolygon IS NULL)" // + + ")"); + + } + + @Override + protected void dropEmptyGeometryTable() throws Exception { + run( "DROP TABLE \"empty\""); + + } + + +} Modified: trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java 2012-05-12 16:10:08 UTC (rev 38717) +++ trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISTestSetup.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -74,11 +74,12 @@ run("INSERT INTO \"ft1\" VALUES(0, GeometryFromText('POINT(0 0)', 4326), 0, 0.0, 'zero')"); run("INSERT INTO \"ft1\" VALUES(1, GeometryFromText('POINT(1 1)', 4326), 1, 1.1, 'one')"); run("INSERT INTO \"ft1\" VALUES(2, GeometryFromText('POINT(2 2)', 4326), 2, 2.2, 'two')"); - // advance the sequence to 2 + // advance the sequence to 2 run("SELECT nextval(pg_get_serial_sequence('ft1','id'))"); run("SELECT nextval(pg_get_serial_sequence('ft1','id'))"); // analyze so that the stats will be up to date run("ANALYZE \"ft1\""); + } Added: trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java (rev 0) +++ trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/ps/PostGISEmptyGeometryTest.java 2012-05-12 16:37:03 UTC (rev 38718) @@ -0,0 +1,35 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.data.postgis.ps; + +import org.geotools.data.postgis.PostGISEmptyGeometryTestSetup; +import org.geotools.jdbc.JDBCEmptyGeometryTest; +import org.geotools.jdbc.JDBCEmptyGeometryTestSetup; + +/** + * + * + * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-postgis/src/test/java/org/geotools/data/postgis/PostGISEmptyGeometryTest.java $ + */ +public class PostGISEmptyGeometryTest extends JDBCEmptyGeometryTest { + + @Override + protected JDBCEmptyGeometryTestSetup createTestSetup() { + return new PostGISEmptyGeometryTestSetup(new PostGISPSTestSetup()); + } + +} \ No newline at end of file |
From: <svn...@os...> - 2012-05-12 16:10:15
|
Author: aaime Date: 2012-05-12 09:10:08 -0700 (Sat, 12 May 2012) New Revision: 38717 Modified: trunk/modules/library/main/src/main/java/org/geotools/data/store/ReprojectingFeatureCollection.java trunk/modules/library/main/src/test/java/org/geotools/data/store/ReprojectingFeatureCollectionTest.java Log: [GEOT-4137] ReprojectingFeatureCollection.getBounds() not returning a ReferencedEnvelope with CRS, patch by Gerson Galang Modified: trunk/modules/library/main/src/main/java/org/geotools/data/store/ReprojectingFeatureCollection.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/data/store/ReprojectingFeatureCollection.java 2012-05-12 13:29:31 UTC (rev 38716) +++ trunk/modules/library/main/src/main/java/org/geotools/data/store/ReprojectingFeatureCollection.java 2012-05-12 16:10:08 UTC (rev 38717) @@ -241,7 +241,7 @@ newBBox.expandToInclude(internal); } } - return ReferencedEnvelope.reference(newBBox); + return new ReferencedEnvelope(newBBox, target); } catch (Exception e) { throw new RuntimeException( "Exception occurred while computing reprojected bounds", e); Modified: trunk/modules/library/main/src/test/java/org/geotools/data/store/ReprojectingFeatureCollectionTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/data/store/ReprojectingFeatureCollectionTest.java 2012-05-12 13:29:31 UTC (rev 38716) +++ trunk/modules/library/main/src/test/java/org/geotools/data/store/ReprojectingFeatureCollectionTest.java 2012-05-12 16:10:08 UTC (rev 38717) @@ -94,7 +94,9 @@ // the reprojection of the full bounds is going to be bigger than the sum of the // feature by feature reprojected bounds assertTrue(bounds.transform(target, true).contains((BoundingBox) rfc.getBounds())); - + + // make sure that the reprojected bounds contain the target CRS + assertEquals(target, rfc.getBounds().getCoordinateReferenceSystem()); } public void testFilter() throws Exception { |
From: <svn...@os...> - 2012-05-12 13:29:39
|
Author: jdeolive Date: 2012-05-12 06:29:31 -0700 (Sat, 12 May 2012) New Revision: 38716 Added: trunk/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java trunk/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java Modified: trunk/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java Log: GEOT-4125, adding support for mark/reset to TransformerBase to enable buffering writes, patch by David Winslow Modified: trunk/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java 2012-05-12 13:28:17 UTC (rev 38715) +++ trunk/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java 2012-05-12 13:29:31 UTC (rev 38716) @@ -18,8 +18,10 @@ import java.io.StringWriter; import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -435,7 +437,155 @@ protected final Attributes NULL_ATTS = new AttributesImpl(); protected NamespaceSupport nsSupport = new NamespaceSupport(); protected SchemaLocationSupport schemaLocation; + /** + * The queue of write operations pending for this translator. + * This should be empty if no mark is set. + */ + private List<Action> pending = new ArrayList<Action>(); + + /** + * An Action records a call to one of the SAX-event-generating methods + * on this translator. + */ + private interface Action { + void commit(); + } + + /** + * The Start class implements an Action corresponding to starting an + * XML element + */ + private class Start implements Action { + private final String element; + private final Attributes attributes; + + public Start(String element, Attributes attributes) { + this.element = element; + this.attributes = new AttributesImpl(attributes); + } + + public void commit() { + _start(element, attributes); + } + } + + /** + * The Chars class implements an Action corresponding to writing a text + * block in the XML output + */ + private class Chars implements Action { + private final String text; + + public Chars(String text) { + this.text = text; + } + + public void commit() { + _chars(text); + } + } + + /** + * The CData class implements an Action corresponding to writing a + * CDATA block in the XML output + */ + private class CData implements Action { + private final String text; + + public CData(String text) { + this.text = text; + } + + public void commit() { + _cdata(text); + } + } + + /** + * The End class implements an Action corresponding to closing an XML + * element + */ + private class End implements Action { + private final String element; + + public End(String element) { + this.element = element; + } + + public void commit() { + _end(element); + } + } + + /** + * The Backend class encapsulates a strategy for writing back to the underlying stream. + */ + private interface Backend { + public void start(String element, Attributes attributes); + public void chars(String text); + public void cdata(String text); + public void end(String element); + } + + /** + * The BufferedBackend queues up write operations in memory, to be committed at a later time. + */ + private class BufferedBackend implements Backend { + public void start(String element, Attributes attributes) { + pending.add(new Start(element, attributes)); + } + + public void chars(String text) { + pending.add(new Chars(text)); + } + + public void cdata(String text) { + pending.add(new CData(text)); + } + + public void end(String element) { + pending.add(new End(element)); + } + } + + /** + * The DirectBackend writes immediately to the underlying output stream. + */ + private class DirectBackend implements Backend { + public void start(String element, Attributes attributes) { + _start(element, attributes); + } + + public void chars(String text) { + _chars(text); + } + + public void cdata(String text) { + _cdata(text); + } + + public void end(String element) { + _end(element); + } + } + + /** + * A singleton instance of the DirectBackend for this TranslatorSupport instance + */ + private final Backend directBackend = new DirectBackend(); + + /** + * A singleton instance of the BufferedBackend for this TranslatorSupport instance + */ + private final Backend bufferedBackend = new BufferedBackend(); + + /** + * The backend currently in use. This should only be modified in the mark/reset/commit methods! + */ + private Backend backend = directBackend; + + /** * Subclasses should check this flag in case an abort message was sent * and stop any internal iteration if false. */ @@ -455,12 +605,70 @@ this(contentHandler, prefix, nsURI); this.schemaLocation = schemaLocation; } - + public void abort() { running = false; } - + /** + * Set a mark() to which we can later "roll back" writes. After a call + * to mark(), the Translator stores pending write operations in memory + * until commit() is called. The pending writes can be discarded with + * the reset() method. + * + * Typically, one would use marks in conjunction with an exception handler: + * + * <pre> + * void encodeFoo(Foo f) { + * try { + * mark(); + * element(foo.riskyMethod()); + * element(foo.dangerousMethod()); + * commit(); + * } catch (BadThingHappened disaster) { + * mitigate(disaster); + * reset(); + * } + * } + * </pre> + * + * @throws IllegalStateException if a mark is already set + */ + protected void mark() { + if (backend == bufferedBackend) throw new IllegalStateException("Mark already set"); + backend = bufferedBackend; + } + + /** + * Discard pending write operations after a mark() has been set. + * + * This method is safe to call even if no mark is set - so it returns + * to a "known good" state as far as marks are concerned. + * + * @see #mark() + */ + protected void reset() { + pending.clear(); + backend = directBackend; + } + + /** + * Commit pending write operations. After setting a mark, this method + * will commit the pending writes. + * + * @see #mark() + * @throws IllegalStateException if no mark is set + */ + protected void commit() { + if (backend != bufferedBackend) throw new IllegalStateException("Can't commit without a mark"); + for (Action a : pending) { + a.commit(); + } + pending.clear(); + backend = directBackend; + } + + /** * Utility method to copy namespace declarations from "sub" translators * into this ns support... */ @@ -499,7 +707,7 @@ protected void element(String element, String content) { element(element, content, NULL_ATTS); } - + /** * Will only issue the provided element if content is non empty * @param element @@ -526,9 +734,12 @@ } protected void start(String element, Attributes atts) { + backend.start(element, atts); + } + + private void _start(String element, Attributes atts) { try { - String el = (prefix == null) ? element : (prefix + ":" - + element); + String el = (prefix == null) ? element : (prefix + ":" + element); contentHandler.startElement("", "", el, atts); } catch (SAXException se) { throw new RuntimeException(se); @@ -536,6 +747,10 @@ } protected void chars(String text) { + backend.chars(text); + } + + private void _chars(String text) { try { char[] ch = text.toCharArray(); contentHandler.characters(ch, 0, ch.length); @@ -545,6 +760,10 @@ } protected void end(String element) { + backend.end(element); + } + + private void _end(String element) { try { String el = (prefix == null) ? element : (prefix + ":" + element); @@ -554,13 +773,18 @@ } } - protected void cdata( String cdata ) { - if ( contentHandler instanceof LexicalHandler ) { + protected void cdata(String cdata) { + backend.cdata(cdata); + } + + private void _cdata(String cdata) { + if (contentHandler instanceof LexicalHandler) { LexicalHandler lexicalHandler = (LexicalHandler) contentHandler; try { lexicalHandler.startCDATA(); - chars(cdata); - lexicalHandler.endCDATA(); + char[] carray = cdata.toCharArray(); + contentHandler.characters(carray, 0, carray.length); + lexicalHandler.endCDATA(); } catch( SAXException e ) { throw new RuntimeException( e ); Added: trunk/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java (rev 0) +++ trunk/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java 2012-05-12 13:29:31 UTC (rev 38716) @@ -0,0 +1,67 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.xml; + +import org.geotools.xml.transform.TransformerBase; +import org.geotools.xml.transform.Translator; +import org.xml.sax.ContentHandler; + +public class ExampleTransformer extends TransformerBase { + private final int bufferEveryNth; + private final int exceptionEveryNth; + private final boolean ignoreErrors; + + public ExampleTransformer(int bufferEveryNth, int exceptionEveryNth, boolean ignoreErrors) { + this.bufferEveryNth = bufferEveryNth; + this.exceptionEveryNth = exceptionEveryNth; + this.ignoreErrors = ignoreErrors; + } + + public Translator createTranslator(ContentHandler handler) { + return new ExampleTranslator(handler); + } + + private class ExampleTranslator extends TranslatorSupport { + public ExampleTranslator(ContentHandler handler) { + super(handler, "test", "http://geotools.org/test"); + } + + public void encode(Object o) { + Integer i = (Integer)o; + start("integers"); + for (int j = 1; j <= i; j++) { + boolean buffer = + ((bufferEveryNth != 0) && (j % bufferEveryNth == 0)); + boolean exception = + ((exceptionEveryNth != 0) && (j % exceptionEveryNth == 0)); + + try { + if (buffer) mark(); + element("integer", String.valueOf(j)); + if (exception) throw new RuntimeException(); + if (buffer) commit(); + } catch (RuntimeException e) { + if (!ignoreErrors) throw e; + } finally { + reset(); + } + } + + end("integers"); + } + } +} Added: trunk/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java (rev 0) +++ trunk/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java 2012-05-12 13:29:31 UTC (rev 38716) @@ -0,0 +1,85 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.xml; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.StringWriter; +import javax.xml.transform.TransformerException; + +import junit.framework.TestCase; + +public class TransformerBaseTest extends TestCase { + + public void testUnbufferedUsageNoErrors() throws FileNotFoundException, TransformerException { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer><test:integer>10</test:integer></test:integers>"; + ExampleTransformer tx = new ExampleTransformer(0, 0, false); + String actual = tx.transform(10); + assertEquals(expected, actual); + } + + public void testUnbufferedUsageOneError() throws FileNotFoundException, TransformerException { + StringWriter w = new StringWriter(); + try { + ExampleTransformer tx = new ExampleTransformer(0, 10, false); + tx.transform(10, w); + fail("Should have thrown an exception before reaching this point"); + } catch (TransformerException e) { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer><test:integer>10</test:integer>"; + String actual = w.toString(); + assertEquals(expected, actual); + } + } + + public void testBufferedUsageNoErrors() throws FileNotFoundException, TransformerException { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer><test:integer>10</test:integer></test:integers>"; + ExampleTransformer tx = new ExampleTransformer(1, 0, false); + String actual = tx.transform(10); + assertEquals(expected, actual); + } + + public void testBufferedUsageOneError() throws FileNotFoundException, TransformerException { + StringWriter w = new StringWriter(); + try { + ExampleTransformer tx = new ExampleTransformer(1, 10, false); + tx.transform(10, w); + fail("Should have thrown an exception before reaching this point!"); + } catch (TransformerException e) { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer>"; + String actual = w.toString(); + assertEquals(expected, actual); + } + } + + public void testBufferedUsageIgnoringOneError() throws FileNotFoundException, TransformerException { + ExampleTransformer tx = new ExampleTransformer(1, 10, true); + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer></test:integers>"; + String actual = tx.transform(10); + assertEquals(expected, actual); + } + + public void testBufferedUsageIgnoringMultipleErrors() throws FileNotFoundException, TransformerException { + ExampleTransformer tx = new ExampleTransformer(1, 2, true); + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>3</test:integer><test:integer>5</test:integer><test:integer>7</test:integer><test:integer>9</test:integer></test:integers>"; + String actual = tx.transform(10); + assertEquals(expected, actual); + } +} |
From: <svn...@os...> - 2012-05-12 13:28:25
|
Author: jdeolive Date: 2012-05-12 06:28:17 -0700 (Sat, 12 May 2012) New Revision: 38715 Added: branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java Modified: branches/2.7.x/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java Log: GEOT-4125, adding support for mark/reset to TransformerBase to enable buffering writes, patch by David Winslow Modified: branches/2.7.x/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java =================================================================== --- branches/2.7.x/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java 2012-05-11 23:03:22 UTC (rev 38714) +++ branches/2.7.x/modules/library/main/src/main/java/org/geotools/xml/transform/TransformerBase.java 2012-05-12 13:28:17 UTC (rev 38715) @@ -18,8 +18,10 @@ import java.io.StringWriter; import java.nio.charset.Charset; +import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -434,7 +436,155 @@ protected final Attributes NULL_ATTS = new AttributesImpl(); protected NamespaceSupport nsSupport = new NamespaceSupport(); protected SchemaLocationSupport schemaLocation; + /** + * The queue of write operations pending for this translator. + * This should be empty if no mark is set. + */ + private List<Action> pending = new ArrayList<Action>(); + + /** + * An Action records a call to one of the SAX-event-generating methods + * on this translator. + */ + private interface Action { + void commit(); + } + + /** + * The Start class implements an Action corresponding to starting an + * XML element + */ + private class Start implements Action { + private final String element; + private final Attributes attributes; + + public Start(String element, Attributes attributes) { + this.element = element; + this.attributes = new AttributesImpl(attributes); + } + + public void commit() { + _start(element, attributes); + } + } + + /** + * The Chars class implements an Action corresponding to writing a text + * block in the XML output + */ + private class Chars implements Action { + private final String text; + + public Chars(String text) { + this.text = text; + } + + public void commit() { + _chars(text); + } + } + + /** + * The CData class implements an Action corresponding to writing a + * CDATA block in the XML output + */ + private class CData implements Action { + private final String text; + + public CData(String text) { + this.text = text; + } + + public void commit() { + _cdata(text); + } + } + + /** + * The End class implements an Action corresponding to closing an XML + * element + */ + private class End implements Action { + private final String element; + + public End(String element) { + this.element = element; + } + + public void commit() { + _end(element); + } + } + + /** + * The Backend class encapsulates a strategy for writing back to the underlying stream. + */ + private interface Backend { + public void start(String element, Attributes attributes); + public void chars(String text); + public void cdata(String text); + public void end(String element); + } + + /** + * The BufferedBackend queues up write operations in memory, to be committed at a later time. + */ + private class BufferedBackend implements Backend { + public void start(String element, Attributes attributes) { + pending.add(new Start(element, attributes)); + } + + public void chars(String text) { + pending.add(new Chars(text)); + } + + public void cdata(String text) { + pending.add(new CData(text)); + } + + public void end(String element) { + pending.add(new End(element)); + } + } + + /** + * The DirectBackend writes immediately to the underlying output stream. + */ + private class DirectBackend implements Backend { + public void start(String element, Attributes attributes) { + _start(element, attributes); + } + + public void chars(String text) { + _chars(text); + } + + public void cdata(String text) { + _cdata(text); + } + + public void end(String element) { + _end(element); + } + } + + /** + * A singleton instance of the DirectBackend for this TranslatorSupport instance + */ + private final Backend directBackend = new DirectBackend(); + + /** + * A singleton instance of the BufferedBackend for this TranslatorSupport instance + */ + private final Backend bufferedBackend = new BufferedBackend(); + + /** + * The backend currently in use. This should only be modified in the mark/reset/commit methods! + */ + private Backend backend = directBackend; + + /** * Subclasses should check this flag in case an abort message was sent * and stop any internal iteration if false. */ @@ -454,12 +604,70 @@ this(contentHandler, prefix, nsURI); this.schemaLocation = schemaLocation; } - + public void abort() { running = false; } - + /** + * Set a mark() to which we can later "roll back" writes. After a call + * to mark(), the Translator stores pending write operations in memory + * until commit() is called. The pending writes can be discarded with + * the reset() method. + * + * Typically, one would use marks in conjunction with an exception handler: + * + * <pre> + * void encodeFoo(Foo f) { + * try { + * mark(); + * element(foo.riskyMethod()); + * element(foo.dangerousMethod()); + * commit(); + * } catch (BadThingHappened disaster) { + * mitigate(disaster); + * reset(); + * } + * } + * </pre> + * + * @throws IllegalStateException if a mark is already set + */ + protected void mark() { + if (backend == bufferedBackend) throw new IllegalStateException("Mark already set"); + backend = bufferedBackend; + } + + /** + * Discard pending write operations after a mark() has been set. + * + * This method is safe to call even if no mark is set - so it returns + * to a "known good" state as far as marks are concerned. + * + * @see #mark() + */ + protected void reset() { + pending.clear(); + backend = directBackend; + } + + /** + * Commit pending write operations. After setting a mark, this method + * will commit the pending writes. + * + * @see #mark() + * @throws IllegalStateException if no mark is set + */ + protected void commit() { + if (backend != bufferedBackend) throw new IllegalStateException("Can't commit without a mark"); + for (Action a : pending) { + a.commit(); + } + pending.clear(); + backend = directBackend; + } + + /** * Utility method to copy namespace declarations from "sub" translators * into this ns support... */ @@ -498,7 +706,7 @@ protected void element(String element, String content) { element(element, content, NULL_ATTS); } - + /** * Will only issue the provided element if content is non empty * @param element @@ -525,9 +733,12 @@ } protected void start(String element, Attributes atts) { + backend.start(element, atts); + } + + private void _start(String element, Attributes atts) { try { - String el = (prefix == null) ? element : (prefix + ":" - + element); + String el = (prefix == null) ? element : (prefix + ":" + element); contentHandler.startElement("", "", el, atts); } catch (SAXException se) { throw new RuntimeException(se); @@ -535,6 +746,10 @@ } protected void chars(String text) { + backend.chars(text); + } + + private void _chars(String text) { try { char[] ch = text.toCharArray(); contentHandler.characters(ch, 0, ch.length); @@ -544,6 +759,10 @@ } protected void end(String element) { + backend.end(element); + } + + private void _end(String element) { try { String el = (prefix == null) ? element : (prefix + ":" + element); @@ -553,13 +772,18 @@ } } - protected void cdata( String cdata ) { - if ( contentHandler instanceof LexicalHandler ) { + protected void cdata(String cdata) { + backend.cdata(cdata); + } + + private void _cdata(String cdata) { + if (contentHandler instanceof LexicalHandler) { LexicalHandler lexicalHandler = (LexicalHandler) contentHandler; try { lexicalHandler.startCDATA(); - chars(cdata); - lexicalHandler.endCDATA(); + char[] carray = cdata.toCharArray(); + contentHandler.characters(carray, 0, carray.length); + lexicalHandler.endCDATA(); } catch( SAXException e ) { throw new RuntimeException( e ); Added: branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java =================================================================== --- branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java (rev 0) +++ branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/ExampleTransformer.java 2012-05-12 13:28:17 UTC (rev 38715) @@ -0,0 +1,67 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.xml; + +import org.geotools.xml.transform.TransformerBase; +import org.geotools.xml.transform.Translator; +import org.xml.sax.ContentHandler; + +public class ExampleTransformer extends TransformerBase { + private final int bufferEveryNth; + private final int exceptionEveryNth; + private final boolean ignoreErrors; + + public ExampleTransformer(int bufferEveryNth, int exceptionEveryNth, boolean ignoreErrors) { + this.bufferEveryNth = bufferEveryNth; + this.exceptionEveryNth = exceptionEveryNth; + this.ignoreErrors = ignoreErrors; + } + + public Translator createTranslator(ContentHandler handler) { + return new ExampleTranslator(handler); + } + + private class ExampleTranslator extends TranslatorSupport { + public ExampleTranslator(ContentHandler handler) { + super(handler, "test", "http://geotools.org/test"); + } + + public void encode(Object o) { + Integer i = (Integer)o; + start("integers"); + for (int j = 1; j <= i; j++) { + boolean buffer = + ((bufferEveryNth != 0) && (j % bufferEveryNth == 0)); + boolean exception = + ((exceptionEveryNth != 0) && (j % exceptionEveryNth == 0)); + + try { + if (buffer) mark(); + element("integer", String.valueOf(j)); + if (exception) throw new RuntimeException(); + if (buffer) commit(); + } catch (RuntimeException e) { + if (!ignoreErrors) throw e; + } finally { + reset(); + } + } + + end("integers"); + } + } +} Added: branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java =================================================================== --- branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java (rev 0) +++ branches/2.7.x/modules/library/main/src/test/java/org/geotools/xml/TransformerBaseTest.java 2012-05-12 13:28:17 UTC (rev 38715) @@ -0,0 +1,85 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.xml; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.io.StringWriter; +import javax.xml.transform.TransformerException; + +import junit.framework.TestCase; + +public class TransformerBaseTest extends TestCase { + + public void testUnbufferedUsageNoErrors() throws FileNotFoundException, TransformerException { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer><test:integer>10</test:integer></test:integers>"; + ExampleTransformer tx = new ExampleTransformer(0, 0, false); + String actual = tx.transform(10); + assertEquals(expected, actual); + } + + public void testUnbufferedUsageOneError() throws FileNotFoundException, TransformerException { + StringWriter w = new StringWriter(); + try { + ExampleTransformer tx = new ExampleTransformer(0, 10, false); + tx.transform(10, w); + fail("Should have thrown an exception before reaching this point"); + } catch (TransformerException e) { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer><test:integer>10</test:integer>"; + String actual = w.toString(); + assertEquals(expected, actual); + } + } + + public void testBufferedUsageNoErrors() throws FileNotFoundException, TransformerException { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer><test:integer>10</test:integer></test:integers>"; + ExampleTransformer tx = new ExampleTransformer(1, 0, false); + String actual = tx.transform(10); + assertEquals(expected, actual); + } + + public void testBufferedUsageOneError() throws FileNotFoundException, TransformerException { + StringWriter w = new StringWriter(); + try { + ExampleTransformer tx = new ExampleTransformer(1, 10, false); + tx.transform(10, w); + fail("Should have thrown an exception before reaching this point!"); + } catch (TransformerException e) { + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer>"; + String actual = w.toString(); + assertEquals(expected, actual); + } + } + + public void testBufferedUsageIgnoringOneError() throws FileNotFoundException, TransformerException { + ExampleTransformer tx = new ExampleTransformer(1, 10, true); + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>2</test:integer><test:integer>3</test:integer><test:integer>4</test:integer><test:integer>5</test:integer><test:integer>6</test:integer><test:integer>7</test:integer><test:integer>8</test:integer><test:integer>9</test:integer></test:integers>"; + String actual = tx.transform(10); + assertEquals(expected, actual); + } + + public void testBufferedUsageIgnoringMultipleErrors() throws FileNotFoundException, TransformerException { + ExampleTransformer tx = new ExampleTransformer(1, 2, true); + String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test:integers xmlns=\"http://geotools.org/test\" xmlns:test=\"http://geotools.org/test\"><test:integer>1</test:integer><test:integer>3</test:integer><test:integer>5</test:integer><test:integer>7</test:integer><test:integer>9</test:integer></test:integers>"; + String actual = tx.transform(10); + assertEquals(expected, actual); + } +} |
From: <svn...@os...> - 2012-05-11 23:03:32
|
Author: groldan Date: 2012-05-11 16:03:22 -0700 (Fri, 11 May 2012) New Revision: 38714 Modified: trunk/modules/library/opengis/src/main/java/org/opengis/filter/identity/Version.java trunk/modules/library/opengis/src/test/java/org/opengis/filter/identity/VersionTest.java Log: GEOT-4141: disallow creating an org.opengis.filter.identity.Version with a non positive index argument Modified: trunk/modules/library/opengis/src/main/java/org/opengis/filter/identity/Version.java =================================================================== --- trunk/modules/library/opengis/src/main/java/org/opengis/filter/identity/Version.java 2012-05-11 10:22:30 UTC (rev 38713) +++ trunk/modules/library/opengis/src/main/java/org/opengis/filter/identity/Version.java 2012-05-11 23:03:22 UTC (rev 38714) @@ -77,10 +77,18 @@ this.union = UNION_ACTION | action.ordinal(); } + /** + * @param index a positive integer > 0, representing the 1 based index of the requested feature + * in its version history. + */ public Version(final Integer index) { if (index == null) { throw new IllegalArgumentException("index can't be null"); } + if (0 >= index.intValue()) { + throw new IllegalArgumentException("Invalid version index: " + index + + ". Must be a positive integer > 0."); + } this.union = UNION_INTEGER | (long) index; } Modified: trunk/modules/library/opengis/src/test/java/org/opengis/filter/identity/VersionTest.java =================================================================== --- trunk/modules/library/opengis/src/test/java/org/opengis/filter/identity/VersionTest.java 2012-05-11 10:22:30 UTC (rev 38713) +++ trunk/modules/library/opengis/src/test/java/org/opengis/filter/identity/VersionTest.java 2012-05-11 23:03:22 UTC (rev 38714) @@ -5,6 +5,7 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.util.Date; @@ -29,6 +30,19 @@ @Test public void versionInteger() { + try { + new Version(-1); + fail("Expected IAE on negative version"); + } catch (IllegalArgumentException e) { + assertTrue(true); + } + try { + new Version(0); + fail("Expected IAE"); + } catch (IllegalArgumentException e) { + assertTrue(true); + } + Integer testInt = new Integer(1234567890); Version version = new Version(testInt); |
Author: aaime Date: 2012-05-11 03:22:30 -0700 (Fri, 11 May 2012) New Revision: 38713 Added: trunk/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld Modified: trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java Log: [GEOT-4139] MetaBufferEstimator won't evaluate graphics size if the size is a NilExpression Modified: trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java =================================================================== --- trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java 2012-05-11 10:18:53 UTC (rev 38712) +++ trunk/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java 2012-05-11 10:22:30 UTC (rev 38713) @@ -58,10 +58,12 @@ import org.geotools.styling.StyledLayerDescriptor; import org.geotools.styling.Symbolizer; import org.geotools.styling.TextSymbolizer; +import org.geotools.styling.TextSymbolizer2; import org.geotools.styling.UserLayer; import org.opengis.filter.Filter; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Literal; +import org.opengis.filter.expression.NilExpression; import org.opengis.style.GraphicalSymbol; /** @@ -163,15 +165,22 @@ public void visit(Stroke stroke) { try { Expression width = stroke.getWidth(); - if (width != null) { + if (!isNull(width)) { evaluateWidth(width); } + if(stroke.getGraphicStroke() != null) { + stroke.getGraphicStroke().accept(this); + } } catch (ClassCastException e) { estimateAccurate = false; LOGGER.info("Could not parse stroke width, " + "it's a literal but not a Number..."); } } + + protected boolean isNull(Expression exp) { + return exp == null || exp instanceof NilExpression; + } /** * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Symbolizer) @@ -249,7 +258,13 @@ * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.TextSymbolizer) */ public void visit(TextSymbolizer text) { - // nothing to do here + // take into account label shields if any + if(text instanceof TextSymbolizer2) { + Graphic graphic = ((TextSymbolizer2) text).getGraphic(); + if(graphic != null) { + graphic.accept(this); + } + } } /** @@ -258,7 +273,7 @@ public void visit(Graphic gr) { try { Expression grSize = gr.getSize(); - if (grSize != null) { + if (!isNull(grSize)) { evaluateWidth(grSize); } else { for (GraphicalSymbol gs : gr.graphicalSymbols()) { Added: trunk/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java =================================================================== --- trunk/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java (rev 0) +++ trunk/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java 2012-05-11 10:22:30 UTC (rev 38713) @@ -0,0 +1,82 @@ +package org.geotools.renderer.lite; + +import static org.junit.Assert.*; + +import org.geotools.styling.Style; +import org.junit.Test; + +public class MetaBufferEstimatorTest { + + @Test + public void testExternalGraphic() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "externalGraphic.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(48, estimator.getBuffer()); + } + + @Test + public void testExternalGraphicNoSize() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "externalGraphicNoSize.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(64, estimator.getBuffer()); + } + + @Test + public void testMark() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "markCircle.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(32, estimator.getBuffer()); + } + + @Test + public void testThinLine() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "lineGray.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(1, estimator.getBuffer()); + } + + @Test + public void testThickLine() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "lineThick.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(4, estimator.getBuffer()); + } + + @Test + public void testGraphicStroke() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "lineRailway.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(8, estimator.getBuffer()); + } + + @Test + public void testPolygon() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "polygon.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(1, estimator.getBuffer()); + } + + @Test + public void testLabelShields() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "textLabelShield.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(32, estimator.getBuffer()); + } + +} Added: trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld =================================================================== --- trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld (rev 0) +++ trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld 2012-05-11 10:22:30 UTC (rev 38713) @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" + xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"> + <NamedLayer> + + <Name>Icon</Name> + <UserStyle> + <FeatureTypeStyle> + <Rule> + <PointSymbolizer> + <Graphic> + <ExternalGraphic> + <OnlineResource xlink:type="simple" xlink:href="icon64.png" /> + <Format>image/png</Format> + </ExternalGraphic> + </Graphic> + </PointSymbolizer> + + </Rule> + </FeatureTypeStyle> + </UserStyle> + </NamedLayer> +</StyledLayerDescriptor> \ No newline at end of file Added: trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld =================================================================== --- trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld (rev 0) +++ trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld 2012-05-11 10:22:30 UTC (rev 38713) @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" + xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"> + <NamedLayer> + + <Name>GrayLines</Name> + <UserStyle> + <FeatureTypeStyle> + <Rule> + <LineSymbolizer> + <Stroke> + <CssParameter name="stroke">0x440000</CssParameter> + <CssParameter name="stroke-width">4</CssParameter> + </Stroke> + </LineSymbolizer> + </Rule> + </FeatureTypeStyle> + </UserStyle> + </NamedLayer> +</StyledLayerDescriptor> \ No newline at end of file Added: trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld =================================================================== --- trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld (rev 0) +++ trunk/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld 2012-05-11 10:22:30 UTC (rev 38713) @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<StyledLayerDescriptor version="1.0.0" + xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" + xmlns="http://www.opengis.net/sld" + xmlns:ogc="http://www.opengis.net/ogc" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <!-- a named layer is the basic building block of an sld document --> + + <NamedLayer> + <UserStyle> + <FeatureTypeStyle> + <Rule> + <PolygonSymbolizer> + <Fill> + <CssParameter name="fill">#AAAAAA</CssParameter> + </Fill> + <Stroke/> + </PolygonSymbolizer> + </Rule> + + </FeatureTypeStyle> + </UserStyle> + </NamedLayer> +</StyledLayerDescriptor> + |
Author: aaime Date: 2012-05-11 03:18:53 -0700 (Fri, 11 May 2012) New Revision: 38712 Added: branches/2.7.x/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld Modified: branches/2.7.x/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java Log: [GEOT-4139] MetaBufferEstimator won't evaluate graphics size if the size is a NilExpression Modified: branches/2.7.x/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java =================================================================== --- branches/2.7.x/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java 2012-05-11 09:05:43 UTC (rev 38711) +++ branches/2.7.x/modules/library/render/src/main/java/org/geotools/renderer/lite/MetaBufferEstimator.java 2012-05-11 10:18:53 UTC (rev 38712) @@ -58,10 +58,12 @@ import org.geotools.styling.StyledLayerDescriptor; import org.geotools.styling.Symbolizer; import org.geotools.styling.TextSymbolizer; +import org.geotools.styling.TextSymbolizer2; import org.geotools.styling.UserLayer; import org.opengis.filter.Filter; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.Literal; +import org.opengis.filter.expression.NilExpression; import org.opengis.style.GraphicalSymbol; /** @@ -162,15 +164,22 @@ public void visit(Stroke stroke) { try { Expression width = stroke.getWidth(); - if (width != null) { + if (!isNull(width)) { evaluateWidth(width); } + if(stroke.getGraphicStroke() != null) { + stroke.getGraphicStroke().accept(this); + } } catch (ClassCastException e) { estimateAccurate = false; LOGGER.info("Could not parse stroke width, " + "it's a literal but not a Number..."); } } + + protected boolean isNull(Expression exp) { + return exp == null || exp instanceof NilExpression; + } /** * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.Symbolizer) @@ -248,7 +257,13 @@ * @see org.geotools.styling.StyleVisitor#visit(org.geotools.styling.TextSymbolizer) */ public void visit(TextSymbolizer text) { - // nothing to do here + // take into account label shields if any + if(text instanceof TextSymbolizer2) { + Graphic graphic = ((TextSymbolizer2) text).getGraphic(); + if(graphic != null) { + graphic.accept(this); + } + } } /** @@ -257,7 +272,7 @@ public void visit(Graphic gr) { try { Expression grSize = gr.getSize(); - if (grSize != null) { + if (!isNull(grSize)) { evaluateWidth(grSize); } else { for (GraphicalSymbol gs : gr.graphicalSymbols()) { Added: branches/2.7.x/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java =================================================================== --- branches/2.7.x/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java (rev 0) +++ branches/2.7.x/modules/library/render/src/test/java/org/geotools/renderer/lite/MetaBufferEstimatorTest.java 2012-05-11 10:18:53 UTC (rev 38712) @@ -0,0 +1,82 @@ +package org.geotools.renderer.lite; + +import static org.junit.Assert.*; + +import org.geotools.styling.Style; +import org.junit.Test; + +public class MetaBufferEstimatorTest { + + @Test + public void testExternalGraphic() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "externalGraphic.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(48, estimator.getBuffer()); + } + + @Test + public void testExternalGraphicNoSize() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "externalGraphicNoSize.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(64, estimator.getBuffer()); + } + + @Test + public void testMark() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "markCircle.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(32, estimator.getBuffer()); + } + + @Test + public void testThinLine() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "lineGray.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(1, estimator.getBuffer()); + } + + @Test + public void testThickLine() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "lineThick.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(4, estimator.getBuffer()); + } + + @Test + public void testGraphicStroke() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "lineRailway.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(8, estimator.getBuffer()); + } + + @Test + public void testPolygon() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "polygon.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(1, estimator.getBuffer()); + } + + @Test + public void testLabelShields() throws Exception { + Style style = RendererBaseTest.loadStyle(this, "textLabelShield.sld"); + MetaBufferEstimator estimator = new MetaBufferEstimator(); + style.accept(estimator); + assertTrue(estimator.isEstimateAccurate()); + assertEquals(32, estimator.getBuffer()); + } + +} Added: branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld =================================================================== --- branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld (rev 0) +++ branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/externalGraphicNoSize.sld 2012-05-11 10:18:53 UTC (rev 38712) @@ -0,0 +1,24 @@ +<?xml version="1.0" encoding="UTF-8"?> +<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" + xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"> + <NamedLayer> + + <Name>Icon</Name> + <UserStyle> + <FeatureTypeStyle> + <Rule> + <PointSymbolizer> + <Graphic> + <ExternalGraphic> + <OnlineResource xlink:type="simple" xlink:href="icon64.png" /> + <Format>image/png</Format> + </ExternalGraphic> + </Graphic> + </PointSymbolizer> + + </Rule> + </FeatureTypeStyle> + </UserStyle> + </NamedLayer> +</StyledLayerDescriptor> \ No newline at end of file Added: branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld =================================================================== --- branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld (rev 0) +++ branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/lineThick.sld 2012-05-11 10:18:53 UTC (rev 38712) @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" + xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"> + <NamedLayer> + + <Name>GrayLines</Name> + <UserStyle> + <FeatureTypeStyle> + <Rule> + <LineSymbolizer> + <Stroke> + <CssParameter name="stroke">0x440000</CssParameter> + <CssParameter name="stroke-width">4</CssParameter> + </Stroke> + </LineSymbolizer> + </Rule> + </FeatureTypeStyle> + </UserStyle> + </NamedLayer> +</StyledLayerDescriptor> \ No newline at end of file Added: branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld =================================================================== --- branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld (rev 0) +++ branches/2.7.x/modules/library/render/src/test/resources/org/geotools/renderer/lite/test-data/polygon.sld 2012-05-11 10:18:53 UTC (rev 38712) @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> +<StyledLayerDescriptor version="1.0.0" + xsi:schemaLocation="http://www.opengis.net/sld StyledLayerDescriptor.xsd" + xmlns="http://www.opengis.net/sld" + xmlns:ogc="http://www.opengis.net/ogc" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> + <!-- a named layer is the basic building block of an sld document --> + + <NamedLayer> + <UserStyle> + <FeatureTypeStyle> + <Rule> + <PolygonSymbolizer> + <Fill> + <CssParameter name="fill">#AAAAAA</CssParameter> + </Fill> + <Stroke/> + </PolygonSymbolizer> + </Rule> + + </FeatureTypeStyle> + </UserStyle> + </NamedLayer> +</StyledLayerDescriptor> + |
Author: jive Date: 2012-05-11 02:05:43 -0700 (Fri, 11 May 2012) New Revision: 38711 Modified: trunk/modules/library/main/src/main/java/org/geotools/feature/visitor/StandardDeviationVisitor.java trunk/modules/library/main/src/main/java/org/geotools/filter/function/RangedClassifier.java trunk/modules/library/main/src/main/java/org/geotools/filter/function/StandardDeviationFunction.java trunk/modules/library/main/src/test/java/org/geotools/filter/function/StandardDeviationFunctionTest.java Log: Restore StandardDeviationFunctionTest and improve RangedClassifier null safety, GEOT-4138 Modified: trunk/modules/library/main/src/main/java/org/geotools/feature/visitor/StandardDeviationVisitor.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/feature/visitor/StandardDeviationVisitor.java 2012-05-11 07:58:42 UTC (rev 38710) +++ trunk/modules/library/main/src/main/java/org/geotools/feature/visitor/StandardDeviationVisitor.java 2012-05-11 09:05:43 UTC (rev 38711) @@ -124,6 +124,10 @@ this.mean = 0; } + /** mean value generated when calcualting standard deviation */ + public double getMean() { + return mean; + } /** * @return the number of features which returned a NaN */ Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/RangedClassifier.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/RangedClassifier.java 2012-05-11 07:58:42 UTC (rev 38710) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/RangedClassifier.java 2012-05-11 09:05:43 UTC (rev 38711) @@ -43,8 +43,8 @@ */ public final class RangedClassifier extends Classifier { - Comparable min[]; - Comparable max[]; + Comparable<?> min[]; + Comparable<?> max[]; public RangedClassifier(Comparable min[], Comparable max[]) { this.min = min; @@ -52,10 +52,35 @@ //initialize titles this.titles = new String[min.length]; for (int i = 0; i < titles.length; i++) { - titles[i] = truncateZeros(min[i].toString()) + ".." + truncateZeros(max[i].toString()); + titles[i] = generateTitle( min[i], max[i] ); } } - + /** + * Null safe title generation. + * + * @param min + * @param max + * @return generated title + */ + private String generateTitle(Comparable<?> min, Comparable<?> max) { + if( min == null && max == null){ + return "Other"; + } + else if ( min == null ){ + return "Below "+truncateZeros( String.valueOf( max )); + } + else if ( max == null ){ + return "Above "+truncateZeros( String.valueOf( min )); + } + else { + return truncateZeros(String.valueOf(min)) + ".." + truncateZeros(String.valueOf(max)); + } + } + /** + * Used to remove trailing zeros; preventing out put like 1.00000. + * @param str + * @return origional string with any trailing decimal places removed. + */ private String truncateZeros(String str) { if (str.indexOf(".") > -1) { while(str.endsWith("0")) { @@ -84,25 +109,40 @@ return classify((Comparable) value); } - private int classify(Comparable val) { - Comparable value = val; + @SuppressWarnings("rawtypes") + private int classify(Comparable<?> val) { + Comparable<?> value = val; if (val instanceof Integer) { //convert to double as java is stupid value = new Double(((Integer) val).intValue()); } //check each slot and see if: min <= value < max int last = min.length - 1; for (int i = 0; i <= last; i++) { - Comparable localMin = (Comparable) this.min[i]; - Comparable localMax = (Comparable) this.max[i]; + Comparable localMin = this.min[i]; + Comparable localMax = this.max[i]; - if (localMin.compareTo(value) < 1 && localMax.compareTo(value) > 0) { + if ((localMin == null || localMin.compareTo(value) < 1 ) && + ( localMax == null || localMax.compareTo(value) > 0)) { return i; } } - if (max[last].compareTo(value) == 0) { //if value = max, put it in the last slot + if (compareTo(max[last],value) == 0) { //if value = max, put it in the last slot return last; } - return -1; + return -1; // value does not fit into any of the provided categories } + + private int compareTo(Comparable compare, Comparable value) { + if( compare == null && value == null ){ + return 0; + } + else if( compare == null ){ + return -1; + } + else if( value == null ){ + return +1; + } + return value.compareTo(compare); + } } Modified: trunk/modules/library/main/src/main/java/org/geotools/filter/function/StandardDeviationFunction.java =================================================================== --- trunk/modules/library/main/src/main/java/org/geotools/filter/function/StandardDeviationFunction.java 2012-05-11 07:58:42 UTC (rev 38710) +++ trunk/modules/library/main/src/main/java/org/geotools/filter/function/StandardDeviationFunction.java 2012-05-11 09:05:43 UTC (rev 38711) @@ -47,27 +47,26 @@ private Object calculate(SimpleFeatureCollection featureCollection) { try { int classNum = getClasses(); - // find the average - AverageVisitor averageVisit = new AverageVisitor(getExpression()); - if (progress == null) progress = new NullProgressListener(); - featureCollection.accepts(averageVisit, progress); - if (progress.isCanceled()) return null; - CalcResult calcResult = averageVisit.getResult(); - if (calcResult == null) return null; - double average = calcResult.toDouble(); - // find the standard deviation - StandardDeviationVisitor sdVisit = new StandardDeviationVisitor(getExpression(), average); - featureCollection.accepts(sdVisit, progress); - if (progress.isCanceled()) return null; - calcResult = sdVisit.getResult(); - if (calcResult == null) return null; - double standardDeviation = calcResult.toDouble(); + + // find the standard deviation + StandardDeviationVisitor sdVisit = new StandardDeviationVisitor(getExpression()); + + featureCollection.accepts(sdVisit, progress); + if (progress != null && progress.isCanceled()) { + return null; + } + CalcResult calcResult = sdVisit.getResult(); + if (calcResult == null) { + return null; + } + double standardDeviation = calcResult.toDouble(); + //figure out the min and max values Double min[] = new Double[classNum]; Double max[] = new Double[classNum]; for (int i = 0; i < classNum; i++) { - min[i] = getMin(i, classNum, average, standardDeviation); - max[i] = getMax(i, classNum, average, standardDeviation); + min[i] = getMin(i, classNum, sdVisit.getMean(), standardDeviation); + max[i] = getMax(i, classNum, sdVisit.getMean(), standardDeviation); } return new RangedClassifier(min, max); } catch (IOException e) { Modified: trunk/modules/library/main/src/test/java/org/geotools/filter/function/StandardDeviationFunctionTest.java =================================================================== --- trunk/modules/library/main/src/test/java/org/geotools/filter/function/StandardDeviationFunctionTest.java 2012-05-11 07:58:42 UTC (rev 38710) +++ trunk/modules/library/main/src/test/java/org/geotools/filter/function/StandardDeviationFunctionTest.java 2012-05-11 09:05:43 UTC (rev 38711) @@ -20,6 +20,8 @@ import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.feature.FeatureCollections; +import org.opengis.feature.Feature; +import org.opengis.feature.FeatureVisitor; import org.opengis.feature.simple.SimpleFeature; import org.opengis.filter.expression.Function; import org.opengis.filter.expression.Literal; @@ -72,46 +74,72 @@ assertEquals(12, func.getClasses()); } - public void xTestGetValue() throws Exception{ + public void testGetValue() throws Exception{ //doesn't work yet? Literal classes = ff.literal(5); PropertyName exp = ff.property("foo"); - Function func = ff.function("StandardDeviation", exp, classes); + Function standardDeviation = ff.function("StandardDeviation", exp, classes); + assertNotNull( "step 1 - standard deviation function", standardDeviation ); + final Classifier classifer = standardDeviation.evaluate( featureCollection, Classifier.class ); + featureCollection.accepts( new FeatureVisitor() { + @Override + public void visit(Feature f) { + SimpleFeature feature = (SimpleFeature) f; + Object value = feature.getAttribute("foo"); + assertNotNull( feature.getID()+" foo", value ); + + int slot = classifer.classify( value ); + assertNotNull( "Slot "+slot, classifer.getTitle( slot ) ); + } + }, null ); + + Function classify = ff.function("classify", exp, ff.literal(classifer)); + assertNotNull( "step 2 - classify function", classify ); + SimpleFeatureIterator list = featureCollection.features(); + //feature 1 SimpleFeature f = list.next(); - int slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(1, slot); + Integer slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"), 1, slot.intValue()); + //feature 2 f = list.next(); - slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(4, slot); + slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"),4, slot.intValue()); + + //feature 3 f = list.next(); - slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(2, slot); + slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"),2, slot.intValue()); + //feature 4 f = list.next(); - slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(2, slot); + slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"),2, slot.intValue()); + + //feature 5 f = list.next(); - slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(2, slot); + slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"),2, slot.intValue()); + + //feature 6 f = list.next(); - slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(3, slot); + slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"),3, slot.intValue()); + //feature 7 f = list.next(); - slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(1, slot); + slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"),1, slot.intValue()); + //feature 8 f = list.next(); - slot = ((Number)func.evaluate(f)).intValue(); - assertEquals(1, slot); + slot = classify.evaluate(f,Integer.class); + assertEquals( "value "+f.getAttribute("foo"),1, slot.intValue()); } - - } |
From: <svn...@os...> - 2012-05-11 07:58:53
|
Author: jive Date: 2012-05-11 00:58:42 -0700 (Fri, 11 May 2012) New Revision: 38710 Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java Log: Reduce AuthorityBackedFactory reporting down to finer to hide an expected message from NADCONTransform when it is not supplied with the support files required for some transforms, see GEOT-4124 Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java 2012-05-10 09:56:21 UTC (rev 38709) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/operation/AuthorityBackedFactory.java 2012-05-11 07:58:42 UTC (rev 38710) @@ -262,7 +262,7 @@ * Other kind of error. It may be more serious, but the super-class is capable * to provides a raisonable default behavior. Log as a warning and lets continue. */ - log(exception, authorityFactory); + log(exception, authorityFactory,Level.FINER); return null; } if (operations != null) { @@ -433,7 +433,13 @@ * Logs a warning when an object can't be created from the specified factory. */ private static void log(final Exception exception, final AuthorityFactory factory) { - final LogRecord record = Loggings.format(Level.WARNING, + log( exception, factory, Level.WARNING); + } + /** + * Logs a warning when an object can't be created from the specified factory. + */ + private static void log(final Exception exception, final AuthorityFactory factory, Level level) { + final LogRecord record = Loggings.format( level, LoggingKeys.CANT_CREATE_COORDINATE_OPERATION_$1, factory.getAuthority().getTitle()); record.setSourceClassName(AuthorityBackedFactory.class.getName()); |
Author: jive Date: 2012-05-10 02:56:21 -0700 (Thu, 10 May 2012) New Revision: 38709 Modified: trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/FallbackAuthorityFactoryTest.java trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java Log: Use CRS reset to clear the slate during testing of anything with the fallback factory, see GEOT-4134 Modified: trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/FallbackAuthorityFactoryTest.java =================================================================== --- trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/FallbackAuthorityFactoryTest.java 2012-05-10 09:16:34 UTC (rev 38708) +++ trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/FallbackAuthorityFactoryTest.java 2012-05-10 09:56:21 UTC (rev 38709) @@ -60,6 +60,8 @@ @Before public void setUp() { assertNull(extra); + + CRS.reset("all"); extra = new FactoryEPSGExtra(); ReferencingFactoryFinder.addAuthorityFactory(extra); ReferencingFactoryFinder.scanForPlugins(); @@ -81,12 +83,15 @@ */ @Test public void testFactoryOrdering() { - Set factories = ReferencingFactoryFinder.getCRSAuthorityFactories(null); + Set<CRSAuthorityFactory> factories = ReferencingFactoryFinder.getCRSAuthorityFactories(null); + for( CRSAuthorityFactory factory : factories ){ + System.out.println("--> "+factory.getClass().getSimpleName() ); + } boolean foundWkt = false; boolean foundExtra = false; - for (Iterator it = factories.iterator(); it.hasNext();) { + for (Iterator<CRSAuthorityFactory> it = factories.iterator(); it.hasNext();) { CRSAuthorityFactory factory = (CRSAuthorityFactory) it.next(); - Class type = factory.getClass(); + Class<?> type = factory.getClass(); if (VERBOSE) { System.out.println(type); } Modified: trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java 2012-05-10 09:16:34 UTC (rev 38708) +++ trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java 2012-05-10 09:56:21 UTC (rev 38709) @@ -88,6 +88,8 @@ * Tests versioning. */ public void testVersion() throws FactoryException { + CRS.reset("all"); + CoordinateReferenceSystem expected = CRS.decode("EPSG:4326"); final String version = String.valueOf(CRS.getVersion("EPSG")); final String urn = "urn:ogc:def:crs:EPSG:" + version + ":4326"; |
Author: ang05a Date: 2012-05-10 02:16:34 -0700 (Thu, 10 May 2012) New Revision: 38708 Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/filter/XPath.java trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/ComplexTestData.java trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/UnmappingFilterVisitorTest.java trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/XPathTest.java Log: Brett Walker's patch for GEOT-4117: Select XML attributes on the root element Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java 2012-05-09 10:37:32 UTC (rev 38707) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java 2012-05-10 09:16:34 UTC (rev 38708) @@ -269,19 +269,24 @@ } List expressions = getExpressions(candidates); - // does the last step refer to a client property of the parent step? + // Does the last step refer to a client property of the parent step? + // The parent step could be the root element which may not be on the path. // i.e. a client property maps to an xml attribute, and the step list // could have been generated from an xpath of the form - // propA/propB@attName - if (candidates.size() == 0 && propertyName.size() > 1) { + // @attName or propA/propB@attName + if (candidates.size() == 0 && propertyName.size() > 0) { XPath.Step clientPropertyStep = (Step) propertyName.get(propertyName.size() - 1); Name clientPropertyName = Types.toTypeName(clientPropertyStep.getName()); + XPath.StepList parentPath; - XPath.StepList parentPath = new XPath.StepList(propertyName); - parentPath.remove(parentPath.size() - 1); + if (propertyName.size() == 1) { + parentPath = XPath.rootElementSteps(this.target, this.namespaces); + } else { + parentPath = new XPath.StepList(propertyName); + parentPath.remove(parentPath.size() - 1); + } candidates = getAttributeMappingsIgnoreIndex(parentPath); - expressions = getClientPropertyExpressions(candidates, clientPropertyName, parentPath); if (expressions.isEmpty()) { // this might be a wrapper mapping for another complex mapping Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/filter/XPath.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/filter/XPath.java 2012-05-09 10:37:32 UTC (rev 38707) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/filter/XPath.java 2012-05-10 09:16:34 UTC (rev 38708) @@ -480,6 +480,29 @@ } /** + * Returns the list of steps in an x-path expression that represents the root element. + * + * @param root + * non null descriptor of the root attribute, generally the Feature descriptor. + * @param namespaces + * namespace support for generating qnames from namespaces. + * @return A list of unique of steps in an xpath expression. + * @throws IllegalArgumentException + * if <code>root</code> is undefined. + */ + public static StepList rootElementSteps(final AttributeDescriptor rootElement, + final NamespaceSupport namespaces) throws IllegalArgumentException { + + if (rootElement == null) { + throw new NullPointerException("root"); + } + StepList steps = new StepList(); + QName qName = Types.toQName(rootElement.getName(), namespaces); + steps.add(new Step(qName, 1, false, false)); + return steps; + } + + /** * Returns the list of stepts in <code>xpathExpression</code> by cleaning it up removing * unnecessary elements. * <p> Modified: trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/ComplexTestData.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/ComplexTestData.java 2012-05-09 10:37:32 UTC (rev 38707) +++ trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/ComplexTestData.java 2012-05-10 09:16:34 UTC (rev 38708) @@ -424,4 +424,56 @@ assertEquals(superType, type.getSuper()); } + /** + * Similar to the feature type return by {@link createExample01MultiValuedComplexProperty} + * except that there is no namespace uri specified. + * + * @param typeFactory + * @return FeatureType + */ + public static FeatureType createExample05NoNamespaceURI(FeatureTypeFactory typeFactory) { + FeatureType wqPlusType; + + TypeBuilder builder = new TypeBuilder(typeFactory); + + builder.setName("sitename"); + builder.setBinding(String.class); + AttributeType SITENAME = builder.attribute(); + + builder.setName("anzlic_noType"); + builder.setBinding(String.class); + AttributeType ANZLIC_NO = builder.attribute(); + + builder.setName("locationType"); + builder.setBinding(Point.class); + GeometryType LOCATION = builder.geometry(); + + // build complex attribute + AttributeType MEASUREMENT = createMeasurementType(typeFactory); + + builder.setName("project_noType"); + builder.setBinding(String.class); + AttributeType PROJECT_NO = builder.attribute(); + + builder.setName("wq_plus"); + + builder.cardinality(1, 1); + builder.addAttribute("sitename", SITENAME); + + builder.cardinality(0, 1); + builder.addAttribute("anzlic_no", ANZLIC_NO); + + builder.cardinality(0, 1); + builder.addAttribute("location", LOCATION); + + builder.cardinality(0, Integer.MAX_VALUE); + builder.addAttribute("measurement", MEASUREMENT); + + builder.cardinality(0, 1); + builder.addAttribute("project_no", PROJECT_NO); + + wqPlusType = builder.feature(); + + return wqPlusType; + } } Modified: trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/UnmappingFilterVisitorTest.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/UnmappingFilterVisitorTest.java 2012-05-09 10:37:32 UTC (rev 38707) +++ trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/UnmappingFilterVisitorTest.java 2012-05-10 09:16:34 UTC (rev 38708) @@ -41,7 +41,6 @@ import org.geotools.data.FeatureSource; import org.geotools.data.complex.AppSchemaDataAccess; import org.geotools.data.complex.AttributeMapping; -import org.geotools.data.complex.DataAccessRegistry; import org.geotools.data.complex.FeatureTypeMapping; import org.geotools.data.complex.TestData; import org.geotools.data.complex.filter.XPath.Step; @@ -53,14 +52,12 @@ import org.geotools.feature.TypeBuilder; import org.geotools.feature.Types; import org.geotools.feature.type.UniqueNameFeatureTypeFactoryImpl; -import org.geotools.filter.FidFilterImpl; import org.geotools.filter.FilterFactoryImplNamespaceAware; import org.geotools.filter.IsEqualsToImpl; import org.geotools.filter.OrImpl; import org.geotools.gml3.GML; import org.geotools.test.AppSchemaTestSupport; import org.geotools.xlink.XLINK; -import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; @@ -399,7 +396,58 @@ assertTrue(unrolled.get(0) instanceof Expression); } + /** + * An x-path expression may target a "client property" mapping (in xml land, an xml attribute + * rather than a xml element). + * + * @throws Exception + */ @Test + public void testPropertyNameWithGmlIdAttribute() throws Exception { + final String XMMLNS = "http://www.opengis.net/xmml"; + final Name typeName = new NameImpl(XMMLNS, "Borehole"); + + AppSchemaDataAccess complexDs = (AppSchemaDataAccess) mappingDataStore; + + mapping = complexDs.getMappingByElement(typeName); + + NamespaceSupport namespaces = new NamespaceSupport(); + namespaces.declarePrefix("gml", GML.NAMESPACE); + namespaces.declarePrefix("xmml", XMMLNS); + namespaces.declarePrefix("xlink", XLINK.NAMESPACE); + + visitor = new UnmappingFilterVisitor(mapping); + FilterFactory2 ff = new FilterFactoryImplNamespaceAware(namespaces); + + String xpathExpression = "@gml:id"; + PropertyName propNameExpression = ff.property(xpathExpression); + + List /* <Expression> */unrolled = (List) propNameExpression.accept(visitor, null); + assertNotNull(unrolled); + assertEquals(1, unrolled.size()); + assertTrue(unrolled.get(0) instanceof Expression); + assertEquals(((Expression) unrolled.get(0)).toString(), "strConcat([bh.], [BGS_ID])"); + + xpathExpression = "/@gml:id"; + propNameExpression = ff.property(xpathExpression); + + unrolled = (List) propNameExpression.accept(visitor, null); + assertNotNull(unrolled); + assertEquals(1, unrolled.size()); + assertTrue(unrolled.get(0) instanceof Expression); + assertEquals(((Expression) unrolled.get(0)).toString(), "strConcat([bh.], [BGS_ID])"); + + xpathExpression = "xmml:Borehole/@gml:id"; + propNameExpression = ff.property(xpathExpression); + + unrolled = (List) propNameExpression.accept(visitor, null); + assertNotNull(unrolled); + assertEquals(1, unrolled.size()); + assertTrue(unrolled.get(0) instanceof Expression); + assertEquals(((Expression) unrolled.get(0)).toString(), "strConcat([bh.], [BGS_ID])"); + } + + @Test public void testBetweenFilter() throws Exception { PropertyIsBetween bf = ff.between(ff.property("measurement/result"), ff.literal(1), ff .literal(2), MatchAction.ALL); Modified: trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/XPathTest.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/XPathTest.java 2012-05-09 10:37:32 UTC (rev 38707) +++ trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/filter/XPathTest.java 2012-05-10 09:16:34 UTC (rev 38708) @@ -172,4 +172,54 @@ assertFalse(Types.isSimpleContentType(GMLSchema.ABSTRACTFEATURECOLLECTIONTYPE_TYPE)); } + /** + * Test that the {@link StepList} for the root element is properly formed. + */ + @Test + public void testRootElementSteps() { + NamespaceSupport namespaces = new NamespaceSupport(); + + try { + XPath.rootElementSteps(null, namespaces); + fail("passed null"); + } catch (NullPointerException e) { + } + + FeatureType complexType = ComplexTestData + .createExample05NoNamespaceURI(new UniqueNameFeatureTypeFactoryImpl()); + Name name = complexType.getName(); + AttributeDescriptor descriptor = new AttributeDescriptorImpl(complexType, name, 0, + Integer.MAX_VALUE, true, null); + + try { + XPath.rootElementSteps(descriptor, namespaces); + } catch (NullPointerException e) { + fail("failed null"); + } + + assertEquals(1, XPath.rootElementSteps(descriptor, namespaces).size()); + XPath.Step step = XPath.rootElementSteps(descriptor, namespaces).get(0); + QName rootQName = new QName(name.getNamespaceURI(), name.getLocalPart(), ""); + assertEquals(rootQName, step.getName()); + + complexType = ComplexTestData + .createExample01MultiValuedComplexProperty(new UniqueNameFeatureTypeFactoryImpl()); + name = complexType.getName(); + descriptor = new AttributeDescriptorImpl(complexType, name, 0, Integer.MAX_VALUE, true, + null); + + String prefix = "wq"; + namespaces.declarePrefix(prefix, name.getNamespaceURI()); + + try { + XPath.rootElementSteps(descriptor, namespaces); + } catch (NullPointerException e) { + fail("failed null"); + } + + assertEquals(1, XPath.rootElementSteps(descriptor, namespaces).size()); + step = XPath.rootElementSteps(descriptor, namespaces).get(0); + rootQName = new QName(name.getNamespaceURI(), name.getLocalPart(), prefix); + assertEquals(rootQName, step.getName()); + } } |
From: <svn...@os...> - 2012-05-09 10:37:43
|
Author: danieleromagnoli Date: 2012-05-09 03:37:32 -0700 (Wed, 09 May 2012) New Revision: 38707 Modified: branches/2.7.x/modules/unsupported/matfile5/pom.xml Log: Removing old repository reference from unsupported matlab plugin Modified: branches/2.7.x/modules/unsupported/matfile5/pom.xml =================================================================== --- branches/2.7.x/modules/unsupported/matfile5/pom.xml 2012-05-09 10:36:38 UTC (rev 38706) +++ branches/2.7.x/modules/unsupported/matfile5/pom.xml 2012-05-09 10:37:32 UTC (rev 38707) @@ -29,6 +29,10 @@ <name>SAS Matlab grid coverage readers</name> <url>http://maven.geotools.fr/reports/modules/unsupported/sas/</url> + <properties> + <imageio.mat.version>1.1M012010</imageio.mat.version> + </properties> + <scm> <connection> scm:svn:http://svn.osgeo.org/geotools/trunk/modules/unsupported/matfile5 @@ -75,14 +79,6 @@ </developer> </developers> - <repositories> - <repository> - <id>geosolutions</id> - <name>GeoSolutions libraries repository</name> - <url>http://mvn.geo-solutions.it/</url> - </repository> - </repositories> - <!-- =========================================================== --> <!-- Dependency Management --> <!-- =========================================================== --> @@ -95,12 +91,12 @@ <dependency> <groupId>it.geosolutions.imageio-ext</groupId> <artifactId>imageio-ext-mat-sas</artifactId> - <version>1.1M012010</version> + <version>${imageio.mat.version}</version> </dependency> <dependency> <groupId>it.geosolutions.imageio-ext</groupId> <artifactId>imageio-ext-imagereadmt</artifactId> - <version>1.1M012010</version> + <version>${imageio.mat.version}</version> </dependency> <dependency> <groupId>org.geotools</groupId> |
From: <svn...@os...> - 2012-05-09 10:36:50
|
Author: danieleromagnoli Date: 2012-05-09 03:36:38 -0700 (Wed, 09 May 2012) New Revision: 38706 Modified: trunk/modules/unsupported/matfile5/pom.xml Log: Removing old repository reference from unsupported matlab plugin Modified: trunk/modules/unsupported/matfile5/pom.xml =================================================================== --- trunk/modules/unsupported/matfile5/pom.xml 2012-05-08 20:50:44 UTC (rev 38705) +++ trunk/modules/unsupported/matfile5/pom.xml 2012-05-09 10:36:38 UTC (rev 38706) @@ -29,6 +29,10 @@ <name>SAS Matlab grid coverage readers</name> <url>http://maven.geotools.fr/reports/modules/unsupported/sas/</url> + <properties> + <imageio.mat.version>1.1M012010</imageio.mat.version> + </properties> + <scm> <connection> scm:svn:http://svn.osgeo.org/geotools/trunk/modules/unsupported/matfile5 @@ -75,14 +79,6 @@ </developer> </developers> - <repositories> - <repository> - <id>geosolutions</id> - <name>GeoSolutions libraries repository</name> - <url>http://mvn.geo-solutions.it/</url> - </repository> - </repositories> - <!-- =========================================================== --> <!-- Dependency Management --> <!-- =========================================================== --> @@ -95,12 +91,12 @@ <dependency> <groupId>it.geosolutions.imageio-ext</groupId> <artifactId>imageio-ext-mat-sas</artifactId> - <version>1.1M012010</version> + <version>${imageio.mat.version}</version> </dependency> <dependency> <groupId>it.geosolutions.imageio-ext</groupId> <artifactId>imageio-ext-imagereadmt</artifactId> - <version>1.1M012010</version> + <version>${imageio.mat.version}</version> </dependency> <dependency> <groupId>org.geotools</groupId> |
From: <svn...@os...> - 2012-05-08 20:50:50
|
Author: nielscharlier Date: 2012-05-08 13:50:44 -0700 (Tue, 08 May 2012) New Revision: 38705 Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/NestedAttributeMapping.java Log: app-schema fix null filters bug Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/NestedAttributeMapping.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/NestedAttributeMapping.java 2012-05-06 10:24:36 UTC (rev 38704) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/NestedAttributeMapping.java 2012-05-08 20:50:44 UTC (rev 38705) @@ -45,6 +45,7 @@ import org.opengis.filter.identity.FeatureId; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.xml.sax.helpers.NamespaceSupport; +import java.util.Collections; /** * This class represents AttributeMapping for attributes that are nested inside another complex @@ -355,6 +356,10 @@ public List<Feature> getFeatures(Object source, Object foreignKeyValue, List<Object> idValues, CoordinateReferenceSystem reprojection, Object feature, List<PropertyName> selectedProperties, boolean includeMandatory) throws IOException { + if (foreignKeyValue == null) { + return Collections.<Feature>emptyList(); + } + if (isSameSource()) { // if linkField is null, this method shouldn't be called because the mapping // should use the same table, and handles it differently |
From: <svn...@os...> - 2012-05-06 10:24:46
|
Author: aaime Date: 2012-05-06 03:24:36 -0700 (Sun, 06 May 2012) New Revision: 38704 Modified: trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisNGJNDIDataStoreFactory.java Log: Remove extra unexpected param which makes sense only for factories building their own connection pool Modified: trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisNGJNDIDataStoreFactory.java =================================================================== --- trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisNGJNDIDataStoreFactory.java 2012-05-06 10:24:21 UTC (rev 38703) +++ trunk/modules/plugin/jdbc/jdbc-postgis/src/main/java/org/geotools/data/postgis/PostgisNGJNDIDataStoreFactory.java 2012-05-06 10:24:36 UTC (rev 38704) @@ -44,7 +44,6 @@ parameters.put(LOOSEBBOX.key, LOOSEBBOX); parameters.put(ESTIMATED_EXTENTS.key, ESTIMATED_EXTENTS); parameters.put(PREPARED_STATEMENTS.key, PREPARED_STATEMENTS); - parameters.put(MAX_OPEN_PREPARED_STATEMENTS.key, MAX_OPEN_PREPARED_STATEMENTS); parameters.put(ENCODE_FUNCTIONS.key, ENCODE_FUNCTIONS); } } |
Author: aaime Date: 2012-05-06 03:24:21 -0700 (Sun, 06 May 2012) New Revision: 38703 Added: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/ trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java Log: [GEOT-4108] File based CoordinateOperation factory Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/DeferredAuthorityFactory.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -126,7 +126,7 @@ * @throws FactoryException if the creation of backing store failed. */ @Override - final AbstractAuthorityFactory getBackingStore() throws FactoryException { + protected final AbstractAuthorityFactory getBackingStore() throws FactoryException { if (backingStore == null) { synchronized (this) { if(backingStore == null) { Added: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java (rev 0) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/PropertyCoordinateOperationAuthorityFactory.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,342 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.referencing.factory; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.geotools.referencing.CRS; +import org.geotools.referencing.operation.DefaultMathTransformFactory; +import org.geotools.referencing.operation.DefaultOperation; +import org.geotools.referencing.operation.DefaultOperationMethod; +import org.geotools.referencing.operation.transform.AbstractMathTransform; +import org.geotools.referencing.operation.transform.AffineTransform2D; +import org.geotools.util.SimpleInternationalString; +import org.opengis.metadata.citation.Citation; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.IdentifiedObject; +import org.opengis.referencing.NoSuchAuthorityCodeException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.NoninvertibleTransformException; +import org.opengis.referencing.operation.OperationMethod; +import org.opengis.util.InternationalString; + +/** + * A {@link CoordinateOperationAuthorityFactory} backed by a properties file. + * Allows custom transform definitions across two CRSs, expressed as WKT math transforms. + * Entries in the properties file take this format: + * <pre> + * [source crs code],[target crs code]=[WKT math transform] + * </pre> + * Examples: + * <pre> + * 4230,4258=PARAM_MT["NTv2", PARAMETER["Latitude and longitude difference file", "100800401.gsb"]] + * 23031,25831=PARAM_MT["Similarity transformation", \ + * PARAMETER["Ordinate 1 of evaluation point in target CRS", -129.549], \ + * PARAMETER["Ordinate 2 of evaluation point in target CRS", -208.185], \ + * PARAMETER["Scale difference", 1.0000015504], \ + * PARAMETER["Rotation angle of source coordinate reference system axes", 1.56504]] + * </pre> + * For more compact definitions, parameter names can be replaced by their corresponding EPSG codes. + * Following examples are the same as former ones: + * <pre> + * 4230,4258=PARAM_MT["9615", PARAMETER["8656", "100800401.gsb"]] + * 23031,25831=PARAM_MT["9621", \ + * PARAMETER["8621", -129.549], \ + * PARAMETER["8622", -208.185], \ + * PARAMETER["8611", 1.0000015504], \ + * PARAMETER["8614", 1.56504]] + * </pre> + * References: + * <p> + * See <a href="http://www.geoapi.org/3.0/javadoc/org/opengis/referencing/doc-files/WKT.html"> + * <cite>Well-Known Text format</cite></a> for math transform syntax. + * Visit the <a href="http://www.epsg-registry.org/"> <cite>EPSG Geodetic Parameter Registry</cite> + * </a> for EPSG parameter codes and values. + * <p> + * Note that invertible transforms will be used in both directions. + * <p> + * This factory doesn't cache any result. Any call to a {@code createFoo} method will trig a new + * WKT parsing. For caching, this factory should be wrapped in some buffered factory like + * {@link BufferedAuthorityFactory}. + * + * @source $URL$ + * @version $Id$ + * @author Oscar Fonts + */ +public class PropertyCoordinateOperationAuthorityFactory extends + DirectAuthorityFactory implements CoordinateOperationAuthorityFactory { + + /** + * The authority for this factory. + */ + private final Citation authority; + + /** + * The properties object for our properties file. Keys are CRS code pairs + * separated by a comma. The associated value is a WKT string for the Math + * Transform. See {@link PropertyCoordinateOperationAuthorityFactory}. + */ + private final Properties definitions = new Properties(); + + /** + * An unmodifiable view of the authority keys. This view is always up to date + * even if entries are added or removed in the {@linkplain #definitions} map. + */ + @SuppressWarnings({ "rawtypes", "unchecked" }) + private final Set<String> codes = Collections.unmodifiableSet((Set) definitions.keySet()); + + /** + * Creates a factory for the specified authority from the specified file. + * + * @param factories The underlying factories used for objects creation. + * @param authority The organization or party responsible for definition and maintenance of + * the database. + * @param definitions URL to the definition file. + * @throws IOException if the definitions can't be read. + */ + public PropertyCoordinateOperationAuthorityFactory( + final ReferencingFactoryContainer factories, + final Citation authority, + final URL definitions) + throws IOException + { + // Set priority low + super(factories, MINIMUM_PRIORITY + 10); + + // Set authority + this.authority = authority; + ensureNonNull("authority", authority); + + // Load properties + final InputStream in = definitions.openStream(); + this.definitions.load(in); + in.close(); + } + + /** + * Creates an operation from a single operation code. + * + * @param code Coded value for operation. + * @return The operation for the given code. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + @Override + public CoordinateOperation createCoordinateOperation(String code) + throws NoSuchAuthorityCodeException, FactoryException { + String[] crsPair = trimAuthority(code).split(","); + if (crsPair.length == 2) { + Set<CoordinateOperation> coordopset = createFromCoordinateReferenceSystemCodes( + trimAuthority(crsPair[0]), trimAuthority(crsPair[1])); + if (!coordopset.isEmpty()) { + return coordopset.iterator().next(); + } + } + return null; + } + + /** + * Creates a {@link CoordinateOperation} from + * {@linkplain CoordinateReferenceSystem coordinate reference system} codes. + * This method returns a single operation from the properties file. + * If operation is invertible, will check also for the inverse one. + * If operation not found, it will return an empty set. + * + * @param sourceCRS Coded value of source coordinate reference system. + * @param targetCRS Coded value of target coordinate reference system. + * @return The operation from {@code sourceCRS} to {@code targetCRS} (one single element). + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + @Override + public Set<CoordinateOperation> createFromCoordinateReferenceSystemCodes( + String sourceCRS, String targetCRS) + throws NoSuchAuthorityCodeException, FactoryException { + + Set<CoordinateOperation> coordops = new HashSet<CoordinateOperation>(1); + + CoordinateOperation coordop = createFromCoordinateReferenceSystemCodes(sourceCRS, + targetCRS, false); + if (coordop == null) { + // Not found. Try to create from the inverse. + coordop = createFromCoordinateReferenceSystemCodes(targetCRS, sourceCRS, true); + } + if (coordop != null) { + // Add to set if found. + coordops.add(coordop); + } + return coordops; + } + + + /** + * Seeks for a WKT definition in the properties file from a CRS pair, parses it, + * and creates the corresponding CoordinateOperation. Returns {@code null} + * if something went wrong. + * <p> + * Will log a WARNING message if a parsing error occurred. + * + * @param sourceCRS Coded value of source coordinate reference system. + * @param targetCRS Coded value of target coordinate reference system. + * @param inverse {@code true} to create operation from the inverse definition. + * @return The operation from {@code sourceCRS} to {@code targetCRS}, + * or {@code null} if not found. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + CoordinateOperation createFromCoordinateReferenceSystemCodes( + String sourceCRS, String targetCRS, boolean inverse) + throws NoSuchAuthorityCodeException, FactoryException { + + // Get WKT definition from properties + sourceCRS = trimAuthority(sourceCRS); + targetCRS = trimAuthority(targetCRS); + String id = sourceCRS+","+targetCRS; + String WKT = definitions.getProperty(id); + if(WKT == null) { + // No definition found. + return null; + } + + // Create MathTransform from WKT + MathTransform mt = null; + try { + mt = factories.getMathTransformFactory().createFromWKT(WKT); + } catch (FactoryException e) { + // Probably malformed WKT. + LOGGER.warning("Error creating transformation: " + WKT); + return null; + } + + // Create the CRS definitions + String s = this.authority.getIdentifiers().iterator().next().getCode(); + CoordinateReferenceSystem source = CRS.decode(s+":"+sourceCRS); + CoordinateReferenceSystem target = CRS.decode(s+":"+targetCRS); + + // Need to create a derived MathTransform that will handle axis order and units + // as defined in CRS. Had to cast to DefaultMathTransformFactory because + // createBaseToDerived is not defined in MathTransformFactory interface (GeoAPI). + DefaultMathTransformFactory mtf = (DefaultMathTransformFactory)factories. + getMathTransformFactory(); + MathTransform mt2 = mtf.createBaseToDerived(source, mt, target.getCoordinateSystem()); + + // Extract name from the transform, if possible, or use class name. + String methodName; + try { + if (mt instanceof AbstractMathTransform) { + methodName = ((AbstractMathTransform)mt).getParameterValues().getDescriptor().getName().getCode(); + } else if (mt instanceof AffineTransform2D) { + methodName = ((AffineTransform2D)mt).getParameterValues().getDescriptor().getName().getCode(); + } else { + methodName = mt.getClass().getSimpleName(); + } + } catch (NullPointerException e) { + methodName = mt.getClass().getSimpleName(); + } + Map<String, String> props = new HashMap<String, String>(); + props.put("name", methodName); + + // Create the OperationMethod + OperationMethod method = new DefaultOperationMethod(props, + mt2.getSourceDimensions(), mt2.getTargetDimensions(), null); + + // Finally create CoordinateOperation + CoordinateOperation coordop = null; + if (!inverse) { // Direct operation + props.put("name", sourceCRS + " \u21E8 " + targetCRS); + coordop = DefaultOperation.create(props, source, target, + mt2, method, CoordinateOperation.class); + } else { // Inverse operation + try { + props.put("name", targetCRS + " \u21E8 " + sourceCRS); + coordop = DefaultOperation.create(props, target, source, + mt2.inverse(), method, CoordinateOperation.class); + } catch (NoninvertibleTransformException e) { + return null; + } + } + return coordop; + } + + /** + * Returns the set of authority codes of the given type. + * Only CoordinateOperation.class is accepted as type. + * + * This factory will not filter codes for its subclasses. + * + * @param type The CoordinateOperation type (or null, same effect). + * @return All of available authority codes, or an empty set. + */ + @Override + public Set<String> getAuthorityCodes(Class<? extends IdentifiedObject> type) { + if (type==null || type.isAssignableFrom(CoordinateOperation.class)) { + return codes; + } else { + return Collections.emptySet(); + } + } + + /** + * Gets a description of the object corresponding to a code. + * + * @param code Value allocated by authority. + * @return A description of the object, or {@code null} if the object + * corresponding to the specified {@code code} has no description. + * @throws NoSuchAuthorityCodeException if the specified {@code code} was not found. + * @throws FactoryException if the query failed for some other reason. + */ + @Override + public InternationalString getDescriptionText(String code) + throws NoSuchAuthorityCodeException, FactoryException { + + final String wkt = definitions.getProperty(trimAuthority(code)); + + if (wkt == null) { + throw noSuchAuthorityCode(IdentifiedObject.class, code); + } + + // The first string literal in WKT will be considered the description text. + int start = wkt.indexOf('"'); + if (start >= 0) { + final int end = wkt.indexOf('"', ++start); + if (end >= 0) { + return new SimpleInternationalString(wkt.substring(start, end).trim()); + } + } + return null; + } + + /** + * Returns the organization or party responsible for definition and maintenance of the + * database. + */ + @Override + public Citation getAuthority() { + return authority; + } +} Added: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java (rev 0) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKT.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,329 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.referencing.factory.epsg; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Iterator; +import java.util.Set; +import java.util.logging.Level; +import java.util.logging.LogRecord; + +import org.geotools.factory.GeoTools; +import org.geotools.factory.Hints; +import org.geotools.metadata.iso.citation.Citations; +import org.geotools.referencing.ReferencingFactoryFinder; +import org.geotools.referencing.factory.AbstractAuthorityFactory; +import org.geotools.referencing.factory.DeferredAuthorityFactory; +import org.geotools.referencing.factory.FactoryNotFoundException; +import org.geotools.referencing.factory.PropertyCoordinateOperationAuthorityFactory; +import org.geotools.referencing.factory.ReferencingFactoryContainer; +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.logging.Logging; +import org.opengis.metadata.Identifier; +import org.opengis.metadata.citation.Citation; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.NoSuchAuthorityCodeException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.CoordinateOperationAuthorityFactory; + +/** + * Authority factory that holds user-defined + * {@linkplain CoordinateOperation Coordinate Operations}. + * <p> + * This factory can be used as a replacement for Coordinate Operations when there is no access + * to a complete EPSG database. Or can be used to override the coordinate operations defined in + * EPSG if assigned a higher priority. + * <p> + * The Coordinate Operations are defined as <cite>Well Known Text</cite> math transforms (see + * {@link PropertyCoordinateOperationAuthorityFactory} for format specification and examples). + * <p> + * Property file name is {@value #FILENAME}, and its possible locations are described + * {@linkplain #FILENAME here}. If no property file is found, the factory won't be activated. + * <p> + * If an operation is not found in the properties file, this factory will delegate + * creation on a fallback factory. The fallback factory is the next registered + * {@link CoordinateOperationAuthorityFactory} after this one in the + * {@linkplain org.geotools.factory.AbstractFactory#priority priority} chain. + * + * @source $URL$ + * @version $Id$ + * @author Oscar Fonts + */ +public class CoordinateOperationFactoryUsingWKT extends DeferredAuthorityFactory + implements CoordinateOperationAuthorityFactory { + /** + * The authority. Will be created only when first needed. + * + * @see #getAuthority + */ + protected Citation authority; + + /** + * The default filename to read. The default {@code FactoryUsingWKT} implementation will + * search for the first occurence of this file in the following places: + * <p> + * <ul> + * <li>In the directory specified by the + * {@value org.geotools.factory.GeoTools#CRS_AUTHORITY_EXTRA_DIRECTORY} + * system property.</li> + * <li>In every {@code org/geotools/referencing/factory/espg} directories found on the + * classpath.</li> + * </ul> + * <p> + * + * @see #getDefinitionsURL + */ + public static final String FILENAME = "epsg_operations.properties"; + + /** + * Priority for this factory + */ + public static final int PRIORITY = NORMAL_PRIORITY - 20; + + /** + * The factories to be given to the backing store. + */ + protected final ReferencingFactoryContainer factories; + + /** + * Directory scanned for extra definitions. + */ + protected final String directory; + + /** + * An alternate factory to be used when the primary one doesn't find an operation + */ + protected CoordinateOperationAuthorityFactory fallbackAuthorityFactory = null; + + /** + * Just a flag not to search more than once + */ + protected boolean fallbackAuthorityFactorySearched = false; + + /** + * Constructs an authority factory using the default set of factories. + */ + public CoordinateOperationFactoryUsingWKT() { + this(null, PRIORITY); + } + + /** + * Constructs an authority factory using a set of factories created from the specified hints. + */ + public CoordinateOperationFactoryUsingWKT(Hints userHints) { + this(userHints, PRIORITY); + } + + /** + * Constructs an authority factory using the specified hints and priority. + */ + protected CoordinateOperationFactoryUsingWKT(final Hints userHints, final int priority) { + super(userHints, priority); + factories = ReferencingFactoryContainer.instance(userHints); + + // Search for user CRS_AUTHORITY_EXTRA_DIRECTORY hint, or use system default value. + Object directoryHint = null; + if (userHints != null && userHints.get(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY) != null) { + directoryHint = userHints.get(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY); + } else if (Hints.getSystemDefault(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY) != null) { + directoryHint = Hints.getSystemDefault(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY); + } + if (directoryHint != null) { + directory = directoryHint.toString(); + hints.put(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY, directory); + } else { + directory = null; + } + + } + + public synchronized Citation getAuthority() { + if (authority == null) { + authority = Citations.EPSG; + } + return authority; + } + + /** + * Creates the backing store authority factory. + * + * @return The backing store to uses in {@code createXXX(...)} methods. + * @throws FactoryNotFoundException if the {@code properties} file has not been found. + * @throws FactoryException if the constructor failed to find or read the file. + * This exception usually has an {@link IOException} as its cause. + */ + protected AbstractAuthorityFactory createBackingStore() throws FactoryException { + try { + URL url = getDefinitionsURL(); + if (url == null) { + throw new FactoryNotFoundException(Errors.format( + ErrorKeys.FILE_DOES_NOT_EXIST_$1, FILENAME)); + } + final Iterator<? extends Identifier> ids = getAuthority().getIdentifiers().iterator(); + final String authority = ids.hasNext() ? ids.next().getCode() : "EPSG"; + final LogRecord record = Loggings.format(Level.CONFIG, + LoggingKeys.USING_FILE_AS_FACTORY_$2, url.getPath(), authority); + record.setLoggerName(LOGGER.getName()); + LOGGER.log(record); + return new PropertyCoordinateOperationAuthorityFactory(factories, this.getAuthority(), url); + } catch (IOException exception) { + throw new FactoryException(Errors.format(ErrorKeys.CANT_READ_$1, FILENAME), exception); + } + } + + /** + * Returns the URL to the property file that contains Operation definitions. + * The default implementation performs the following search path: + * <ul> + * <li>If a value is set for the {@value GeoTools#CRS_AUTHORITY_EXTRA_DIRECTORY} system property key, + * then the {@value #FILENAME} file will be searched in this directory.</li> + * <li>If no value is set for the above-cited system property, or if no {@value #FILENAME} + * file was found in that directory, then the first {@value #FILENAME} file found in + * any {@code org/geotools/referencing/factory/epsg} directory on the classpath will + * be used.</li> + * <li>If no file was found on the classpath neither, then this factory will be disabled.</li> + * </ul> + * + * @return The URL, or {@code null} if none. + */ + protected URL getDefinitionsURL() { + try { + if (directory != null) { + final File file = new File(directory, FILENAME); + if (file.isFile()) { + return file.toURI().toURL(); // TODO + } + } + } catch (SecurityException exception) { + Logging.unexpectedException(LOGGER, exception); + } catch (MalformedURLException exception) { + Logging.unexpectedException(LOGGER, exception); + } + return this.getClass().getResource(FILENAME); + } + + /** + * Creates operations from {@linkplain CoordinateReferenceSystem coordinate reference system} + * codes. + * + * This method searches in the {@linkplain #FILENAME properties file} for operations. + * + * If not found there, it will create operations from a fallback factory (see + * {@link #getFallbackAuthorityFactory}). + * + * @param sourceCRS Coded value of source coordinate reference system. + * @param targetCRS Coded value of target coordinate reference system. + * @return The operations from {@code sourceCRS} to {@code targetCRS}. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + @Override + public Set<CoordinateOperation> createFromCoordinateReferenceSystemCodes( + String sourceCRS, String targetCRS) throws NoSuchAuthorityCodeException, FactoryException { + Set<CoordinateOperation> coordops = super.createFromCoordinateReferenceSystemCodes(sourceCRS, targetCRS); + if (coordops.isEmpty()) { + // If not found, delegate to the fallback factory. + CoordinateOperationAuthorityFactory fallback = getFallbackAuthorityFactory(); + if (fallback != null) { + coordops = fallback.createFromCoordinateReferenceSystemCodes(sourceCRS, targetCRS); + } + } + return coordops; + } + + /** + * Creates an operation from a single operation code. + * + * This method searches in the {@linkplain #FILENAME properties file} for operations. + * + * If not found there, it will create operations from a fallback factory (see + * {@link #getFallbackAuthorityFactory}). + * + * @param code Coded value for operation. + * @return The operation from {@code sourceCRS} to {@code targetCRS}. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + public CoordinateOperation createCoordinateOperation(String code) + throws NoSuchAuthorityCodeException, FactoryException { + CoordinateOperation coordop = super.createCoordinateOperation(code); + if (coordop == null) { + CoordinateOperationAuthorityFactory fallback = getFallbackAuthorityFactory(); + if (fallback != null) { + coordop = fallback.createCoordinateOperation(code); + } + } + return coordop; + } + + /** + * Gets the next available {@link CoordinateOperationAuthorityFactory} + * in the priority list. + * + * @return the alternative CoordinateOperationAuthorityFactory. + * @throws NoSuchAuthorityCodeException if a specified code was not found. + * @throws FactoryException if the object creation failed for some other reason. + */ + protected CoordinateOperationAuthorityFactory getFallbackAuthorityFactory() + throws NoSuchAuthorityCodeException, FactoryException { + + if(!fallbackAuthorityFactorySearched) { // Search once + CoordinateOperationAuthorityFactory candidate = null; + + // These hints are to prevent infinite recursion when called + // from OrderedAxisAuthorityFactory. See "noForce(Hints)" + // from AuthorityBackedFactory. + // See also: http://jira.codehaus.org/browse/GEOT-1161 + Hints h = new Hints(); + h.put(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.FALSE); + h.put(Hints.FORCE_STANDARD_AXIS_DIRECTIONS, Boolean.FALSE); + h.put(Hints.FORCE_STANDARD_AXIS_UNITS, Boolean.FALSE); + + Set<CoordinateOperationAuthorityFactory> factories = ReferencingFactoryFinder. + getCoordinateOperationAuthorityFactories(h); + Iterator<CoordinateOperationAuthorityFactory> it = factories.iterator(); + + // Skip factories with higher priority than me. + while (it.hasNext()) { + candidate = it.next(); + if (candidate == this) { + break; + } + } + + // Get the next one for this same authority + while (it.hasNext()) { + candidate = it.next(); + if (!(candidate instanceof CoordinateOperationFactoryUsingWKT) + && candidate.getAuthority().getTitle().equals(this.getAuthority().getTitle())) { + fallbackAuthorityFactory = candidate; + break; + } + } + fallbackAuthorityFactorySearched = true; + } + + return fallbackAuthorityFactory; + } +} \ No newline at end of file Modified: trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java =================================================================== --- trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/main/java/org/geotools/referencing/wkt/MathTransformParser.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -16,6 +16,7 @@ */ package org.geotools.referencing.wkt; +import java.net.URI; import java.text.ParseException; import java.text.ParsePosition; @@ -184,6 +185,8 @@ parameter.setValue(param.pullInteger("value")); } else if (Double.class.equals(type)) { parameter.setValue(param.pullDouble("value")); + } else if (URI.class.equals(type)){ + parameter.setValue(URI.create(param.pullString("value"))); } else { parameter.setValue(param.pullString("value")); } Modified: trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory =================================================================== --- trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/main/resources/META-INF/services/org.opengis.referencing.operation.CoordinateOperationAuthorityFactory 2012-05-06 10:24:21 UTC (rev 38703) @@ -1,3 +1,4 @@ +org.geotools.referencing.factory.epsg.CoordinateOperationFactoryUsingWKT org.geotools.referencing.factory.epsg.DefaultFactory org.geotools.referencing.factory.epsg.LongitudeFirstFactory org.geotools.referencing.factory.URN_AuthorityFactory Added: trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java =================================================================== --- trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java (rev 0) +++ trunk/modules/library/referencing/src/test/java/org/geotools/referencing/factory/epsg/CoordinateOperationFactoryUsingWKTTest.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,201 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.referencing.factory.epsg; + +import static org.junit.Assert.*; + +import java.io.File; +import java.util.Properties; +import java.util.Set; + +import org.geotools.factory.AbstractFactory; +import org.geotools.factory.Hints; +import org.geotools.metadata.iso.citation.Citations; +import org.geotools.referencing.CRS; +import org.geotools.referencing.ReferencingFactoryFinder; +import org.junit.Before; +import org.junit.Test; +import org.opengis.referencing.FactoryException; +import org.opengis.referencing.NoSuchAuthorityCodeException; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; + +/** + * Tests the {@link testCoordinateOperationFactoryUsingWKT} public methods. + * + * @author Oscar Fonts + */ +public class CoordinateOperationFactoryUsingWKTTest { + + CoordinateOperationFactoryUsingWKT factory; + + private static final String DEFINITIONS_FILE_NAME = "epsg_operations.properties"; + private static Properties properties; + + private static final String SOURCE_CRS = "EPSG:TEST1"; + private static final String TARGET_CRS = "EPSG:TEST2"; + private static final String CRS_PAIR = SOURCE_CRS + "," + TARGET_CRS; + private static final String INVERSE_CRS_PAIR = TARGET_CRS + "," + SOURCE_CRS; + private static final String INVALID_CRS = "nonexistent"; + + private static final double[] SRC_TEST_POINT = {3.084896111, 39.592654167}; + private static final double[] DST_TEST_POINT = {3.0844689951999427, 39.594235744481225}; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + ReferencingFactoryFinder.addAuthorityFactory( + new FactoryUsingWKT(null, AbstractFactory.MAXIMUM_PRIORITY)); + + factory = (CoordinateOperationFactoryUsingWKT) ReferencingFactoryFinder. + getCoordinateOperationAuthorityFactory("EPSG", + new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class)); + + // Read definitions + properties = new Properties(); + properties.load(this.getClass().getResourceAsStream(DEFINITIONS_FILE_NAME)); + } + + /** + * @throws Exception + */ + @Test + public void testExtraDirectoryHint() throws Exception { + Hints hints = new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class); + try { + hints.put(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY, "invalid"); + fail("Should of been tossed out as an invalid hint"); + } + catch (IllegalArgumentException expected) { + // This is the expected exception. + } + String directory = new File(".").getAbsolutePath(); + hints = new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class); + hints.put(Hints.CRS_AUTHORITY_EXTRA_DIRECTORY, directory); + + CoordinateOperationFactoryUsingWKT fact = (CoordinateOperationFactoryUsingWKT) + ReferencingFactoryFinder.getCoordinateOperationAuthorityFactory("EPSG", + new Hints(Hints.COORDINATE_OPERATION_AUTHORITY_FACTORY, + CoordinateOperationFactoryUsingWKT.class)); + + // BTW testing the inverse construction + CoordinateOperation co = fact.createCoordinateOperation(INVERSE_CRS_PAIR); + CoordinateReferenceSystem crs = CRS.decode(TARGET_CRS); + assertSame(crs, co.getSourceCRS()); + crs = CRS.decode(SOURCE_CRS); + assertSame(crs, co.getTargetCRS()); + + assertTrue(co.getMathTransform() instanceof MathTransform); + double[] p = new double[2]; + co.getMathTransform().transform(DST_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], SRC_TEST_POINT[0], 1e-8); + assertEquals(p[1], SRC_TEST_POINT[1], 1e-8); + } + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#getAuthority}. + */ + @Test + public void testGetAuthority() { + assertTrue(factory.getAuthority().equals(Citations.EPSG)); + } + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#createCoordinateOperation}. + * @throws TransformException + */ + @Test + public void testCreateCoordinateOperation() throws TransformException { + + try { + assertNull(factory.createCoordinateOperation(INVALID_CRS)); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when requesting" + + "a nonexistent operation. Instead, a NoSuchAuthorityCodeException was expected."); + } + + try { + // Test CoordinateOperation + CoordinateOperation co = factory.createCoordinateOperation(CRS_PAIR); + assertNotNull(co); + + // Test CRSs + CoordinateReferenceSystem crs = CRS.decode(SOURCE_CRS); + assertSame(crs, co.getSourceCRS()); + crs = CRS.decode(TARGET_CRS); + assertSame(crs, co.getTargetCRS()); + + // Test MathTransform + assertTrue(co.getMathTransform() instanceof MathTransform); + double[] p = new double[2]; + co.getMathTransform().transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when creating" + + " coordinate operation from an existing code."); + } + } + + /** + * Test method for + * {@link CoordinateOperationFactoryUsingWKT#createFromCoordinateReferenceSystemCodes}. + * @throws TransformException + */ + @Test + public void testCreateFromCoordinateReferenceSystemCodes() throws TransformException { + try { + Set<CoordinateOperation> cos = factory.createFromCoordinateReferenceSystemCodes( + INVALID_CRS, INVALID_CRS); + assertTrue(cos.isEmpty()); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when requesting" + + "a nonexistent operation. Instead, a NoSuchAuthorityCodeException was expected."); + } + + try { + // Test CoordinateOperation + Set<CoordinateOperation> cos = factory.createFromCoordinateReferenceSystemCodes(SOURCE_CRS, TARGET_CRS); + assertTrue(cos.size() == 1); + CoordinateOperation co = cos.iterator().next(); + assertNotNull(co); + + // Test CRSs + CoordinateReferenceSystem crs = CRS.decode(SOURCE_CRS); + assertSame(crs, co.getSourceCRS()); + crs = CRS.decode(TARGET_CRS); + assertSame(crs, co.getTargetCRS()); + + // Test MathTransform + assertTrue(co.getMathTransform() instanceof MathTransform); + double[] p = new double[2]; + co.getMathTransform().transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } catch (FactoryException e) { + fail(factory.getClass().getSimpleName() + " threw a FactoryException when creating" + + " coordinate operation from an existing code."); + } + } +} Modified: trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties =================================================================== --- trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -5,3 +5,24 @@ # 42101=PROJCS["WGS 84 / LCC Canada",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Decimal_Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["central_meridian",-95.0],PARAMETER["latitude_of_origin",0],PARAMETER["standard_parallel_1",49.0],PARAMETER["standard_parallel_2",77.0],PARAMETER["false_northing",-8000000.0],UNIT["Meter",1]] + +# These are used in CoordinateOperationFactoryUsingWKTTest +TEST1=GEOGCS["ED50", \ + DATUM["European Datum 1950", \ + SPHEROID["International 1924", 6378388.0, 297.0, AUTHORITY["EPSG","7022"]], \ + TOWGS84[-116.641, -56.931, -110.559, 0.893, 0.921, -0.917, -3.52], \ + AUTHORITY["EPSG","6230"]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295], \ + AXIS["Geodetic latitude", NORTH], \ + AXIS["Geodetic longitude", EAST], \ + AUTHORITY["EPSG","4230"]] +TEST2=GEOGCS["WGS 84", \ + DATUM["World Geodetic System 1984", \ + SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], \ + AUTHORITY["EPSG","6326"]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295], \ + AXIS["Geodetic latitude", NORTH], \ + AXIS["Geodetic longitude", EAST], \ + AUTHORITY["EPSG","4326"]] Added: trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties =================================================================== --- trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties (rev 0) +++ trunk/modules/library/referencing/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,13 @@ +# Data used in CoordinateOperationFactoryUsingWKTTest +TEST1,TEST2=CONCAT_MT[ \ + PARAM_MT["Ellipsoid_To_Geocentric", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378388.0], \ + PARAMETER["semi_minor", 6356911.9461279465]], \ + PARAM_MT["Position Vector transformation (geog2D domain)", PARAMETER["dx", 1], PARAMETER["dy", 2], PARAMETER["dz", 3], PARAMETER["ex", 4], PARAMETER["ey", 5], PARAMETER["ez", 6], PARAMETER["ppm", 7]], \ + PARAM_MT["Geocentric_To_Ellipsoid", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378137.0], \ + PARAMETER["semi_minor", 6356752.314245179]] \ + ] +#4230,4258=PARAM_MT["NTv2", PARAMETER["Latitude and longitude difference file", "100800401.gsb"]] Modified: trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java 2012-05-04 15:22:05 UTC (rev 38702) +++ trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/URN_EPSG_Test.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -108,7 +108,7 @@ assertSame(expected, test.createCoordinateReferenceSystem("urn:ogc:def:crs:EPSG:6.11:4326")); assertEquals("6.11", test.lastVersion.toString()); assertEquals("Should use the fallback factory.", - failureCount + 1, FallbackAuthorityFactory.getFailureCount()); + failureCount + 2, FallbackAuthorityFactory.getFailureCount()); } /** Added: trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java (rev 0) +++ trunk/modules/plugin/epsg-hsql/src/test/java/org/geotools/referencing/factory/epsg/LongitudeFirstFactoryOverrideTest.java 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,135 @@ +/* + * GeoTools - The Open Source Java GIS Toolkit + * http://geotools.org + * + * (C) 2002-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.referencing.factory.epsg; + +import static org.junit.Assert.*; + +import java.util.Properties; + +import org.geotools.factory.AbstractFactory; +import org.geotools.referencing.CRS; +import org.geotools.referencing.ReferencingFactoryFinder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.opengis.referencing.operation.ConcatenatedOperation; +import org.opengis.referencing.operation.CoordinateOperation; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; + +/** + * Makes sure the {@link testCoordinateOperationFactoryUsingWKT} is not ignored when + * referencing is setup in "Longitude first" mode. + * + * @author Oscar Fonts + * @author Andrea Aime + */ +public class LongitudeFirstFactoryOverrideTest { + + private static final String DEFINITIONS_FILE_NAME = "epsg_operations.properties"; + private static Properties properties; + + private static final String SOURCE_CRS = "EPSG:TEST1"; + private static final String TARGET_CRS = "EPSG:TEST2"; + + private static final double[] SRC_TEST_POINT = {39.592654167, 3.084896111}; + private static final double[] DST_TEST_POINT = {39.594235744481225, 3.0844689951999427}; + + /** + * @throws java.lang.Exception + */ + @Before + public void setUp() throws Exception { + // force longitude first mode + System.setProperty("org.geotools.referencing.forceXY", "true"); + + CRS.reset("all"); + + ReferencingFactoryFinder.addAuthorityFactory( + new FactoryUsingWKT(null, AbstractFactory.MAXIMUM_PRIORITY)); + + ReferencingFactoryFinder.addAuthorityFactory(new CoordinateOperationFactoryUsingWKT(null, AbstractFactory.MAXIMUM_PRIORITY)); + + // Read definitions + properties = new Properties(); + properties.load(this.getClass().getResourceAsStream(DEFINITIONS_FILE_NAME)); + } + + @After + public void tearDown() { + // unset axis ordering hint + System.clearProperty("org.geotools.referencing.forceXY"); + + CRS.reset("all"); + } + + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#createCoordinateOperation}. + * @throws TransformException + */ + @Test + public void testCreateOperationFromCustomCodes() throws Exception { + // Test CRSs + CoordinateReferenceSystem source = CRS.decode(SOURCE_CRS); + CoordinateReferenceSystem target = CRS.decode(TARGET_CRS); + MathTransform mt = CRS.findMathTransform(source, target, true); + + // Test MathTransform + double[] p = new double[2]; + mt.transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } + + /** + * Test method for {@link CoordinateOperationFactoryUsingWKT#createCoordinateOperation}. + * @throws TransformException + */ + @Test + public void testOverrideEPSGOperation() throws Exception { + // Test CRSs + CoordinateReferenceSystem source = CRS.decode("EPSG:4269"); + CoordinateReferenceSystem target = CRS.decode("EPSG:4326"); + MathTransform mt = CRS.findMathTransform(source, target, true); + + // Test MathTransform + double[] p = new double[2]; + mt.transform(SRC_TEST_POINT, 0, p, 0, 1); + assertEquals(p[0], DST_TEST_POINT[0], 1e-8); + assertEquals(p[1], DST_TEST_POINT[1], 1e-8); + } + + /** + * Check we are actually using the EPSG database for anything not in override + * + * @throws TransformException + */ + @Test + public void testFallbackOnEPSGDatabase() throws Exception { + // Test CRSs + CoordinateReferenceSystem source = CRS.decode("EPSG:3003"); + CoordinateReferenceSystem target = CRS.decode("EPSG:4326"); + CoordinateOperation co = CRS.getCoordinateOperationFactory(true).createOperation(source, target); + ConcatenatedOperation cco = (ConcatenatedOperation) co; + // the EPSG one only has two steps, the non EPSG one 4 + assertEquals(2, cco.getOperations().size()); + } + + +} \ No newline at end of file Added: trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties (rev 0) +++ trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,20 @@ +# +# Additional CRS for unit testing FactoryUsingWkt. +# +# $Id$ +# + +42101=PROJCS["WGS 84 / LCC Canada",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Decimal_Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic_2SP"],PARAMETER["central_meridian",-95.0],PARAMETER["latitude_of_origin",0],PARAMETER["standard_parallel_1",49.0],PARAMETER["standard_parallel_2",77.0],PARAMETER["false_northing",-8000000.0],UNIT["Meter",1]] + +# These are used in CoordinateOperationFactoryUsingWKTTest +TEST1=GEOGCS["ED50", \ + DATUM["European Datum 1950", \ + SPHEROID["International 1924", 6378388.0, 297.0, AUTHORITY["EPSG","7022"]], \ + TOWGS84[-116.641, -56.931, -110.559, 0.893, 0.921, -0.917, -3.52]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295]] +TEST2=GEOGCS["WGS 84", \ + DATUM["World Geodetic System 1984", \ + SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]]], \ + PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], \ + UNIT["degree", 0.017453292519943295]] Added: trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties =================================================================== --- trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties (rev 0) +++ trunk/modules/plugin/epsg-hsql/src/test/resources/org/geotools/referencing/factory/epsg/epsg_operations.properties 2012-05-06 10:24:21 UTC (rev 38703) @@ -0,0 +1,24 @@ +# Data used in CoordinateOperationFactoryUsingWKTTest +TEST1,TEST2=CONCAT_MT[ \ + PARAM_MT["Ellipsoid_To_Geocentric", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378388.0], \ + PARAMETER["semi_minor", 6356911.9461279465]], \ + PARAM_MT["Position Vector transformation (geog2D domain)", PARAMETER["dx", 1], PARAMETER["dy", 2], PARAMETER["dz", 3], PARAMETER["ex", 4], PARAMETER["ey", 5], PARAMETER["ez", 6], PARAMETER["ppm", 7]], \ + PARAM_MT["Geocentric_To_Ellipsoid", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378137.0], \ + PARAMETER["semi_minor", 6356752.314245179]] \ + ] +4269,4326=CONCAT_MT[ \ + PARAM_MT["Ellipsoid_To_Geocentric", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378388.0], \ + PARAMETER["semi_minor", 6356911.9461279465]], \ + PARAM_MT["Position Vector transformation (geog2D domain)", PARAMETER["dx", 1], PARAMETER["dy", 2], PARAMETER["dz", 3], PARAMETER["ex", 4], PARAMETER["ey", 5], PARAMETER["ez", 6], PARAMETER["ppm", 7]], \ + PARAM_MT["Geocentric_To_Ellipsoid", \ + PARAMETER["dim", 2], \ + PARAMETER["semi_major", 6378137.0], \ + PARAMETER["semi_minor", 6356752.314245179]] \ + ] +#4230,4258=PARAM_MT["NTv2", PARAMETER["Latitude and longitude difference file", "100800401.gsb"]] |
From: <svn...@os...> - 2012-05-04 15:22:16
|
Author: aaime Date: 2012-05-04 08:22:05 -0700 (Fri, 04 May 2012) New Revision: 38702 Modified: trunk/modules/unsupported/wps/src/main/java/org/geotools/data/wps/response/ExecuteProcessResponse.java trunk/modules/unsupported/wps/src/test/java/org/geotools/data/wps/OnlineWPSManualRequestTest.java Log: [GEOT-4127] WPS client won't report exceptions in case a raw response has been demanded by the client Modified: trunk/modules/unsupported/wps/src/main/java/org/geotools/data/wps/response/ExecuteProcessResponse.java =================================================================== --- trunk/modules/unsupported/wps/src/main/java/org/geotools/data/wps/response/ExecuteProcessResponse.java 2012-05-03 13:01:36 UTC (rev 38701) +++ trunk/modules/unsupported/wps/src/main/java/org/geotools/data/wps/response/ExecuteProcessResponse.java 2012-05-04 15:22:05 UTC (rev 38702) @@ -76,7 +76,7 @@ // could be gml or other stuff, not necessarily a service exception, we need to check if it's an exception or not rawContentType = httpResponse.getContentType(); - if(rawContentType.startsWith("text/xml")) { + if(rawContentType.matches(".*/xml.*")) { // make sure we don't throw away info inputStream = new BufferedInputStream(httpResponse.getResponseStream()); inputStream.mark(8192); @@ -89,9 +89,8 @@ // get the first tag name String name = parser.getName(); - String namespace = parser.getNamespace(); inputStream.reset(); - if("ServiceException".equals(name) || "ExecuteResponse".equals(name)) { + if("ServiceException".equals(name) || "ExceptionReport".equals(name) || "ExecuteResponse".equals(name)) { parseDocumentResponse(inputStream); return; } @@ -143,6 +142,10 @@ if (object instanceof ExecuteResponseType) { exeResponse = (ExecuteResponseType) object; + // in case of exceptions let's be explicit about them + if(exeResponse.getStatus() != null && exeResponse.getStatus().getProcessFailed() != null) { + excepResponse = exeResponse.getStatus().getProcessFailed().getExceptionReport(); + } } // exception caught on server and returned else if (object instanceof ExceptionReportType) Modified: trunk/modules/unsupported/wps/src/test/java/org/geotools/data/wps/OnlineWPSManualRequestTest.java =================================================================== --- trunk/modules/unsupported/wps/src/test/java/org/geotools/data/wps/OnlineWPSManualRequestTest.java 2012-05-03 13:01:36 UTC (rev 38701) +++ trunk/modules/unsupported/wps/src/test/java/org/geotools/data/wps/OnlineWPSManualRequestTest.java 2012-05-04 15:22:05 UTC (rev 38702) @@ -26,6 +26,7 @@ import java.util.List; import net.opengis.ows11.ExceptionReportType; +import net.opengis.ows11.ExceptionType; import net.opengis.wps10.DataType; import net.opengis.wps10.DocumentOutputDefinitionType; import net.opengis.wps10.ExecuteResponseType; @@ -933,4 +934,152 @@ System.out.println(arcgrid); assertTrue(arcgrid.startsWith(expectedHeader)); } + + /** + * Test exception parsing on invalid process request + * + * @throws ServiceException + * @throws IOException + * @throws ParseException + */ + public void testInvalidProcess() throws ServiceException, IOException, ParseException + { + + // don't run the test if the server is not up + if (fixture == null) + { + return; + } + + if (DISABLE) + { + return; + } + + String processIdenLocal = "gs:InvalidProcessName"; + + WPSCapabilitiesType capabilities = wps.getCapabilities(); + + // get the first process and execute it + ProcessOfferingsType processOfferings = capabilities.getProcessOfferings(); + EList processes = processOfferings.getProcess(); + // ProcessBriefType process = (ProcessBriefType) processes.get(0); + + // does the server contain the specific process I want + boolean found = false; + Iterator iterator = processes.iterator(); + while (iterator.hasNext()) + { + ProcessBriefType process = (ProcessBriefType) iterator.next(); + if (process.getIdentifier().getValue().equalsIgnoreCase(processIdenLocal)) + { + found = true; + + break; + } + } + + // exit test if my process doesn't exist on server + if (found) + { + System.out.println("Skipping, gs:InvalidProcessName has been found!"); + return; + } + + // setup a fake call to fake process + ExecuteProcessRequest exeRequest = wps.createExecuteProcessRequest(); + exeRequest.setIdentifier(processIdenLocal); + ResponseDocumentType doc = wps.createResponseDocumentType(false, true, true, "result"); + DocumentOutputDefinitionType odt = (DocumentOutputDefinitionType) doc.getOutput().get(0); + odt.setMimeType("application/arcgrid"); + odt.setAsReference(true); + ResponseFormType responseForm = wps.createResponseForm(doc, null); + exeRequest.setResponseForm(responseForm); + + // send the request + ExecuteProcessResponse response = wps.issueRequest(exeRequest); + + // response should not be null and no exception should occur. + assertNotNull(response); + + // we should get an exception + ExceptionReportType report = response.getExceptionResponse(); + assertNotNull(report); + ExceptionType exception = (ExceptionType) report.getException().get(0); + String errorMessage = exception.getExceptionText().get(0).toString(); + assertTrue(errorMessage.contains(processIdenLocal)); + } + + /** + * Make sure we get the proper exception report + * + * @throws ServiceException + * @throws IOException + * @throws ParseException + */ + public void testInvalidParamsRawOutput() throws ServiceException, IOException, ParseException + { + + // don't run the test if the server is not up + if (fixture == null) + { + return; + } + + if (DISABLE) + { + return; + } + + String processIdenLocal = "gs:AreaGrid"; + + WPSCapabilitiesType capabilities = wps.getCapabilities(); + + // get the first process and execute it + ProcessOfferingsType processOfferings = capabilities.getProcessOfferings(); + EList processes = processOfferings.getProcess(); + // ProcessBriefType process = (ProcessBriefType) processes.get(0); + + // does the server contain the specific process I want + boolean found = false; + Iterator iterator = processes.iterator(); + while (iterator.hasNext()) + { + ProcessBriefType process = (ProcessBriefType) iterator.next(); + if (process.getIdentifier().getValue().equalsIgnoreCase(processIdenLocal)) + { + found = true; + + break; + } + } + + // exit test if my process doesn't exist on server + if (!found) + { + System.out.println("Skipping, gs:AreaGrid not found!"); + return; + } + + // based on the describeprocess, setup the execute + ExecuteProcessRequest exeRequest = wps.createExecuteProcessRequest(); + exeRequest.setIdentifier(processIdenLocal); + // don't send over the inputs + OutputDefinitionType rawOutput = wps.createOutputDefinitionType("result"); + rawOutput.setMimeType("application/arcgrid"); + ResponseFormType responseForm = wps.createResponseForm(null, rawOutput); + exeRequest.setResponseForm(responseForm); + + // send the request + ExecuteProcessResponse response = wps.issueRequest(exeRequest); + + // response should not be null and no exception should occur. + assertNotNull(response); + + // we should get an exception here too + ExceptionReportType report = response.getExceptionResponse(); + assertNotNull(report); + } + + } |
Author: ang05a Date: 2012-05-03 06:01:36 -0700 (Thu, 03 May 2012) New Revision: 38701 Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AttributeMapping.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/ComplexFeatureConstants.java 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/NestedAttributeMapping.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AppSchemaDataAccessConfigurator.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AttributeMapping.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/XMLConfigDigester.java trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/TestData.java trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/AppSchemaDataAccess.xsd Log: GEOT-4126: Enable specifying row number in getting sourceExpression for denormalised rows (for timeseries subsetting). Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AttributeMapping.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AttributeMapping.java 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/AttributeMapping.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -63,6 +63,8 @@ private String instancePath; + private String sourceIndex; + /** * Creates a new AttributeMapping object. * @@ -73,10 +75,10 @@ */ public AttributeMapping(Expression idExpression, Expression sourceExpression, StepList targetXPath) { - this(idExpression, sourceExpression, targetXPath, null, false, null); + this(idExpression, sourceExpression, null, targetXPath, null, false, null); } - public AttributeMapping(Expression idExpression, Expression sourceExpression, + public AttributeMapping(Expression idExpression, Expression sourceExpression, String sourceIndex, StepList targetXPath, AttributeType targetNodeInstance, boolean isMultiValued, Map<Name, Expression> clientProperties) { @@ -86,6 +88,7 @@ if (this.sourceExpression == null) { this.sourceExpression = Expression.NIL; } + this.sourceIndex = sourceIndex; this.targetXPath = targetXPath; this.targetNodeInstance = targetNodeInstance; this.clientProperties = clientProperties == null ? Collections @@ -103,6 +106,10 @@ public Expression getSourceExpression() { return sourceExpression; } + + public String getSourceIndex() { + return sourceIndex; + } public StepList getTargetXPath() { return targetXPath; Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/ComplexFeatureConstants.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/ComplexFeatureConstants.java 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/ComplexFeatureConstants.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -85,4 +85,9 @@ * Fake attribute name for simple contents of a complex type, eg. gml:name of gml:CodeType type */ public static final Name SIMPLE_CONTENT = new NameImpl(null, "simpleContent"); + + /** + * Constant to indicate the last row from denormalised rows. + */ + public static final String LAST_INDEX = "LAST"; } 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-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -902,7 +902,17 @@ setAttributeValue(target, null, source, attMapping, null, null, selectedProperties.get(attMapping)); } } else { - setAttributeValue(target, null, sources.get(0), attMapping, null, null, selectedProperties.get(attMapping)); + String indexString = attMapping.getSourceIndex(); + // if not specified, get the first row by default + int index = 0; + if (indexString != null) { + if (ComplexFeatureConstants.LAST_INDEX.equals(indexString)) { + index = sources.size() - 1; + } else { + index = Integer.parseInt(indexString); + } + } + setAttributeValue(target, null, sources.get(index), attMapping, null, null, selectedProperties.get(attMapping)); // When a feature is not multi-valued but still has multiple rows with the same ID in // a denormalised table, by default app-schema only takes the first row and ignores // the rest (see above). The following line is to make sure that the cursors in the Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/NestedAttributeMapping.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/NestedAttributeMapping.java 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/NestedAttributeMapping.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -127,7 +127,7 @@ StepList targetXPath, boolean isMultiValued, Map<Name, Expression> clientProperties, Expression sourceElement, StepList sourcePath, NamespaceSupport namespaces) throws IOException { - super(idExpression, parentExpression, targetXPath, null, isMultiValued, clientProperties); + super(idExpression, parentExpression, null, targetXPath, null, isMultiValued, clientProperties); this.nestedTargetXPath = sourcePath; this.nestedFeatureType = sourceElement; this.filterFac = new FilterFactoryImplNamespaceAware(namespaces); Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AppSchemaDataAccessConfigurator.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AppSchemaDataAccessConfigurator.java 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AppSchemaDataAccessConfigurator.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -346,8 +346,6 @@ final boolean isMultiValued = attDto.isMultiple(); - final boolean isList = attDto.isList(); - final Expression idExpression = (idXpath == null) ? parseOgcCqlExpression(idExpr) : new AttributeExpressionImpl(idXpath, new Hints( FeaturePropertyAccessorFactory.NAMESPACE_CONTEXT, this.namespaces)); @@ -401,7 +399,7 @@ } } else { - attMapping = new AttributeMapping(idExpression, sourceExpression, targetXPathSteps, + attMapping = new AttributeMapping(idExpression, sourceExpression, attDto.getSourceIndex(), targetXPathSteps, expectedInstanceOf, isMultiValued, clientProperties); } Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AttributeMapping.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AttributeMapping.java 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/AttributeMapping.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -62,6 +62,17 @@ private String sourceExpression; /** + * Expression whose evaluation result in numeric value to indicate row number to extract {@link + * this#sourceExpression} from denormalised database rows. + * + * <p> + * At this stage, the expression must be a valid integer, or LAST would work to + * get the last dynamic result. + * </p> + */ + private String sourceIndex; + + /** * Label used to refer to an attribute. */ private String label; @@ -162,6 +173,31 @@ } /** + * Returns the expression whose evaluation result in numeric value to indicate row number to extract {@link + * this#sourceExpression} from denormalised database rows. + * + * <p> + * At this stage, the expression must be a valid integer, or LAST would work to + * get the last dynamic result. + * </p> + * + * @return OGC CQL expression for the attribute value + */ + public String getSourceIndex() { + return sourceIndex; + } + + /** + * Sets the OGC CQL expression index for the attribute value. + * + * @param sourceIndex + * OGC CQL expression index for the attribute value. + */ + public void setSourceIndex(String sourceIndex) { + this.sourceIndex = sourceIndex; + } + + /** * Return the input XPath expression * @return the input XPath expression */ Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/XMLConfigDigester.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/XMLConfigDigester.java 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/config/XMLConfigDigester.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -238,6 +238,9 @@ digester.addCallMethod(attMap + "/sourceExpression/OCQL", "setSourceExpression", 1); digester.addCallParam(attMap + "/sourceExpression/OCQL", 0); + + digester.addCallMethod(attMap + "/sourceExpression/index", "setSourceIndex", 1); + digester.addCallParam(attMap + "/sourceExpression/index", 0); digester.addCallMethod(attMap + "/idExpression/inputAttribute", "setIdentifierPath", 1); digester.addCallParam(attMap + "/idExpression/inputAttribute", 0); Modified: trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/TestData.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/TestData.java 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/test/java/org/geotools/data/complex/TestData.java 2012-05-03 13:01:36 UTC (rev 38701) @@ -297,7 +297,7 @@ id = ff.property("id[1]"); source = null; target = "wq_plus/measurement"; - mappings.add(new AttributeMapping(id, source, XPath + mappings.add(new AttributeMapping(id, source, null, XPath .steps(targetFeature, target, namespaces), null, true, null)); source = ff.property("determinand_description"); Modified: trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/AppSchemaDataAccess.xsd =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/AppSchemaDataAccess.xsd 2012-05-02 13:20:19 UTC (rev 38700) +++ trunk/modules/extension/app-schema/app-schema/src/test/resources/test-data/AppSchemaDataAccess.xsd 2012-05-03 13:01:36 UTC (rev 38701) @@ -310,7 +310,16 @@ </annotation> <sequence> <choice minOccurs="0"> - <element name="OCQL" type="string" /> + <sequence> + <element name="OCQL" type="string" /> + <element name="index" type="string" minOccurs="0" maxOccurs="1"> + <annotation> + <documentation> + <![CDATA[ The index of database row if denormalised. Example of usage is timeseries endPosition that reflects the last timePosition where the timePosition value is dynamic. ]]> + </documentation> + </annotation> + </element> + </sequence> <element name="Expression"> <complexType> <sequence> |
From: <svn...@os...> - 2012-05-02 13:20:27
|
Author: ang05a Date: 2012-05-02 06:20:19 -0700 (Wed, 02 May 2012) New Revision: 38700 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/MappingFeatureIteratorFactory.java Log: App-schema isList: subsetting should affect other property values outside the filter properties. 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-05-02 01:23:15 UTC (rev 38699) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-05-02 13:20:19 UTC (rev 38700) @@ -124,8 +124,6 @@ */ private Filter listFilter; - private List<StepList> listFilterProperties; - public DataAccessMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, boolean isFiltered) throws IOException { this(store, mapping, query, null); @@ -181,6 +179,24 @@ } } } + // HACK HACK HACK + // evaluate filter that applies to this list as we want a subset + // instead of full result + // this is a temporary solution for Bureau of Meteorology + // requirement for timePositionList + if (listFilter != null) { + while (exists && !listFilter.evaluate(curSrcFeature)) { + // only add to subset if filter matches value + if (getSourceFeatureIterator() != null + && getSourceFeatureIterator().hasNext()) { + this.curSrcFeature = getSourceFeatureIterator().next(); + exists = true; + } else { + exists = false; + } + } + } + // END OF HACK } else { exists = false; } @@ -714,8 +730,26 @@ while (getSourceFeatureIterator().hasNext()) { Feature next = getSourceFeatureIterator().next(); if (extractIdForFeature(next).equals(fId) && checkForeignIdValues(foreignIdValues, next)) { - features.add(next); - } else { + // HACK HACK HACK + // evaluate filter that applies to this list as we want a subset + // instead of full result + // this is a temporary solution for Bureau of Meteorology + // requirement for timePositionList + if (listFilter != null) { + if (listFilter.evaluate(next)) { + features.add(next); + } + // END OF HACK + } else { + features.add(next); + } + // HACK HACK HACK + // evaluate filter that applies to this list as we want a subset + // instead of full result + // this is a temporary solution for Bureau of Meteorology + // requirement for timePositionList + } else if (listFilter == null || listFilter.evaluate(next)) { + // END OF HACK curSrcFeature = next; break; } @@ -740,6 +774,8 @@ query.setCoordinateSystemReproject(reprojection); } } + + Filter fidFilter; if (mapping.getFeatureIdExpression().equals(Expression.NIL)) { // no real feature id mapping, @@ -747,16 +783,30 @@ Set<FeatureId> ids = new HashSet<FeatureId>(); FeatureId featureId = namespaceAwareFilterFactory.featureId(fId); ids.add(featureId); - query.setFilter(namespaceAwareFilterFactory.id(ids)); - matchingFeatures = this.mappedSource.getFeatures(query); + fidFilter = namespaceAwareFilterFactory.id(ids); } else { // in case the expression is wrapped in a function, eg. strConcat // that's why we don't always filter by id, but do a PropertyIsEqualTo - query.setFilter(namespaceAwareFilterFactory.equals(mapping.getFeatureIdExpression(), - namespaceAwareFilterFactory.literal(fId))); - matchingFeatures = this.mappedSource.getFeatures(query); + fidFilter = namespaceAwareFilterFactory.equals(mapping.getFeatureIdExpression(), + namespaceAwareFilterFactory.literal(fId)); } + + // HACK HACK HACK + // evaluate filter that applies to this list as we want a subset + // instead of full result + // this is a temporary solution for Bureau of Meteorology + // requirement for timePositionList + if (listFilter != null) { + List<Filter> filters = new ArrayList<Filter>(); + filters.add(listFilter); + filters.add(fidFilter); + fidFilter = namespaceAwareFilterFactory.and(filters); + } + // END OF HACK + query.setFilter(fidFilter); + matchingFeatures = this.mappedSource.getFeatures(query); + FeatureIterator<? extends Feature> iterator = matchingFeatures.features(); List<Feature> features = new ArrayList<Feature>(); @@ -830,24 +880,8 @@ if (sources.size() > 1 && instance != null) { List<Object> values = new ArrayList<Object>(); Expression sourceExpr = attMapping.getSourceExpression(); - if (listFilter != null - && listFilterProperties.contains(attMapping.getTargetXPath())) { - for (Feature source : sources) { - // HACK HACK HACK - // evaluate filter that applies to this list as we want a subset - // instead of full result - // this is a temporary solution for Bureau of Meteorology - // requirement for timePositionList - if (listFilter.evaluate(source)) { - // only add to subset if filter matches value - values.add(getValue(sourceExpr, source)); - } - } - } else { - // no filter concerning the list - for (Feature source : sources) { - values.add(getValue(sourceExpr, source)); - } + for (Feature source : sources) { + values.add(getValue(sourceExpr, source)); } String valueString = StringUtils.join(values.iterator(), " "); StepList fullPath = attMapping.getTargetXPath(); @@ -975,7 +1009,6 @@ sourceFeatureIterator = null; sourceFeatures = null; filteredFeatures = null; - listFilterProperties = null; listFilter = null; //NC - joining nested atts @@ -1111,9 +1144,5 @@ public void setListFilter(Filter filter) { listFilter = filter; - } - - public void setListFilterProperties(List<StepList> properties) { - listFilterProperties = properties; - } + } } Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java 2012-05-02 01:23:15 UTC (rev 38699) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java 2012-05-02 13:20:19 UTC (rev 38700) @@ -18,7 +18,6 @@ package org.geotools.data.complex; import java.io.IOException; -import java.util.ArrayList; import java.util.List; import java.util.logging.Logger; @@ -69,15 +68,15 @@ // Attribute mappings that have isList enabled private List<AttributeMapping> listMappings; - // Filter properties that are configured as isList - private List<StepList> listFilterProperties; + // True if the filter has properties that are configured as isList + private boolean isListFilter; private FeatureTypeMapping mappings; public IsListFilterVisitor(List<AttributeMapping> listMappings, FeatureTypeMapping mappings) { this.listMappings = listMappings; this.mappings = mappings; - listFilterProperties = new ArrayList<StepList>(); + isListFilter = false; } @Override @@ -91,14 +90,15 @@ targetXpath = mapping.getTargetXPath(); if (targetXpath.equals(simplifiedSteps)) { // TODO: support feature chaining too? - listFilterProperties.add(targetXpath); + isListFilter = true; + return extraData; } } return extraData; } - public List<StepList> getListFilterProperties() { - return listFilterProperties; + public boolean isListFilterExists() { + return isListFilter; } } @@ -107,23 +107,7 @@ if (mapping instanceof XmlFeatureTypeMapping) { return new XmlMappingFeatureIterator(store, mapping, query); - } - - // HACK HACK HACK - // experimental/temporary solution for isList subsetting by filtering - List<AttributeMapping> listMappings = mapping.getIsListMappings(); - Filter isListFilter = null; - List<StepList> listFilterProperties = null; - if (!listMappings.isEmpty()) { - IsListFilterVisitor listChecker = new IsListFilterVisitor(listMappings, mapping); - Filter complexFilter = query.getFilter(); - complexFilter.accept(listChecker, null); - listFilterProperties = listChecker.getListFilterProperties(); - if (!listFilterProperties.isEmpty()) { - isListFilter = AppSchemaDataAccess.unrollFilter(complexFilter, mapping); - } - } - // END OF HACK + } boolean isJoining = AppSchemaDataAccessConfigurator.isJoining(); @@ -146,6 +130,19 @@ unrolledQuery); } } else { + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + List<AttributeMapping> listMappings = mapping.getIsListMappings(); + Filter isListFilter = null; + if (!listMappings.isEmpty()) { + IsListFilterVisitor listChecker = new IsListFilterVisitor(listMappings, mapping); + Filter complexFilter = query.getFilter(); + complexFilter.accept(listChecker, null); + if (listChecker.isListFilterExists()) { + isListFilter = AppSchemaDataAccess.unrollFilter(complexFilter, mapping); + } + } + // END OF HACK FeatureSource mappedSource = mapping.getSource(); if (isJoining || mappedSource instanceof JDBCFeatureSource || mappedSource instanceof JDBCFeatureStore) { @@ -169,15 +166,12 @@ iterator = new DataAccessMappingFeatureIterator(store, mapping, query, isFiltered); // HACK HACK HACK // experimental/temporary solution for isList subsetting by filtering - if (isListFilter != null) { - ((DataAccessMappingFeatureIterator) iterator).setListFilter(isListFilter); - ((DataAccessMappingFeatureIterator) iterator) - .setListFilterProperties(listFilterProperties); - } + if (isListFilter == null) { // END OF HACK - if (filter != null && filter != Filter.INCLUDE) { - iterator = new PostFilteringMappingFeatureIterator(iterator, filter, + if (filter != null && filter != Filter.INCLUDE) { + iterator = new PostFilteringMappingFeatureIterator(iterator, filter, maxFeatures); + } } } else if (mappedSource instanceof MappingFeatureSource) { // web service data access wrapper @@ -212,17 +206,13 @@ iterator = new DataAccessMappingFeatureIterator(store, mapping, query); } } + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + if (isListFilter != null && iterator instanceof DataAccessMappingFeatureIterator) { + ((DataAccessMappingFeatureIterator) iterator).setListFilter(isListFilter); + } + // END OF HACK } - - // HACK HACK HACK - // experimental/temporary solution for isList subsetting by filtering - if (isListFilter != null && iterator instanceof DataAccessMappingFeatureIterator) { - ((DataAccessMappingFeatureIterator) iterator).setListFilter(isListFilter); - ((DataAccessMappingFeatureIterator) iterator) - .setListFilterProperties(listFilterProperties); - } - // END OF HACK - return iterator; } |
From: <svn...@os...> - 2012-05-02 01:23:24
|
Author: jive Date: 2012-05-01 18:23:15 -0700 (Tue, 01 May 2012) New Revision: 38699 Modified: trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeReader.java trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeWriter.java trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyFeatureWriter.java trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStore2Test.java trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStoreTest.java trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyExamples.java Log: work on property string encoding Signed-off-by: Jody Garnett <jod...@gm...> Modified: trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeReader.java =================================================================== --- trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeReader.java 2012-05-01 18:57:46 UTC (rev 38698) +++ trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeReader.java 2012-05-02 01:23:15 UTC (rev 38699) @@ -4,8 +4,11 @@ import java.io.File; import java.io.FileReader; import java.io.IOException; +import java.util.Arrays; import java.util.NoSuchElementException; import java.util.Properties; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.geotools.data.AttributeReader; import org.geotools.data.DataSourceException; @@ -48,14 +51,19 @@ * </p> * * <pre> - * <code> - * fid4=4||<null> -> Feature( id=2, name="", geom=null ) - * </code> + * fid4=4||<null> * </pre> + * <p> + * You can use \ to escape a | character, you can also use it to protect newlines:: + * <pre> + * fid4=4|I have a \\|splitting\\| headache|POINT(0,0) + * fid5=5|Example of \nmulti-lin text|POINT(1,1) + * fid6=6|Second \\ + * example of multi-line text|POINT(2,2) + * </pre> * * @author Jody Garnett * - * * @source $URL$ */ public class PropertyAttributeReader implements AttributeReader { @@ -183,10 +191,14 @@ if( txt == null ){ break; } + // skip comments if( txt.startsWith("#") || txt.startsWith("!")){ - continue; // skip content + continue; } + // ignore leading white space txt = trimLeft( txt ); + + // handle escaped line feeds used to span multiple lines if( txt.endsWith("\\")){ buffer.append(txt.substring(0,txt.length()-1) ); buffer.append("\n"); @@ -201,13 +213,30 @@ return null; // there is no line } String raw = buffer.toString(); - raw = raw.replace("\\n", "\n" ); - raw = raw.replace("\\r", "\r" ); - raw = raw.replace("\\t", "\t" ); +// String line = decodeString(raw); +// return line; return raw; } /** - * Trim leading white space as described Properties. + * Used to decode common whitespace chracters and escaped | characters. + * + * @param txt Origional raw text as stored + * @return decoded text as provided for storage + * @see PropertyAttributeWriter#encodeString(String) + */ + String decodeString( String txt ){ + // unpack whitespace constants + txt = txt.replace( "\\n", "\n"); + txt = txt.replaceAll("\\r", "\r" ); + + // unpack our our escaped characters + txt = txt.replace("\\|", "|" ); + // txt = txt.replace("\\\\", "\\" ); + + return txt; + } + /** + * Trim leading white space as described Properties file standard. * @see Properties#load(java.io.Reader) * @param txt * @return txt leading whitespace removed @@ -241,15 +270,62 @@ int split = line.indexOf('='); fid = line.substring(0, split); - text = line.substring(split + 1).split("\\|", -1);//use -1 as limit to include empty trailing spaces - if (type.getAttributeCount() != text.length) - throw new DataSourceException("format error: expected " + type.getAttributeCount() - + " attributes, but found " + text.length + ". [" + line + "]"); + String data = line.substring(split+1); + + text = splitIntoText(data); } else { throw new NoSuchElementException(); } } + /** + * Split the provided text using | charater as a seperator. + * <p> + * This method respects the used of \ to "escape" a | character allowing + * representations such as the following:<pre> + * String example="text|example of escaped \\| character|text"; + * + * // represents: "text|example of escaped \| character|text" + * String split=splitIntoText( example );</pre> + * + * @param data Origional raw text as stored + * @return data split using | as seperator + * @throws DataSourceException if the information stored is inconsistent with the headered provided + */ + private String[] splitIntoText(String data) throws DataSourceException { + // return data.split("|", -1); // use -1 as a limit to include empty trailing spaces + // return data.split("[.-^\\\\]\\|",-1); //use -1 as limit to include empty trailing spaces + String split[] = new String[type.getAttributeCount()]; + int i = 0; + StringBuilder item = new StringBuilder(); + for (String str : data.split("\\|",-1)) { + if (i == type.getAttributeCount()) { + // limit reached + throw new DataSourceException("format error: expected " + text.length + + " attributes, stopped after finding " + i + ". [" + line + + "] split into " + Arrays.asList(text)); + } + if (str.endsWith("\\")) { +// String shorter = str.substring(0, str.length() - 1); +// item.append(shorter); + item.append(str); + item.append("|"); + } else { + item.append(str); + split[i] = item.toString(); + + i++; + item = new StringBuilder(); + } + } + if (i < type.getAttributeCount()) { + throw new DataSourceException("format error: expected " + type.getAttributeCount() + + " attributes, but only found " + i + ". [" + line + "] split into " + + Arrays.asList(text)); + } + return split; + } + /** * Retrieve the FeatureId identifying the current line. * @@ -281,18 +357,18 @@ AttributeDescriptor attType = type.getDescriptor(index); String stringValue = null; - boolean isEmpty = "".equals(stringValue); + //boolean isEmpty = "".equals(stringValue); try { - // read the value - stringValue = text[index]; - } catch (RuntimeException e1) { - e1.printStackTrace(); + // read the value and decode any interesting characters + stringValue = decodeString( text[index] ); + } catch (RuntimeException huh) { + huh.printStackTrace(); stringValue = null; } // check for special <null> flag if ("<null>".equals(stringValue)) { stringValue = null; - isEmpty = true; + // isEmpty = true; } if (stringValue == null) { if (attType.isNillable()) { Modified: trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeWriter.java =================================================================== --- trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeWriter.java 2012-05-01 18:57:46 UTC (rev 38698) +++ trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyAttributeWriter.java 2012-05-02 01:23:15 UTC (rev 38699) @@ -20,6 +20,9 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.regex.MatchResult; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.geotools.data.AttributeWriter; import org.geotools.data.DataUtilities; @@ -110,22 +113,42 @@ if (attribute == null) { writer.write("<null>"); // nothing! } else if( attribute instanceof String){ - // encode newlines - String txt = (String) attribute; - txt = txt.replace("\n", "\\n"); - txt = txt.replace("\r", "\\r"); - writer.write( txt ); + String txt = encodeString((String) attribute); + writer.write( txt ); } else if (attribute instanceof Geometry) { Geometry geometry = (Geometry) attribute; - writer.write( geometry.toText() ); + String txt = geometry.toText(); + + txt = encodeString( txt ); + writer.write( txt ); } else { String txt = Converters.convert( attribute, String.class ); if( txt == null ){ // could not convert? txt = attribute.toString(); } + txt = encodeString( txt ); writer.write( txt ); } } + + /** + * Used to encode common whitespace characters and | character for safe transport. + * + * @param txt + * @return txt encoded for storage + * @see PropertyAttributeReader#decodeString(String) + */ + String encodeString( String txt ){ + // encode our escaped characters + // txt = txt.replace("\\", "\\\\"); + txt = txt.replace("|","\\|"); + + // encode whitespace constants + txt = txt.replace("\n", "\\n"); + txt = txt.replace("\r", "\\r"); + + return txt; + } // write end // close start Modified: trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyFeatureWriter.java =================================================================== --- trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyFeatureWriter.java 2012-05-01 18:57:46 UTC (rev 38698) +++ trunk/modules/plugin/property/src/main/java/org/geotools/data/property/PropertyFeatureWriter.java 2012-05-02 01:23:15 UTC (rev 38699) @@ -105,6 +105,7 @@ // writeImplementation end // next start + long nextFid = System.currentTimeMillis(); // seed with a big number public SimpleFeature next() throws IOException { if (writer == null) { throw new IOException("Writer has been closed"); @@ -125,7 +126,7 @@ live = SimpleFeatureBuilder.copy(origional); return live; } else { - fid = type.getTypeName() + "." + System.currentTimeMillis(); + fid = type.getTypeName() + "." + (nextFid++); Object values[] = DataUtilities.defaultValues(type); origional = null; Modified: trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStore2Test.java =================================================================== --- trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStore2Test.java 2012-05-01 18:57:46 UTC (rev 38698) +++ trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStore2Test.java 2012-05-02 01:23:15 UTC (rev 38699) @@ -16,47 +16,72 @@ */ package org.geotools.data.property; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNotSame; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; -import junit.framework.TestCase; - -import org.geotools.data.DefaultQuery; +import org.geotools.data.DataUtilities; +import org.geotools.data.Query; +import org.geotools.data.collection.ListFeatureCollection; import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.data.simple.SimpleFeatureSource; +import org.geotools.data.simple.SimpleFeatureStore; +import org.geotools.factory.CommonFactoryFinder; +import org.geotools.factory.Hints; +import org.geotools.feature.simple.SimpleFeatureBuilder; +import org.geotools.geometry.jts.JTSFactoryFinder; import org.geotools.referencing.CRS; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.opengis.feature.Feature; +import org.opengis.feature.FeatureVisitor; import org.opengis.feature.Property; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.GeometryDescriptor; import org.opengis.feature.type.GeometryType; import org.opengis.filter.Filter; +import org.opengis.filter.FilterFactory2; import org.opengis.referencing.crs.CoordinateReferenceSystem; +import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; +import com.vividsolutions.jts.geom.GeometryFactory; +import com.vividsolutions.jts.geom.LineString; /** - * Test non functionality of PropertyDataStore. + * Test non functionality of PropertyDataStore (problems and enhancements requested through JIRA). * - * @author Jody Garnett, Refractions Research Inc. + * @author Jody Garnett (LISAsoft) * * * @source $URL$ */ -public class PropertyDataStore2Test extends TestCase { +public class PropertyDataStore2Test { PropertyDataStore store; PropertyDataStore sridStore; - /** - * Constructor for SimpleDataStoreTest. - * @param arg0 - */ - public PropertyDataStore2Test(String arg0) { - super(arg0); - } - protected void setUp() throws Exception { + + private PropertyDataStore unusalStore; + + @Before + public void setUp() throws Exception { File dir = new File(".", "propertyTestData" ); dir.mkdir(); @@ -93,24 +118,46 @@ writer2.close(); sridStore = new PropertyDataStore(dir2); - super.setUp(); + // Create a similar data store with various unusal problems + File dir3 = new File(".", "propertyTestData3"); + dir3.mkdir(); + File file3 = new File( dir3 ,"unusual.properties"); + if( file3.exists()){ + file3.delete(); + } + + BufferedWriter writer3 = new BufferedWriter( new FileWriter( file3 ) ); + writer3.write("_=id:Integer,*geom:Geometry,data:String"); writer3.newLine(); + writer3.write("fid1=1|LINESTRING(0 0,10 10)|feeling a bit \\|broken up"); writer3.newLine(); + writer3.write("fid2=2|\\\nLINESTRING(20 20,30 30)|\\\nnew line\\\ndiff friendly");writer3.newLine(); + writer3.close(); + unusalStore = new PropertyDataStore( dir3 ); + + // listFileContents( file3 ); } - protected void tearDown() throws Exception { + + @After + public void tearDown() throws Exception { + store.dispose(); File dir = new File( "propertyTestData" ); - File list[]=dir.listFiles(); - for( int i=0; i<list.length;i++){ - list[i].delete(); + for( File file : dir.listFiles()){ + file.delete(); } dir.delete(); - + + sridStore.dispose(); dir = new File( "propertyTestData2" ); - File list2[] = dir.listFiles(); - for( int i=0; i<list2.length;i++){ - list2[i].delete(); + for( File file : dir.listFiles()){ + file.delete(); } dir.delete(); - - super.tearDown(); + + unusalStore.dispose(); + dir = new File( "propertyTestData3" ); + for( File file : dir.listFiles()){ + file.delete(); + } + dir.delete(); } /** @@ -118,6 +165,7 @@ * * @throws Exception */ + @Test public void testCRS() throws Exception { SimpleFeatureSource road = sridStore.getFeatureSource("road2"); SimpleFeatureCollection features = road.getFeatures(); @@ -144,7 +192,37 @@ assertEquals(userData, geomType.getCoordinateReferenceSystem()); } } - + @Test + public void unusual() throws Exception { + SimpleFeatureSource road = unusalStore.getFeatureSource( "unusual" ); + assertEquals( 3, road.getSchema().getAttributeCount() ); + + SimpleFeatureCollection features = road.getFeatures(); + assertFalse( features.isEmpty() ); + + FilterFactory2 ff = CommonFactoryFinder.getFilterFactory2(); + + SimpleFeatureCollection select = road.getFeatures( ff.id( ff.featureId("fid1"))); + SimpleFeatureIterator iterator = select.features(); + SimpleFeature feature1 = iterator.next(); + assertNotNull( feature1 ); + iterator.close(); + + select = road.getFeatures( ff.id( ff.featureId("fid2"))); + iterator = select.features(); + SimpleFeature feature2 = iterator.next(); + assertNotNull( feature2 ); + iterator.close(); + + // Encode | + assertEquals("feeling a bit |broken up", feature1.getAttribute("data")); + + // Encode newline; but still respect trim of white space + assertTrue( feature2.getAttribute("geom") instanceof LineString ); + assertEquals("\nnew line\ndiff friendly", feature2.getAttribute("data")); + } + @Test + public void testSimple() throws Exception { SimpleFeatureSource road = store.getFeatureSource( "road" ); SimpleFeatureCollection features = road.getFeatures(); @@ -152,17 +230,19 @@ //assertEquals( 1, features.getFeatureType().getAttributeCount() ); assertEquals( 4, features.size() ); } + @Test + public void testQuery() throws Exception { SimpleFeatureSource road = store.getFeatureSource( "road" ); - DefaultQuery query = new DefaultQuery( "road", Filter.INCLUDE, + Query query = new Query( "road", Filter.INCLUDE, new String[]{ "name" } ); SimpleFeatureCollection features = road.getFeatures( query ); assertEquals( 4, features.size() ); //assertEquals( 1, features.getFeatureType().getAttributeCount() ); } - + @Test public void testQueryReproject() throws Exception { CoordinateReferenceSystem world = CRS.decode("EPSG:4326"); // world lon/lat CoordinateReferenceSystem local = CRS.decode("EPSG:3005"); // british columbia @@ -171,7 +251,7 @@ SimpleFeatureSource road = store.getFeatureSource( "road" ); SimpleFeatureType origionalType = road.getSchema(); - DefaultQuery query = new DefaultQuery( "road", Filter.INCLUDE, + Query query = new Query( "road", Filter.INCLUDE, new String[]{ "geom", "name" } ); query.setCoordinateSystem( local ); // FROM @@ -187,5 +267,96 @@ assertEquals( world, resultType.getCoordinateReferenceSystem() ); GeometryDescriptor geometryDescriptor = resultType.getGeometryDescriptor(); + assertTrue( Geometry.class.isAssignableFrom( geometryDescriptor.getType().getBinding() ) ); } + @Test + public void testUnusalRoundTrip() throws Throwable { + + File target = new File( "propertyTestData3/trip.properties" ); + if( target.exists() ){ + boolean deleted = target.delete(); + assertTrue( "unable to delete "+target.getAbsolutePath(), deleted ); + } + assertFalse( "trip.properties should not exist yet", target.exists() ); + + + SimpleFeatureType schema = DataUtilities.createType("trip", "point:Point::srid=4326,text:String, number:Integer"); + SimpleFeatureBuilder builder = new SimpleFeatureBuilder( schema ); + GeometryFactory gf = JTSFactoryFinder.getGeometryFactory(); + + List<SimpleFeature> list = new ArrayList<SimpleFeature>(); + SimpleFeature feature; + + feature = builder.buildFeature("trip1", new Object[]{gf.createPoint( new Coordinate(0,0)), "hello world", 1 }); + feature.getUserData().put( Hints.USE_PROVIDED_FID, true ); + list.add( feature); + + feature = builder.buildFeature("trip2", new Object[]{gf.createPoint( new Coordinate(0,0)), "test if | chracter handling", 2 }); + feature.getUserData().put( Hints.USE_PROVIDED_FID, true ); + list.add( feature ); + + feature= builder.buildFeature("trip3", new Object[]{gf.createPoint( new Coordinate(0,0)), "test of\n multi-line handling", 3 }); + feature.getUserData().put( Hints.USE_PROVIDED_FID, true ); + list.add( feature ); + + feature = builder.buildFeature("trip4", new Object[]{gf.createPoint( new Coordinate(0,0)), " test of\n whitespace handling", 4 }); + feature.getUserData().put( Hints.USE_PROVIDED_FID, true ); + list.add( feature ); + + feature = builder.buildFeature("trip5", new Object[]{gf.createPoint( new Coordinate(0,0)), "test encoding does not get confused over \\n newline and \\twhite space and \\| other markers", 5 }); + feature.getUserData().put( Hints.USE_PROVIDED_FID, true ); + list.add( feature ); + + feature = builder.buildFeature("trip6", new Object[]{gf.createPoint( new Coordinate(0,0)), "How well can we encode 1\\2?", 5 }); + feature.getUserData().put( Hints.USE_PROVIDED_FID, true ); + list.add( feature ); + + ListFeatureCollection features = new ListFeatureCollection(schema, list ); + + unusalStore.createSchema( schema ); + SimpleFeatureStore trip = (SimpleFeatureStore) unusalStore.getFeatureSource("trip"); + + trip.addFeatures( features ); + assertTrue( "trip.properties created", target.exists() ); + + // listFileContents(target); + + assertEquals("stored", list.size(), trip.getCount(Query.ALL)); + + final Map<String,SimpleFeature> cache = new HashMap<String,SimpleFeature>(); + SimpleFeatureCollection readFeatures = trip.getFeatures(); + + FeatureVisitor cacheResults = new FeatureVisitor() { + @Override + public void visit(Feature f) { + SimpleFeature feature = (SimpleFeature) f; + cache.put( feature.getID(), feature ); + } + }; + readFeatures.accepts( cacheResults, null ); + assertEquals( "restored", list.size(), cache.size() ); + assertEquals( "hello world", cache.get("trip1").getAttribute("text")); + assertEquals( "test if | chracter handling", cache.get("trip2").getAttribute("text")); + assertEquals( "test of\n multi-line handling", cache.get("trip3").getAttribute("text")); + assertEquals( " test of\n whitespace handling", cache.get("trip4").getAttribute("text")); + + // need some regex magic to make this work + //assertEquals( "test encoding does not get confused over \\n newline and \\twhite space and \\| other markers", cache.get("trip5").getAttribute("text")); + assertEquals( "How well can we encode 1\\2?", cache.get("trip6").getAttribute("text")); + } + + private void listFileContents(File target) throws FileNotFoundException, IOException { + System.out.println("Contents of "+target ); + if( target.exists() ){ + BufferedReader reader = new BufferedReader( new FileReader( target ) ); + String line; + while( (line = reader.readLine()) != null ){ + System.out.println( line ); + } + reader.close(); + } + else { + System.out.println(" ... does not exist"); + } + } } Modified: trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStoreTest.java =================================================================== --- trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStoreTest.java 2012-05-01 18:57:46 UTC (rev 38698) +++ trunk/modules/plugin/property/src/test/java/org/geotools/data/property/PropertyDataStoreTest.java 2012-05-02 01:23:15 UTC (rev 38699) @@ -25,12 +25,10 @@ import java.util.Collections; import java.util.List; import java.util.NoSuchElementException; -import java.util.Set; import junit.framework.TestCase; import org.geotools.data.DataUtilities; -import org.geotools.data.DefaultQuery; import org.geotools.data.DefaultTransaction; import org.geotools.data.FeatureReader; import org.geotools.data.FeatureWriter; @@ -43,7 +41,6 @@ import org.geotools.factory.CommonFactoryFinder; import org.geotools.factory.Hints; import org.geotools.feature.simple.SimpleFeatureBuilder; -import org.geotools.filter.identity.FeatureIdImpl; import org.opengis.feature.Feature; import org.opengis.feature.FeatureVisitor; import org.opengis.feature.IllegalAttributeException; @@ -55,497 +52,539 @@ import org.opengis.filter.identity.FeatureId; /** - * Test functioning of PropertyDataStore. + * Test functioning of PropertyDataStore (used as conformance testing and examples for the AbstractDataStore tutorial). * - * @author Jody Garnett, Refractions Research Inc. - * - * + * @author Jody Garnett (LISAsoft) + * * @source $URL$ */ public class PropertyDataStoreTest extends TestCase { PropertyDataStore store; - + static FilterFactory2 ff = (FilterFactory2) CommonFactoryFinder.getFilterFactory(null); /** * Constructor for SimpleDataStoreTest. + * * @param arg0 */ public PropertyDataStoreTest(String arg0) { super(arg0); } + protected void setUp() throws Exception { - File dir = new File(".", "propertyTestData" ); + File dir = new File(".", "propertyTestData"); dir.mkdir(); - - File file = new File( dir ,"road.properties"); - if( file.exists()){ + + File file = new File(dir, "road.properties"); + if (file.exists()) { file.delete(); - } - BufferedWriter writer = new BufferedWriter( new FileWriter( file ) ); - writer.write("_=id:Integer,name:String"); writer.newLine(); - writer.write("fid1=1|jody"); writer.newLine(); - writer.write("fid2=2|brent"); writer.newLine(); - writer.write("fid3=3|dave"); writer.newLine(); - writer.write("fid4=4|justin"); writer.newLine(); + } + BufferedWriter writer = new BufferedWriter(new FileWriter(file)); + writer.write("_=id:Integer,name:String"); + writer.newLine(); + writer.write("fid1=1|jody"); + writer.newLine(); + writer.write("fid2=2|brent"); + writer.newLine(); + writer.write("fid3=3|dave"); + writer.newLine(); + writer.write("fid4=4|justin"); + writer.newLine(); writer.write("fid5=5|"); writer.close(); - - file = new File( dir ,"dots.in.name.properties"); - if( file.exists()){ + + file = new File(dir, "dots.in.name.properties"); + if (file.exists()) { file.delete(); - } - writer = new BufferedWriter( new FileWriter( file ) ); - writer.write("_=id:Integer,name:String"); writer.newLine(); - writer.write("fid1=1|jody"); writer.newLine(); - writer.write("fid2=2|brent"); writer.newLine(); - writer.write("fid3=3|dave"); writer.newLine(); + } + writer = new BufferedWriter(new FileWriter(file)); + writer.write("_=id:Integer,name:String"); + writer.newLine(); + writer.write("fid1=1|jody"); + writer.newLine(); + writer.write("fid2=2|brent"); + writer.newLine(); + writer.write("fid3=3|dave"); + writer.newLine(); writer.write("fid4=4|justin"); writer.close(); - file = new File( dir ,"multiline.properties"); - if( file.exists()){ + file = new File(dir, "multiline.properties"); + if (file.exists()) { file.delete(); - } - writer = new BufferedWriter( new FileWriter( file ) ); - writer.write("_=id:Integer,name:String"); writer.newLine(); - writer.write("fid1=1|jody \\"); writer.newLine(); - writer.write(" garnett"); writer.newLine(); - writer.write("fid2=2|brent"); writer.newLine(); - writer.write("fid3=3|dave"); writer.newLine(); + } + writer = new BufferedWriter(new FileWriter(file)); + writer.write("_=id:Integer,name:String"); + writer.newLine(); + writer.write("fid1=1|jody \\"); + writer.newLine(); + writer.write(" garnett"); + writer.newLine(); + writer.write("fid2=2|brent"); + writer.newLine(); + writer.write("fid3=3|dave"); + writer.newLine(); writer.write("fid4=4|justin\\\n"); writer.close(); - file = new File( dir ,"table.properties"); - if( file.exists()){ + file = new File(dir, "table.properties"); + if (file.exists()) { file.delete(); - } - writer = new BufferedWriter( new FileWriter( file ) ); - writer.write("_=description:String,name:String"); writer.newLine(); - writer.write("GenericEntity.f004=description-f004|name-f004"); writer.newLine(); - writer.write("GenericEntity.f003=description-f003|<null>"); writer.newLine(); - writer.write("GenericEntity.f007=description-f007|"); writer.newLine(); - writer.write(" GenericEntity.f009=description-f009| "); writer.newLine(); + } + writer = new BufferedWriter(new FileWriter(file)); + writer.write("_=description:String,name:String"); + writer.newLine(); + writer.write("GenericEntity.f004=description-f004|name-f004"); + writer.newLine(); + writer.write("GenericEntity.f003=description-f003|<null>"); + writer.newLine(); + writer.write("GenericEntity.f007=description-f007|"); + writer.newLine(); + writer.write(" GenericEntity.f009=description-f009| "); + writer.newLine(); writer.close(); - - store = new PropertyDataStore( dir ); + + store = new PropertyDataStore(dir); super.setUp(); } + protected void tearDown() throws Exception { - File dir = new File( "propertyTestData" ); - File list[]=dir.listFiles(); - for( int i=0; i<list.length;i++){ + File dir = new File("propertyTestData"); + File list[] = dir.listFiles(); + for (int i = 0; i < list.length; i++) { list[i].delete(); } dir.delete(); - super.tearDown(); + super.tearDown(); } public void testGetNames() { String names[] = store.getTypeNames(); Arrays.sort(names); - assertEquals( 4, names.length ); - assertEquals( "dots.in.name", names[0] ); - assertEquals( "multiline", names[1] ); - assertEquals( "road", names[2] ); - assertEquals( "table", names[3] ); + assertEquals(4, names.length); + assertEquals("dots.in.name", names[0]); + assertEquals("multiline", names[1]); + assertEquals("road", names[2]); + assertEquals("table", names[3]); } public void testGetSchema() throws IOException { - SimpleFeatureType type = store.getSchema( "road" ); - assertNotNull( type ); - assertEquals( "road", type.getTypeName() ); - assertEquals( "propertyTestData", type.getName().getNamespaceURI().toString() ); - assertEquals( 2, type.getAttributeCount() ); - - AttributeDescriptor id = type.getDescriptor(0); + SimpleFeatureType type = store.getSchema("road"); + assertNotNull(type); + assertEquals("road", type.getTypeName()); + assertEquals("propertyTestData", type.getName().getNamespaceURI().toString()); + assertEquals(2, type.getAttributeCount()); + + AttributeDescriptor id = type.getDescriptor(0); AttributeDescriptor name = type.getDescriptor(1); - - assertEquals( "id", id.getLocalName() ); - assertEquals( "class java.lang.Integer", id.getType().getBinding().toString() ); - - assertEquals( "name", name.getLocalName() ); - assertEquals( "class java.lang.String", name.getType().getBinding().toString() ); + + assertEquals("id", id.getLocalName()); + assertEquals("class java.lang.Integer", id.getType().getBinding().toString()); + + assertEquals("name", name.getLocalName()); + assertEquals("class java.lang.String", name.getType().getBinding().toString()); } + public void testGetFeaturesFeatureTypeFilterTransaction1() throws Exception { - SimpleFeatureType type = store.getSchema( "road" ); - Query roadQuery = new DefaultQuery("road"); - FeatureReader<SimpleFeatureType, SimpleFeature> reader = store.getFeatureReader( roadQuery, Transaction.AUTO_COMMIT ); + Query roadQuery = new Query("road"); + FeatureReader<SimpleFeatureType, SimpleFeature> reader = store.getFeatureReader(roadQuery, + Transaction.AUTO_COMMIT); int count = 0; try { - while( reader.hasNext() ){ + while (reader.hasNext()) { reader.next(); count++; } - } - finally { + } finally { reader.close(); } - assertEquals( 5, count ); - + assertEquals(5, count); + Filter selectFid1; - - selectFid1 = ff.id( Collections.singleton( ff.featureId("fid1") ) ); - reader = store.getFeatureReader( new DefaultQuery("road", selectFid1 ), Transaction.AUTO_COMMIT ); - assertEquals( 1, count( reader ) ); - + + selectFid1 = ff.id(Collections.singleton(ff.featureId("fid1"))); + reader = store.getFeatureReader(new Query("road", selectFid1), Transaction.AUTO_COMMIT); + assertEquals(1, count(reader)); + Transaction transaction = new DefaultTransaction(); - reader = store.getFeatureReader( roadQuery, transaction ); - assertEquals( 5, count( reader )); - - reader = store.getFeatureReader( roadQuery, transaction ); - List list = new ArrayList(); + reader = store.getFeatureReader(roadQuery, transaction); + assertEquals(5, count(reader)); + + reader = store.getFeatureReader(roadQuery, transaction); + List<String> list = new ArrayList<String>(); try { - while( reader.hasNext() ){ - list.add( reader.next().getID() ); + while (reader.hasNext()) { + list.add(reader.next().getID()); } - } - finally { + } finally { reader.close(); } - assertEquals( "[fid1, fid2, fid3, fid4, fid5]", list.toString() ); + assertEquals("[fid1, fid2, fid3, fid4, fid5]", list.toString()); } + /* - * Test for FeatureReader<SimpleFeatureType, SimpleFeature> getFeatureReader(String) + * Test for FeatureReader<SimpleFeatureType, SimpleFeature> getFeatureReader(String) */ - public void testGetFeatureReaderString() throws NoSuchElementException, IOException, IllegalAttributeException { - FeatureReader<SimpleFeatureType, SimpleFeature> reader = store.getFeatureReader("road"); + public void testGetFeatureReaderString() throws NoSuchElementException, IOException, + IllegalAttributeException { + FeatureReader<SimpleFeatureType, SimpleFeature> reader = store.getFeatureReader("road"); int count = 0; try { - while( reader.hasNext() ){ - reader.next(); + while (reader.hasNext()) { + reader.next(); count++; } - } - finally { + } finally { reader.close(); } - assertEquals( 5, count ); + assertEquals(5, count); } - private int count( FeatureReader<SimpleFeatureType, SimpleFeature> reader ) throws Exception { + + private int count(FeatureReader<SimpleFeatureType, SimpleFeature> reader) throws Exception { int count = 0; try { - while( reader.hasNext() ){ + while (reader.hasNext()) { reader.next(); count++; } - } - finally { + } finally { reader.close(); } - return count; - } - private int count( String typeName ) throws Exception { - return count( store.getFeatureReader( typeName ) ); + return count; } - + + private int count(String typeName) throws Exception { + return count(store.getFeatureReader(typeName)); + } + public void testWriterSkipThrough() throws Exception { - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); - + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); + File in = writer.read; File out = writer.write; - + int count = 0; - while( writer.hasNext() ){ + while (writer.hasNext()) { writer.next(); count++; } - assertEquals( 5, count ); - assertTrue( in.exists() ); - assertTrue( out.exists() ); + assertEquals(5, count); + assertTrue(in.exists()); + assertTrue(out.exists()); writer.close(); - assertTrue( in.exists() ); - - assertEquals( 5, count( "road" ) ); + assertTrue(in.exists()); + + assertEquals(5, count("road")); } - public void testWriterChangeName() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); - + + public void testWriterChangeName() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); + int count = 0; - while( writer.hasNext() ){ + while (writer.hasNext()) { SimpleFeature f = writer.next(); - f.setAttribute(1,"name "+(count+1)); + f.setAttribute(1, "name " + (count + 1)); writer.write(); count++; - } - writer.close(); - assertEquals( 5, count ); - assertEquals( 5, count( "road" )); + } + writer.close(); + assertEquals(5, count); + assertEquals(5, count("road")); } - public void testWriterChangeFirstName() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); + + public void testWriterChangeFirstName() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); SimpleFeature f; f = writer.next(); - f.setAttribute(1,"changed"); + f.setAttribute(1, "changed"); writer.write(); - writer.close(); - assertEquals( 5, count( "road" )); + writer.close(); + assertEquals(5, count("road")); } - public void testWriterChangeLastName() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); + + public void testWriterChangeLastName() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); SimpleFeature f; writer.next(); writer.next(); - writer.next(); + writer.next(); f = writer.next(); - f.setAttribute(1,"changed"); + f.setAttribute(1, "changed"); writer.write(); - writer.close(); - assertEquals( 5, count( "road" )); - } - public void testWriterChangeAppend() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); + writer.close(); + assertEquals(5, count("road")); + } + + public void testWriterChangeAppend() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); SimpleFeature f; writer.next(); writer.next(); writer.next(); writer.next(); writer.next(); - assertFalse( writer.hasNext() ); + assertFalse(writer.hasNext()); f = writer.next(); - assertNotNull( f ); - f.setAttribute(0,new Integer(-1)); - f.setAttribute(1,"new"); + assertNotNull(f); + f.setAttribute(0, new Integer(-1)); + f.setAttribute(1, "new"); writer.write(); writer.close(); - assertEquals( 6, count( "road" )); + assertEquals(6, count("road")); } - public void testWriterAppendLastNull() throws Exception{ - FeatureWriter<SimpleFeatureType, SimpleFeature> writer = (FeatureWriter) - store.getFeatureWriterAppend("road", Transaction.AUTO_COMMIT); + + public void testWriterAppendLastNull() throws Exception { + FeatureWriter<SimpleFeatureType, SimpleFeature> writer = store + .getFeatureWriterAppend("road", Transaction.AUTO_COMMIT); SimpleFeature f; - assertFalse( writer.hasNext() ); + assertFalse(writer.hasNext()); f = writer.next(); - assertNotNull( f ); - f.setAttribute(0,new Integer(-1)); - f.setAttribute(1,null); // this made the datastore break + assertNotNull(f); + f.setAttribute(0, new Integer(-1)); + f.setAttribute(1, null); // this made the datastore break writer.write(); writer.close(); - assertEquals( 6, count( "road" )); + assertEquals(6, count("road")); } - public void testWriterChangeRemoveFirst() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); - + + public void testWriterChangeRemoveFirst() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); + writer.next(); writer.remove(); writer.close(); - assertEquals( 4, count( "road" )); + assertEquals(4, count("road")); } - public void testWriterChangeRemoveLast() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); - + + public void testWriterChangeRemoveLast() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); + writer.next(); writer.next(); writer.next(); writer.remove(); writer.close(); - assertEquals( 4, count( "road" )); + assertEquals(4, count("road")); } - public void testWriterChangeRemoveAppend() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); + + public void testWriterChangeRemoveAppend() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); SimpleFeature f; writer.next(); writer.next(); writer.next(); - writer.next(); - writer.next(); - - assertFalse( writer.hasNext() ); + writer.next(); + writer.next(); + + assertFalse(writer.hasNext()); f = writer.next(); - assertNotNull( f ); - f.setAttribute(0,new Integer(-1)); - f.setAttribute(1,"new"); + assertNotNull(f); + f.setAttribute(0, new Integer(-1)); + f.setAttribute(1, "new"); writer.remove(); writer.close(); - assertEquals( 5, count( "road" )); + assertEquals(5, count("road")); } - public void testWriterChangeIgnoreAppend() throws Exception{ - PropertyFeatureWriter writer = (PropertyFeatureWriter) - store.createFeatureWriter("road",Transaction.AUTO_COMMIT); + + public void testWriterChangeIgnoreAppend() throws Exception { + PropertyFeatureWriter writer = (PropertyFeatureWriter) store.createFeatureWriter("road", + Transaction.AUTO_COMMIT); SimpleFeature f; writer.next(); writer.next(); writer.next(); writer.next(); writer.next(); - assertFalse( writer.hasNext() ); + assertFalse(writer.hasNext()); f = writer.next(); - assertNotNull( f ); - f.setAttribute(0,new Integer(-1)); - f.setAttribute(1,"new"); + assertNotNull(f); + f.setAttribute(0, new Integer(-1)); + f.setAttribute(1, "new"); writer.close(); - assertEquals( 5, count( "road" )); + assertEquals(5, count("road")); } - + public void testGetFeatureSource() throws Exception { - SimpleFeatureSource road = store.getFeatureSource( "road" ); + SimpleFeatureSource road = store.getFeatureSource("road"); SimpleFeatureCollection features = road.getFeatures(); SimpleFeatureIterator reader = features.features(); - List list = new ArrayList(); + List<String> list = new ArrayList<String>(); try { - while( reader.hasNext() ){ - list.add( reader.next().getID() ); + while (reader.hasNext()) { + list.add(reader.next().getID()); } } finally { reader.close(); } - assertEquals( "[fid1, fid2, fid3, fid4, fid5]", list.toString() ); - assertEquals( 5, road.getCount(Query.ALL) ); - assertTrue( road.getBounds(Query.ALL).isNull() ); - assertEquals( 5, features.size() ); - assertTrue( features.getBounds().isNull() ); - assertEquals( 5, features.size() ); - + assertEquals("[fid1, fid2, fid3, fid4, fid5]", list.toString()); + assertEquals(5, road.getCount(Query.ALL)); + assertTrue(road.getBounds(Query.ALL).isNull()); + assertEquals(5, features.size()); + assertTrue(features.getBounds().isNull()); + assertEquals(5, features.size()); + } /** - * In response to <a - * href="https://jira.codehaus.org/browse/GEOT-1409">GEOT-1409 Property - * datastore ruins the property file if a string attribute has newlines</a>. + * In response to <a href="https://jira.codehaus.org/browse/GEOT-1409">GEOT-1409 Property datastore ruins the property file if a string attribute + * has newlines</a>. * * @throws Exception */ public void testMultiLine() throws Exception { - SimpleFeatureSource road = store.getFeatureSource( "multiline" ); + SimpleFeatureSource road = store.getFeatureSource("multiline"); FeatureId fid1 = ff.featureId("fid1"); - Filter select = ff.id( Collections.singleton(fid1)); - SimpleFeatureCollection featureCollection = road.getFeatures( select ); + Filter select = ff.id(Collections.singleton(fid1)); + SimpleFeatureCollection featureCollection = road.getFeatures(select); featureCollection.accepts(new FeatureVisitor() { public void visit(Feature f) { SimpleFeature feature = (SimpleFeature) f; String name = (String) feature.getAttribute("name"); - assertEquals( "jody \ngarnett", name ); + assertEquals("jody \ngarnett", name); } - },null); + }, null); } /** - * In response to <a - * href="http://jira.codehaus.org/browse/GEOT-3540">GEOT-3540 - * PropertyDataStore doesn't support empty trailing spaces</a>. + * In response to <a href="http://jira.codehaus.org/browse/GEOT-3540">GEOT-3540 PropertyDataStore doesn't support empty trailing spaces</a>. * <p> * Table with no geoemtry, containing null and empty strings at end of line * </p> * * @throws Exception */ - public void testTable() throws Exception{ - SimpleFeatureSource table = store.getFeatureSource( "table" ); - //GenericEntity.f004=description-f004|name-f004 + public void testTable() throws Exception { + SimpleFeatureSource table = store.getFeatureSource("table"); + // GenericEntity.f004=description-f004|name-f004 FeatureId fid1 = ff.featureId("GenericEntity.f004"); - Filter select = ff.id( Collections.singleton(fid1)); - SimpleFeatureCollection featureCollection = table.getFeatures( select ); + Filter select = ff.id(Collections.singleton(fid1)); + SimpleFeatureCollection featureCollection = table.getFeatures(select); featureCollection.accepts(new FeatureVisitor() { public void visit(Feature f) { SimpleFeature feature = (SimpleFeature) f; String name = (String) feature.getAttribute("name"); - assertEquals( "name-f004", name ); + assertEquals("name-f004", name); } - },null); - //GenericEntity.f003=description-f003|<null> + }, null); + // GenericEntity.f003=description-f003|<null> fid1 = ff.featureId("GenericEntity.f003"); - select = ff.id( Collections.singleton(fid1)); - featureCollection = table.getFeatures( select ); + select = ff.id(Collections.singleton(fid1)); + featureCollection = table.getFeatures(select); featureCollection.accepts(new FeatureVisitor() { public void visit(Feature f) { SimpleFeature feature = (SimpleFeature) f; String name = (String) feature.getAttribute("name"); - System.out.println( name ); - assertNull( "represent null", name ); + System.out.println(name); + assertNull("represent null", name); } - },null); - //GenericEntity.f007=description-f007| + }, null); + // GenericEntity.f007=description-f007| fid1 = ff.featureId("GenericEntity.f007"); - select = ff.id( Collections.singleton(fid1)); - featureCollection = table.getFeatures( select ); + select = ff.id(Collections.singleton(fid1)); + featureCollection = table.getFeatures(select); featureCollection.accepts(new FeatureVisitor() { public void visit(Feature f) { SimpleFeature feature = (SimpleFeature) f; String name = (String) feature.getAttribute("name"); - assertEquals( "represent empty string", "", name ); + assertEquals("represent empty string", "", name); } - },null); - //" GenericEntity.f009=description-f009| " + }, null); + // " GenericEntity.f009=description-f009| " fid1 = ff.featureId("GenericEntity.f009"); - select = ff.id( Collections.singleton(fid1)); - featureCollection = table.getFeatures( select ); + select = ff.id(Collections.singleton(fid1)); + featureCollection = table.getFeatures(select); featureCollection.accepts(new FeatureVisitor() { public void visit(Feature f) { SimpleFeature feature = (SimpleFeature) f; String name = (String) feature.getAttribute("name"); - assertEquals( "represent empty string", " ", name ); + assertEquals("represent empty string", " ", name); } - },null); + }, null); } + public void testTransactionIndependence() throws Exception { - SimpleFeatureType ROAD = store.getSchema( "road" ); - SimpleFeature chrisFeature = - SimpleFeatureBuilder.build(ROAD, new Object[]{ new Integer(5), "chris"}, "fid5" ); - + SimpleFeatureType ROAD = store.getSchema("road"); + SimpleFeature chrisFeature = SimpleFeatureBuilder.build(ROAD, new Object[] { + new Integer(5), "chris" }, "fid5"); + SimpleFeatureStore roadAuto = (SimpleFeatureStore) store.getFeatureSource("road"); - + SimpleFeatureStore roadFromClient1 = (SimpleFeatureStore) store.getFeatureSource("road"); Transaction transaction1 = new DefaultTransaction("Transaction Used by Client 1"); - roadFromClient1.setTransaction( transaction1 ); - + roadFromClient1.setTransaction(transaction1); + SimpleFeatureStore roadFromClient2 = (SimpleFeatureStore) store.getFeatureSource("road"); Transaction transaction2 = new DefaultTransaction("Transaction Used by Client 2"); - roadFromClient2.setTransaction( transaction2 ); + roadFromClient2.setTransaction(transaction2); FilterFactory2 ff = (FilterFactory2) CommonFactoryFinder.getFilterFactory(null); - Filter selectFid1 = ff.id( Collections.singleton( ff.featureId("fid1") )); - + Filter selectFid1 = ff.id(Collections.singleton(ff.featureId("fid1"))); + // Before we edit everything should be the same - assertEquals( "auto before", 5, roadAuto.getFeatures().size() ); - assertEquals( "client 1 before", 5, roadFromClient1.getFeatures().size() ); - assertEquals( "client 2 before", 5, roadFromClient2.getFeatures().size() ); + assertEquals("auto before", 5, roadAuto.getFeatures().size()); + assertEquals("client 1 before", 5, roadFromClient1.getFeatures().size()); + assertEquals("client 2 before", 5, roadFromClient2.getFeatures().size()); // Remove Feature with Fid1 - roadFromClient1.removeFeatures( selectFid1 ); // road1 removes fid1 on t1 - - assertEquals( "auto after client 1 removes fid1", 5, roadAuto.getFeatures().size() ); - assertEquals( "client 1 after client 1 removes fid1", 4, roadFromClient1.getFeatures().size() ); - assertEquals( "client 2 after client 1 removes fid1", 5, roadFromClient2.getFeatures().size() ); - - roadFromClient2.addFeatures( DataUtilities.collection( chrisFeature )); // road2 adds fid5 on t2 - assertEquals( "auto after client 1 removes fid1 and client 2 adds fid5", 5, roadAuto.getFeatures().size() ); - assertEquals( "client 1 after client 1 removes fid1 and client 2 adds fid5", 4, roadFromClient1.getFeatures().size() ); - assertEquals( "cleint 2 after client 1 removes fid1 and client 2 adds fid5", 6, roadFromClient2.getFeatures().size() ); + roadFromClient1.removeFeatures(selectFid1); // road1 removes fid1 on t1 + assertEquals("auto after client 1 removes fid1", 5, roadAuto.getFeatures().size()); + assertEquals("client 1 after client 1 removes fid1", 4, roadFromClient1.getFeatures() + .size()); + assertEquals("client 2 after client 1 removes fid1", 5, roadFromClient2.getFeatures() + .size()); + + roadFromClient2.addFeatures(DataUtilities.collection(chrisFeature)); // road2 adds fid5 on t2 + assertEquals("auto after client 1 removes fid1 and client 2 adds fid5", 5, roadAuto + .getFeatures().size()); + assertEquals("client 1 after client 1 removes fid1 and client 2 adds fid5", 4, + roadFromClient1.getFeatures().size()); + assertEquals("cleint 2 after client 1 removes fid1 and client 2 adds fid5", 6, + roadFromClient2.getFeatures().size()); + transaction1.commit(); - assertEquals( "auto after client 1 commits removal of fid1 (client 2 has added fid5)", 4, roadAuto.getFeatures().size() ); - assertEquals( "client 1 after commiting removal of fid1 (client 2 has added fid5)", 4, roadFromClient1.getFeatures().size() ); - assertEquals( "client 2 after client 1 commits removal of fid1 (client 2 has added fid5)", 5, roadFromClient2.getFeatures().size() ); - + assertEquals("auto after client 1 commits removal of fid1 (client 2 has added fid5)", 4, + roadAuto.getFeatures().size()); + assertEquals("client 1 after commiting removal of fid1 (client 2 has added fid5)", 4, + roadFromClient1.getFeatures().size()); + assertEquals("client 2 after client 1 commits removal of fid1 (client 2 has added fid5)", + 5, roadFromClient2.getFeatures().size()); + transaction2.commit(); - assertEquals( "auto after client 2 commits addition of fid5 (fid1 previously removed)", 5, roadAuto.getFeatures().size() ); - assertEquals( "client 1 after client 2 commits addition of fid5 (fid1 previously removed)", 5, roadFromClient1.getFeatures().size() ); - assertEquals( "client 2 after commiting addition of fid5 (fid1 previously removed)", 5, roadFromClient2.getFeatures().size() ); + assertEquals("auto after client 2 commits addition of fid5 (fid1 previously removed)", 5, + roadAuto.getFeatures().size()); + assertEquals("client 1 after client 2 commits addition of fid5 (fid1 previously removed)", + 5, roadFromClient1.getFeatures().size()); + assertEquals("client 2 after commiting addition of fid5 (fid1 previously removed)", 5, + roadFromClient2.getFeatures().size()); } - + public void testUseExistingFid() throws Exception { - SimpleFeatureType ROAD = store.getSchema( "road" ); - SimpleFeature chrisFeature = SimpleFeatureBuilder.build(ROAD, new Object[]{ new Integer(5), "chris"}, "fid5" ); + SimpleFeatureType ROAD = store.getSchema("road"); + SimpleFeature chrisFeature = SimpleFeatureBuilder.build(ROAD, new Object[] { + new Integer(5), "chris" }, "fid5"); chrisFeature.getUserData().put(Hints.USE_PROVIDED_FID, Boolean.TRUE); - + SimpleFeatureStore roadAuto = (SimpleFeatureStore) store.getFeatureSource("road"); List<FeatureId> fids = roadAuto.addFeatures(DataUtilities.collection(chrisFeature)); - + // checke the id was preserved assertEquals(1, fids.size()); FeatureId fid = SimpleFeatureBuilder.createDefaultFeatureIdentifier("fid5"); assertTrue(fids.contains(fid)); - + // manually check the feature with the proper id is actually there - SimpleFeatureIterator it = roadAuto.getFeatures(ff.id(Collections.singleton(fid))).features(); + SimpleFeatureIterator it = roadAuto.getFeatu... [truncated message content] |
From: <svn...@os...> - 2012-05-01 18:57:55
|
Author: jdeolive Date: 2012-05-01 11:57:46 -0700 (Tue, 01 May 2012) New Revision: 38698 Modified: trunk/docs/src/main/java/org/geotools/jdbc/JDBCExamples.java trunk/docs/user/library/jdbc/datastore.rst trunk/docs/user/library/jdbc/h2.rst trunk/docs/user/library/jdbc/postgis.rst trunk/docs/user/library/jdbc/spatiallite.rst Log: some tweaks to jdbc documentation, pointing at correct code samples Modified: trunk/docs/src/main/java/org/geotools/jdbc/JDBCExamples.java =================================================================== --- trunk/docs/src/main/java/org/geotools/jdbc/JDBCExamples.java 2012-05-01 10:03:00 UTC (rev 38697) +++ trunk/docs/src/main/java/org/geotools/jdbc/JDBCExamples.java 2012-05-01 18:57:46 UTC (rev 38698) @@ -19,6 +19,30 @@ // h2Example end } +void h2AbsPathExample() throws IOException { + // h2AbsPathExample start + Map<String,Object> params = new HashMap<String,Object>(); + params.put("dbtype", "h2"); + params.put("database", "/abs/path/to/geotools"); + + DataStore datastore = DataStoreFinder.getDataStore(params); + // h2AbsPathExample end +} + +void h2TcpExample() throws IOException { + // h2TcpExample start + Map<String,Object> params = new HashMap<String,Object>(); + params.put("dbtype", "h2"); + params.put("host", "localhost"); + params.put("port", 9902); + params.put("database", "geotools"); + params.put("passwd", "geotools"); + params.put("passwd", "geotools"); + + DataStore datastore = DataStoreFinder.getDataStore(params); + // h2TcpExample end +} + void postgisExample() throws IOException { // postgisExample start Map<String,Object> params = new HashMap<String,Object>(); Modified: trunk/docs/user/library/jdbc/datastore.rst =================================================================== --- trunk/docs/user/library/jdbc/datastore.rst 2012-05-01 10:03:00 UTC (rev 38697) +++ trunk/docs/user/library/jdbc/datastore.rst 2012-05-01 18:57:46 UTC (rev 38698) @@ -10,7 +10,7 @@ The process of creating a JDBC data store follows the regular steps of creating any type of datastore. That is defining the parameters to connect to the database in a map, and then creating the data store factory.: -.. literalinclude:: /../src/main/java/org/geotools/data/SimpleFeatureStoreExamples.java +.. literalinclude:: /../src/main/java/org/geotools/jdbc/JDBCExamples.java :language: java :start-after: // postgisExample start :end-before: // postgisExample end Modified: trunk/docs/user/library/jdbc/h2.rst =================================================================== --- trunk/docs/user/library/jdbc/h2.rst 2012-05-01 10:03:00 UTC (rev 38697) +++ trunk/docs/user/library/jdbc/h2.rst 2012-05-01 18:57:46 UTC (rev 38698) @@ -36,7 +36,26 @@ Here is a quick example: -.. literalinclude:: /../src/main/java/org/geotools/data/SimpleFeatureStoreExamples.java +.. literalinclude:: /../src/main/java/org/geotools/jdbc/JDBCExamples.java :language: java :start-after: // h2Example start :end-before: // h2Example end + +The above will reference a database file named "geotools" located in the current working directory. +A full path may also be specified: + +.. literalinclude:: /../src/main/java/org/geotools/jdbc/JDBCExamples.java + :language: java + :start-after: // h2AbsPathExample start + :end-before: // h2AbsPathExample end + +The above examples create a connection to H2 in "embedded" mode. One limitation to this approach is +that it only allows for a single java process to access the database at any one time. H2 also offers +a `server mode <http://www.h2database.com/html/tutorial.html#using_server>`_ in which access +to the underlying database is made via traditional client-server TCP connection, and removes the embedded +single process restriction: + +.. literalinclude:: /../src/main/java/org/geotools/jdbc/JDBCExamples.java + :language: java + :start-after: // h2TcpExample start + :end-before: // h2TcpExample end Modified: trunk/docs/user/library/jdbc/postgis.rst =================================================================== --- trunk/docs/user/library/jdbc/postgis.rst 2012-05-01 10:03:00 UTC (rev 38697) +++ trunk/docs/user/library/jdbc/postgis.rst 2012-05-01 18:57:46 UTC (rev 38698) @@ -41,7 +41,7 @@ Connect using DataStore finder: -.. literalinclude:: /../src/main/java/org/geotools/data/SimpleFeatureStoreExamples.java +.. literalinclude:: /../src/main/java/org/geotools/jdbc/JDBCExamples.java :language: java :start-after: // postgisExample start :end-before: // postgisExample end Modified: trunk/docs/user/library/jdbc/spatiallite.rst =================================================================== --- trunk/docs/user/library/jdbc/spatiallite.rst 2012-05-01 10:03:00 UTC (rev 38697) +++ trunk/docs/user/library/jdbc/spatiallite.rst 2012-05-01 18:57:46 UTC (rev 38698) @@ -55,9 +55,24 @@ * Native Libraries - The SpatiaLite data store requires the native libraries for SQLite - and SpatiaLite to be installed on the system. Precompiled libraries for - SQLite and SpatiaLite are available. + The SpatiaLite datastore ships with its own build of the SQLite and SpatiaLite + libraries. The SpatiaLite component has been compiled with GEOS and PROJ support + so those libraries need to be installed on the system for the datastore to + function. Binaries for a variety of platforms are available at https://www.gaia-gis.it/fossil/libspatialite/index. + + See also: - * http://www.sqlite.org/download.html - * http://www.gaia-gis.it/spatialite/binaries.html + * http://trac.osgeo.org/proj/ + * http://trac.osgeo.org/geos/ + +* Java Environment + + In order to load the native libraries at runtime Java must be told where the libraries live + with a system property named "java.library.path". This is specified during java startup:: + + java -Djava.library.path=/usr/local/lib ... + + Depending on how the O/S is configured the additional ``LD_LIBRARY_PATH`` (unix/linux) and + ``DYLD_LIBRARY_PATH`` (osx) environment variables may need to be set. + + |
From: <svn...@os...> - 2012-05-01 10:03:07
|
Author: ang05a Date: 2012-05-01 03:03:00 -0700 (Tue, 01 May 2012) New Revision: 38697 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/FeatureTypeMapping.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java Log: App-schema isList experimental/temporary solution to subsetting timeseries via filters. 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-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/DataAccessMappingFeatureIterator.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -61,6 +61,7 @@ import org.opengis.feature.type.AttributeType; import org.opengis.feature.type.FeatureType; import org.opengis.feature.type.Name; +import org.opengis.filter.Filter; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.PropertyName; import org.opengis.filter.identity.FeatureId; @@ -118,7 +119,13 @@ private boolean isFiltered = false; private ArrayList<String> filteredFeatures; + /** + * Temporary/experimental changes for enabling subsetting for isList only. + */ + private Filter listFilter; + private List<StepList> listFilterProperties; + public DataAccessMappingFeatureIterator(AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, boolean isFiltered) throws IOException { this(store, mapping, query, null); @@ -821,14 +828,28 @@ Attribute instance = setAttributeValue(target, null, sources.get(0), attMapping, null, null, selectedProperties.get(attMapping)); if (sources.size() > 1 && instance != null) { - Object[] values = new Object[sources.size()]; + List<Object> values = new ArrayList<Object>(); Expression sourceExpr = attMapping.getSourceExpression(); - int i = 0; - for (Feature source : sources) { - values[i] = getValue(sourceExpr, source); - i++; + if (listFilter != null + && listFilterProperties.contains(attMapping.getTargetXPath())) { + for (Feature source : sources) { + // HACK HACK HACK + // evaluate filter that applies to this list as we want a subset + // instead of full result + // this is a temporary solution for Bureau of Meteorology + // requirement for timePositionList + if (listFilter.evaluate(source)) { + // only add to subset if filter matches value + values.add(getValue(sourceExpr, source)); + } + } + } else { + // no filter concerning the list + for (Feature source : sources) { + values.add(getValue(sourceExpr, source)); + } } - String valueString = StringUtils.join(values, " "); + String valueString = StringUtils.join(values.iterator(), " "); StepList fullPath = attMapping.getTargetXPath(); StepList leafPath = fullPath.subList(fullPath.size() - 1, fullPath.size()); if (instance instanceof ComplexAttributeImpl) { @@ -954,6 +975,8 @@ sourceFeatureIterator = null; sourceFeatures = null; filteredFeatures = null; + listFilterProperties = null; + listFilter = null; //NC - joining nested atts for (AttributeMapping attMapping : selectedMapping) { @@ -1085,4 +1108,12 @@ public boolean isReprojectionCrsEqual(CoordinateReferenceSystem source,CoordinateReferenceSystem target) { return CRS.equalsIgnoreMetadata(source,target); } + + public void setListFilter(Filter filter) { + listFilter = filter; + } + + public void setListFilterProperties(List<StepList> properties) { + listFilterProperties = properties; + } } Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java 2012-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/FeatureTypeMapping.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -223,11 +223,24 @@ public Name getMappingName() { return mappingName; } - - - - + /** + * Return list of attribute mappings that are configured as list (isList = true). + * @return attribute mappings with isList enabled. + */ + public List<AttributeMapping> getIsListMappings() { + List<AttributeMapping> mappings = new ArrayList<AttributeMapping>(); + AttributeMapping attMapping; + for (Iterator<AttributeMapping> it = attributeMappings.iterator(); it.hasNext();) { + attMapping = (AttributeMapping) it.next(); + if (attMapping.isList()) { + mappings.add(attMapping); + } + } + return mappings; + } + + /** * Looks up for attribute mappings matching the xpath expression <code>propertyName</code>. * <p> * If any step in <code>propertyName</code> has index greater than 1, any mapping for the same Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java 2012-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/MappingFeatureIteratorFactory.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -18,23 +18,28 @@ package org.geotools.data.complex; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Logger; import org.geotools.data.FeatureSource; import org.geotools.data.Query; import org.geotools.data.complex.config.AppSchemaDataAccessConfigurator; import org.geotools.data.complex.filter.ComplexFilterSplitter; +import org.geotools.data.complex.filter.XPath; +import org.geotools.data.complex.filter.XPath.StepList; import org.geotools.data.joining.JoiningQuery; import org.geotools.feature.Types; import org.geotools.filter.FidFilterImpl; import org.geotools.filter.FilterCapabilities; -import org.geotools.filter.NestedAttributeExpression; import org.geotools.filter.visitor.DefaultFilterVisitor; import org.geotools.jdbc.JDBCFeatureSource; import org.geotools.jdbc.JDBCFeatureStore; +import org.opengis.feature.type.AttributeDescriptor; import org.opengis.filter.Filter; import org.opengis.filter.expression.PropertyName; import org.opengis.referencing.crs.CoordinateReferenceSystem; +import org.xml.sax.helpers.NamespaceSupport; /** * @author Russell Petty (GeoScience Victoria) @@ -49,13 +54,76 @@ public class MappingFeatureIteratorFactory { protected static final Logger LOGGER = org.geotools.util.logging.Logging .getLogger("org.geotools.data.complex"); + + /** + * Temporary filter visitor to determine whether the filter concerns any attribute mapping that + * has isList enabled. This is because Bureau of Meteorology requires a subset of the property + * value to be returned, instead of the full value. This should be a temporary solution. This + * won't work with feature chaining at the moment. + * + * @author Rini Angreani (CSIRO Earth Science and Resource Engineering) + * + */ + static class IsListFilterVisitor extends DefaultFilterVisitor { + // Attribute mappings that have isList enabled + private List<AttributeMapping> listMappings; + + // Filter properties that are configured as isList + private List<StepList> listFilterProperties; + + private FeatureTypeMapping mappings; + + public IsListFilterVisitor(List<AttributeMapping> listMappings, FeatureTypeMapping mappings) { + this.listMappings = listMappings; + this.mappings = mappings; + listFilterProperties = new ArrayList<StepList>(); + } + + @Override + public Object visit(PropertyName expression, Object extraData) { + AttributeDescriptor root = mappings.getTargetFeature(); + String attPath = expression.getPropertyName(); + NamespaceSupport namespaces = mappings.getNamespaces(); + StepList simplifiedSteps = XPath.steps(root, attPath, namespaces); + StepList targetXpath; + for (AttributeMapping mapping : listMappings) { + targetXpath = mapping.getTargetXPath(); + if (targetXpath.equals(simplifiedSteps)) { + // TODO: support feature chaining too? + listFilterProperties.add(targetXpath); + } + } + return extraData; + } + + public List<StepList> getListFilterProperties() { + return listFilterProperties; + } + } + public static IMappingFeatureIterator getInstance(AppSchemaDataAccess store, FeatureTypeMapping mapping, Query query, Filter unrolledFilter) throws IOException { if (mapping instanceof XmlFeatureTypeMapping) { return new XmlMappingFeatureIterator(store, mapping, query); } + + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + List<AttributeMapping> listMappings = mapping.getIsListMappings(); + Filter isListFilter = null; + List<StepList> listFilterProperties = null; + if (!listMappings.isEmpty()) { + IsListFilterVisitor listChecker = new IsListFilterVisitor(listMappings, mapping); + Filter complexFilter = query.getFilter(); + complexFilter.accept(listChecker, null); + listFilterProperties = listChecker.getListFilterProperties(); + if (!listFilterProperties.isEmpty()) { + isListFilter = AppSchemaDataAccess.unrollFilter(complexFilter, mapping); + } + } + // END OF HACK boolean isJoining = AppSchemaDataAccessConfigurator.isJoining(); @@ -99,6 +167,14 @@ // to find denormalised rows that match the id (but doesn't match pre filter) boolean isFiltered = !isJoining && preFilter != null && preFilter != Filter.INCLUDE; iterator = new DataAccessMappingFeatureIterator(store, mapping, query, isFiltered); + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + if (isListFilter != null) { + ((DataAccessMappingFeatureIterator) iterator).setListFilter(isListFilter); + ((DataAccessMappingFeatureIterator) iterator) + .setListFilterProperties(listFilterProperties); + } + // END OF HACK if (filter != null && filter != Filter.INCLUDE) { iterator = new PostFilteringMappingFeatureIterator(iterator, filter, maxFeatures); @@ -137,6 +213,15 @@ } } } + + // HACK HACK HACK + // experimental/temporary solution for isList subsetting by filtering + if (isListFilter != null && iterator instanceof DataAccessMappingFeatureIterator) { + ((DataAccessMappingFeatureIterator) iterator).setListFilter(isListFilter); + ((DataAccessMappingFeatureIterator) iterator) + .setListFilterProperties(listFilterProperties); + } + // END OF HACK return iterator; } Modified: trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java =================================================================== --- trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java 2012-04-30 14:22:21 UTC (rev 38696) +++ trunk/modules/extension/app-schema/app-schema/src/main/java/org/geotools/data/complex/PostFilteringMappingFeatureIterator.java 2012-05-01 10:03:00 UTC (rev 38697) @@ -54,8 +54,14 @@ protected Feature getFilteredNext() { while (delegate.hasNext() && count < maxFeatures) { Feature feature = delegate.next(); - if (filter.evaluate(feature)) { - return feature; + try { + if (filter.evaluate(feature)) { + return feature; + } + } catch (NullPointerException e) { + // ignore this exception + // this is to cater the case if the attribute has no value and + // has been skipped in the delegate DataAccessMappingFeatureIterator } } return null; |