/*
* GeotoolKit - An Open source Java GIS Toolkit
* http://geotoolkit.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.geotoolkit.data.shapefile;
import org.junit.Test;
import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.geotoolkit.ShapeTestData;
import org.geotoolkit.data.FeatureStore;
import org.geotoolkit.data.query.QueryBuilder;
import org.geotoolkit.util.NamesExt;
import org.geotoolkit.data.FeatureReader;
import org.geotoolkit.data.FeatureWriter;
import org.geotoolkit.data.query.Query;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.data.FeatureCollection;
import org.geotoolkit.data.FeatureIterator;
import org.geotoolkit.geometry.jts.JTSEnvelope2D;
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.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Point;
import com.vividsolutions.jts.geom.Polygon;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.apache.sis.feature.FeatureExt;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
import org.apache.sis.referencing.CommonCRS;
import org.geotoolkit.io.wkt.PrjFiles;
import org.geotoolkit.test.TestData;
import static org.junit.Assert.*;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.PropertyType;
import org.apache.sis.feature.builder.AttributeRole;
import org.apache.sis.referencing.CRS;
import org.apache.sis.util.Utilities;
/**
*
* @version $Id$
* @author Ian Schneider
* @module
*/
public class ShapefileDataStoreTest extends AbstractTestCaseSupport {
static final String STATE_POP = "shapes/statepop.shp";
static final String STREAM = "shapes/stream.shp";
static final String DANISH = "shapes/danish_point.shp";
static final String CHINESE = "shapes/chinese_poly.shp";
static final FilterFactory2 ff = (FilterFactory2) FactoryFinder.getFilterFactory(null);
protected FeatureCollection loadFeatures(final String resource, Query query)
throws Exception {
assertNotNull(query);
URL url = ShapeTestData.url(resource);
ShapefileFeatureStore s = new ShapefileFeatureStore(url.toURI(),null,true,null);
final QueryBuilder builder = new QueryBuilder(query);
builder.setTypeName(s.getName());
query = builder.buildQuery();
return s.createSession(true).getFeatureCollection(query);
}
protected FeatureCollection loadFeatures(final String resource, final Charset charset, final Query q) throws Exception {
URL url = ShapeTestData.url(resource);
ShapefileFeatureStore s = new ShapefileFeatureStore(url.toURI(), null, false, charset);
if(q == null){
return s.createSession(true).getFeatureCollection(QueryBuilder.all(s.getName()));
}else{
return s.createSession(true).getFeatureCollection(q);
}
}
protected FeatureCollection loadFeatures(final ShapefileFeatureStore s)
throws Exception {
return s.createSession(true).getFeatureCollection(QueryBuilder.all(s.getName()));
}
@Test
public void testLoad() throws Exception {
loadFeatures(STATE_POP, QueryBuilder.all(NamesExt.create("statepop")));
}
@Test
public void testLoadDanishChars() throws Exception {
FeatureCollection fc = loadFeatures(DANISH, QueryBuilder.all(NamesExt.create("danish_point")));
Feature first = firstFeature(fc);
// Charlotte (but with the o is stroked)
assertEquals("Charl\u00F8tte", first.getPropertyValue("TEKST1"));
}
@Test
public void testLoadChineseChars() throws Exception {
try {
FeatureCollection fc = loadFeatures(CHINESE, Charset
.forName("GB18030"), null);
Feature first = firstFeature(fc);
String s = (String) first.getPropertyValue("NAME");
assertEquals("\u9ed1\u9f99\u6c5f\u7701", s);
} catch (UnsupportedCharsetException notInstalledInJRE){
// this just means you have not installed
// chinese support into your JRE
// (as such it represents a bad configuration
// rather than a test failure)
// we only wanted to ensure that if you have Chinese support
// available - GeotoolKit can use it
}
}
@Test
public void testNamespace() throws Exception {
ShapefileFeatureStoreFactory factory = new ShapefileFeatureStoreFactory();
Map map = new HashMap();
String namespace = "http://jesse.com";
map.put(ShapefileFeatureStoreFactory.NAMESPACE.getName().toString(), namespace);
map.put(ShapefileFeatureStoreFactory.PATH.getName().toString(), ShapeTestData.url(STATE_POP));
FeatureStore store = (FeatureStore) factory.open(map);
FeatureType schema = store.getFeatureType(store.getNames().iterator().next().toString());
assertEquals(namespace, NamesExt.getNamespace(schema.getName()));
}
@Test
public void testSchema() throws Exception {
URL url = ShapeTestData.url(STATE_POP);
ShapefileFeatureStore shapeFeatureStore = new ShapefileFeatureStore(url.toURI());
String typeName = shapeFeatureStore.getNames().iterator().next().toString();
FeatureType schema = shapeFeatureStore.getFeatureType(typeName);
Collection<? extends PropertyType> attributes = schema.getProperties(true);
assertEquals("Number of Attributes", 256, attributes.size());
}
@Test
public void testSpacesInPath() throws Exception {
URL u = TestData.url(AbstractTestCaseSupport.class, "folder with spaces/pointtest.shp");
File f = new File(URLDecoder.decode(u.getFile(), "UTF-8"));
assertTrue(f.exists());
ShapefileFeatureStore s = new ShapefileFeatureStore(u.toURI());
loadFeatures(s);
}
/**
* Test envelope versus old DataSource
*/
@Test
public void testEnvelope() throws Exception {
FeatureCollection features = loadFeatures(STATE_POP, QueryBuilder.all(NamesExt.create("statepop")));
ShapefileFeatureStore s = new ShapefileFeatureStore(ShapeTestData.url(STATE_POP).toURI());
String typeName = s.getName().toString();
FeatureCollection all = s.createSession(true).getFeatureCollection(QueryBuilder.all(s.getName()));
assertEquals(features.getEnvelope(), all.getEnvelope());
}
@Test
public void testLoadAndVerify() throws Exception {
FeatureCollection features = loadFeatures(STATE_POP, QueryBuilder.all(NamesExt.create("statepop")));
// FeatureCollection<SimpleFeatureType, SimpleFeature> features = loadFeaturesM2();
int count = features.size();
assertTrue("Have features", count > 0);
// assertEquals("Number of Features loaded",49,features.size()); // FILE
// (correct value)
// assertEquals("Number of Features loaded",3, count); // JAR
Feature firstFeature = firstFeature(features);
FeatureType schema = firstFeature.getType();
assertNotNull(FeatureExt.getDefaultGeometryAttribute(schema));
assertEquals("Number of Attributes", 256, schema.getProperties(true).size());
assertEquals("Value of statename is wrong", "Illinois", firstFeature
.getPropertyValue("STATE_NAME"));
assertEquals("Value of land area is wrong", 143986.61,
((Double) firstFeature.getPropertyValue("LAND_KM")).doubleValue(),
0.001);
}
@Test
public void testCreateSchemaWithEmptyCRS() throws Exception {
File file = new File("test.shp");
final URI toURI = file.toURI();
final ShapefileFeatureStore ds = new ShapefileFeatureStore(toURI);
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
ftb.setName("test");
ftb.addAttribute(MultiPolygon.class).setName("geom").addRole(AttributeRole.DEFAULT_GEOMETRY);
final FeatureType toCreate = ftb.build();
ds.createFeatureType(toCreate);
assertEquals("test", ds.getName().toString());
file.deleteOnExit();
file = new File("test.dbf");
file.deleteOnExit();
file = new File("test.shp");
file.deleteOnExit();
file = new File("test.prj");
if (file.exists())
file.deleteOnExit();
file = new File("test.shx");
if (file.exists()){
file.deleteOnExit();
}
file = new File("test.cpg");
if (file.exists()){
file.deleteOnExit();
}
}
@Test
public void testCreateSchemaWithCRS() throws Exception {
File file = new File("test.shp");
URI toURI = file.toURI();
ShapefileFeatureStore ds = new ShapefileFeatureStore(toURI);
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
ftb.setName("test");
ftb.addAttribute(MultiPolygon.class).setName("geom").setCRS(CRS.forCode("EPSG:32615")).addRole(AttributeRole.DEFAULT_GEOMETRY);
FeatureType featureType = ftb.build();
CoordinateReferenceSystem crs = FeatureExt.getCRS(featureType);
assertNotNull( crs );
ds.createFeatureType(featureType);
assertEquals("test", ds.getName().tip().toString());
CoordinateReferenceSystem crs2 = FeatureExt.getCRS(ds.getFeatureType("test"));
assertNotNull( crs2 );
assertTrue(Utilities.equalsIgnoreMetadata(crs, crs2));
file.deleteOnExit();
file = new File("test.dbf");
file.deleteOnExit();
file = new File("test.shp");
file.deleteOnExit();
file = new File("test.prj");
if (file.exists())
file.deleteOnExit();
file = new File("test.shx");
if (file.exists()){
file.deleteOnExit();
}
file = new File("test.prj");
if( file.exists()){
file.deleteOnExit();
}
file = new File("test.cpg");
if( file.exists()){
file.deleteOnExit();
}
}
/**
* Create a set of features, then remove every other one, updating the
* remaining. Test for removal and proper update after reloading...
*/
@Test
public void testUpdating() throws Throwable {
ShapefileFeatureStore sds = createDataStore();
loadFeatures(sds);
FeatureWriter writer = null;
try {
writer = sds.getFeatureWriter(QueryBuilder.all(sds.getNames().iterator().next().toString()));
while (writer.hasNext()) {
Feature feat = writer.next();
Byte b = (Byte) feat.getPropertyValue("b");
if (b.byteValue() % 2 == 0) {
writer.remove();
} else {
feat.setPropertyValue("b", new Byte((byte) -1));
}
}
} finally {
if (writer != null) {
writer.close();
}
}
FeatureCollection fc = loadFeatures(sds);
assertEquals(10, fc.size());
FeatureIterator i = fc.iterator();
for (; i.hasNext();) {
assertEquals(-1, ((Byte) (i.next()).getPropertyValue("b")).byteValue());
}
i.close();
}
/**
* Create a test file, then continue removing the first entry until there
* are no features left.
*/
@Test
public void testRemoveFromFrontAndClose() throws Throwable {
ShapefileFeatureStore sds = createDataStore();
int idx = loadFeatures(sds).size();
while (idx > 0) {
FeatureWriter writer = null;
try {
writer = sds.getFeatureWriter(QueryBuilder.all(sds.getNames().iterator().next().toString()));
writer.next();
writer.remove();
} finally {
if (writer != null) {
writer.close();
writer = null;
}
}
assertEquals(--idx, loadFeatures(sds).size());
}
}
/**
* Create a test file, then continue removing the first entry until there
* are no features left.
*/
@Test
public void testRemoveFromFrontAndCloseTransaction() throws Throwable {
ShapefileFeatureStore sds = createDataStore();
int idx = loadFeatures(sds).size();
while (idx > 0) {
FeatureWriter writer = null;
try {
writer = sds.getFeatureWriter(QueryBuilder.all(sds.getName().toString()));
// System.out.println("classe : " + writer.getClass());
writer.next();
writer.remove();
} finally {
if (writer != null) {
writer.close();
writer = null;
}
}
assertEquals(--idx, loadFeatures(sds).size());
}
}
/**
* Create a test file, then continue removing the last entry until there are
* no features left.
*/
@Test
public void testRemoveFromBackAndClose() throws Throwable {
ShapefileFeatureStore sds = createDataStore();
int idx = loadFeatures(sds).size();
while (idx > 0) {
FeatureWriter writer = null;
try {
writer = sds.getFeatureWriter(QueryBuilder.all(sds.getName().toString()));
while (writer.hasNext()) {
writer.next();
}
writer.remove();
} finally {
if (writer != null) {
writer.close();
writer = null;
}
}
assertEquals(--idx, loadFeatures(sds).size());
}
}
@Test
public void testWriteShapefileWithNoRecords() throws Exception {
final FeatureTypeBuilder ftb = new FeatureTypeBuilder().setName("whatever");
ftb.addAttribute(Polygon.class).setName("a").addRole(AttributeRole.DEFAULT_GEOMETRY);
ftb.addAttribute(String.class).setName("b");
FeatureType featureType = ftb.build();
File tempFile = getTempFile();
ShapefileFeatureStore shapefileFeatureStore = new ShapefileFeatureStore(tempFile.toURI());
shapefileFeatureStore.createFeatureType(featureType);
FeatureWriter featureWriter = shapefileFeatureStore.getFeatureWriter(QueryBuilder.all(shapefileFeatureStore.getName().toString()));
// don't add any features to the data store....
// this should open a shapefile with no records. Not sure about the
// semantics of this,
// but it's meant to be used in the context of a FeatureCollection
// iteration,
// where the FeatureCollection<SimpleFeatureType, SimpleFeature> has nothing in it.
featureWriter.close();
}
@Test
public void testAttributesWriting() throws Exception {
Collection<Feature> features = createFeatureCollection();
File tmpFile = getTempFile();
tmpFile.createNewFile();
ShapefileFeatureStore s = new ShapefileFeatureStore(tmpFile.toURI());
writeFeatures(s, features);
}
@Test
public void testWriteReadBigNumbers() throws Exception {
// open feature type
final FeatureTypeBuilder ftb = new FeatureTypeBuilder().setName("junk");
ftb.addAttribute(Point.class).setName("a").addRole(AttributeRole.DEFAULT_GEOMETRY);
ftb.addAttribute(BigDecimal.class).setName("b");
ftb.addAttribute(BigInteger.class).setName("c");
FeatureType type = ftb.build();
Collection<Feature> features = new ArrayList<>();
BigInteger bigInteger = new BigInteger("1234567890123456789");
BigDecimal bigDecimal = new BigDecimal(bigInteger, 2);
final Feature feature = type.newInstance();
feature.setPropertyValue("a", new GeometryFactory().createPoint(new Coordinate(1, -1)));
feature.setPropertyValue("b", bigDecimal);
feature.setPropertyValue("c", bigInteger);
features.add(feature);
// store features
File tmpFile = getTempFile();
tmpFile.createNewFile();
ShapefileFeatureStore s = new ShapefileFeatureStore(tmpFile.toURI());
writeFeatures(s, features);
// read them back
FeatureReader reader = s.getFeatureReader(QueryBuilder.all(type.getName()));
try {
Feature f = reader.next();
assertEquals("big decimal", bigDecimal.doubleValue(), ((Number) f
.getPropertyValue("b")).doubleValue(), 0.00001);
assertEquals("big integer", bigInteger.longValue(), ((Number) f
.getPropertyValue("c")).longValue(), 0.00001);
} finally {
reader.close();
}
}
@Test
public void testGeometriesWriting() throws Exception {
String[] wktResources = new String[] { "point", "multipoint", "line",
"multiline", "polygon", "multipolygon" };
for (int i = 0; i < wktResources.length; i++) {
Geometry geom = readGeometry(wktResources[i]);
String testName = wktResources[i];
try {
runWriteReadTest(geom, false);
make3D(geom);
testName += "3d";
runWriteReadTest(geom, true);
} catch (Throwable e) {
e.printStackTrace();
throw new Exception("Error in " + testName, e);
}
}
}
@Test
public void testGetCount() throws Exception {
assertTrue(copyShapefiles(STREAM).canRead()); // The following test
// seems to fail in the
// URL point into the
// JAR file.
ShapefileFeatureStore store = (ShapefileFeatureStore) new ShapefileFeatureStoreFactory()
.createDataStore(TestData.url(AbstractTestCaseSupport.class, STREAM).toURI());
int count = 0;
FeatureReader reader = store.getFeatureReader(QueryBuilder.all(store.getNames().iterator().next()));
try {
while (reader.hasNext()) {
count++;
reader.next();
}
assertEquals(count, store.getCount(QueryBuilder.all(store.getNames().iterator().next())));
} finally {
reader.close();
}
}
/**
* Checks if feature reading optimizations still allow to execute the
* queries or not
*
* @throws Exception
*/
@Test
public void testGetReaderOptimizations() throws Exception {
URL url = ShapeTestData.url(STATE_POP);
ShapefileFeatureStore s = new ShapefileFeatureStore(url.toURI());
// attributes other than geometry can be ignored here
final QueryBuilder builder = new QueryBuilder();
builder.setTypeName(s.getNames().iterator().next());
builder.setFilter(Filter.INCLUDE);
builder.setProperties(new String[]{"the_geom"});
Query query = builder.buildQuery();
FeatureReader reader = s.getFeatureReader(query);
assertEquals(1, reader.getFeatureType().getProperties(true).size());
assertEquals("the_geom", reader.getFeatureType().getProperties(true).iterator().next().getName().tip().toString());
// here too, the filter is using the geometry only
GeometryFactory gc = new GeometryFactory();
LinearRing ring = gc.createLinearRing(new Coordinate[] {
new Coordinate(0, 0), new Coordinate(10, 0),
new Coordinate(10, 10), new Coordinate(0, 10),
new Coordinate(0, 0) });
Polygon polygon = gc.createPolygon(ring, null);
JTSEnvelope2D bounds = new JTSEnvelope2D(polygon
.getEnvelopeInternal(), null);
Filter gf = ff.bbox(ff.property("the_geom"), bounds);
builder.reset();
builder.setTypeName(s.getNames().iterator().next());
builder.setFilter(gf);
builder.setProperties(new String[]{"the_geom"});
query = builder.buildQuery();
reader.close();
reader = s.getFeatureReader(query);
assertEquals(1, reader.getFeatureType().getProperties(true).size());
assertEquals("the_geom", reader.getFeatureType().getProperties(true).iterator().next().getName().tip().toString());
reader.close();
// here not, we need state_name in the feature type, so open the dbf
// file please
Filter cf = ff
.equals(ff.property("STATE_NAME"), ff.literal("Illinois"));
builder.reset();
builder.setTypeName(s.getNames().iterator().next());
builder.setFilter(cf);
builder.setProperties(new String[]{"the_geom"});
query = builder.buildQuery();
reader = s.getFeatureReader(query);
assertEquals(1, reader.getFeatureType().getProperties(true).size());
assertEquals("the_geom", reader.getFeatureType().getProperties(true).iterator().next().getName().tip().toString());
reader.close();
}
@Test
public void testWrite() throws Exception {
// open feature type
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
ftb.setName("junk");
ftb.addAttribute(Point.class).setName("a").addRole(AttributeRole.DEFAULT_GEOMETRY);
ftb.addAttribute(BigDecimal.class).setName("b");
ftb.addAttribute(BigInteger.class).setName("c");
FeatureType type = ftb.build();
BigInteger bigInteger = new BigInteger("1234567890123456789");
BigDecimal bigDecimal = new BigDecimal(bigInteger, 2);
Feature feature = type.newInstance();
feature.setPropertyValue("a", new GeometryFactory().createPoint(new Coordinate(1, -1)));
feature.setPropertyValue("b",bigDecimal);
feature.setPropertyValue("c",bigInteger);
// store features
File tmpFile = getTempFile();
tmpFile.createNewFile();
ShapefileFeatureStore s = new ShapefileFeatureStore(tmpFile.toURI());
s.createFeatureType(type);
// // was failing in GEOT-2427
// FeatureWriter<SimpleFeatureType, SimpleFeature> writer = s.getFeatureWriter(s.getNames().iterator().next(),Filter.INCLUDE);
// SimpleFeature feature1 = writer.next();
// writer.close();
}
@Test
public void testReadQPJ() throws Exception {
final URL shpUrl = this.getClass().getResource("/org/geotoolkit/test-data/shapes/utf8.shp");
final FeatureType ft = new ShapefileFeatureStore(shpUrl.toURI()).getFeatureType();
assertNotNull("No feature type loaded !", ft);
final CoordinateReferenceSystem crs = FeatureExt.getCRS(ft);
assertNotNull("No CRS loaded !", crs);
final URL qpjUrl = this.getClass().getResource("/org/geotoolkit/test-data/shapes/utf8.qpj");
assertEquals("CRS loaded by shapefile store is not the one contained in qpj !", crs, PrjFiles.read(qpjUrl));
}
/**
* Creates feature collection with all the stuff we care about from simple
* types, to Geometry and date.
* <p>
* As we care about supporting more stuff please add on to the end of this
* list...
*
* @return FeatureCollection<SimpleFeature> For use in testing.
* @throws Exception
*/
private Collection<Feature> createFeatureCollection() throws Exception {
FeatureType featureType = createExampleSchema();
Collection<Feature> features = new ArrayList<>();
for (int i = 0, ii = 20; i < ii; i++) {
final Feature feature = featureType.newInstance();
feature.setPropertyValue("a",new GeometryFactory().createPoint(new Coordinate(1, -1)));
feature.setPropertyValue("b",new Byte((byte) i));
feature.setPropertyValue("c",new Short((short) i));
feature.setPropertyValue("d",new Double(i));
feature.setPropertyValue("e",new Float(i));
feature.setPropertyValue("f",new String(i + " "));
feature.setPropertyValue("g",new Date(i));
feature.setPropertyValue("h",new Boolean(true));
feature.setPropertyValue("i",new Integer(22));
feature.setPropertyValue("j",new Long(1234567890123456789L));
feature.setPropertyValue("k",new BigDecimal(new BigInteger("12345678901234567890123456789"), 2));
feature.setPropertyValue("l",new BigInteger("12345678901234567890123456789"));
features.add(feature);
}
return features;
}
private FeatureType createExampleSchema() {
FeatureTypeBuilder build = new FeatureTypeBuilder();
build.setName("junk");
build.addAttribute(Point.class).setName("a").setCRS(CommonCRS.WGS84.normalizedGeographic());
build.addAttribute(Byte.class).setName("b");
build.addAttribute(Short.class).setName("c");
build.addAttribute(Double.class).setName("d");
build.addAttribute(Float.class).setName("e");
build.addAttribute(String.class).setName("f");
build.addAttribute(Date.class).setName("g");
build.addAttribute(Boolean.class).setName("h");
build.addAttribute(Number.class).setName("i");
build.addAttribute(Long.class).setName("j");
build.addAttribute(BigDecimal.class).setName("k");
build.addAttribute(BigInteger.class).setName("l");
return build.build();
}
private void make3D(final Geometry g) {
Coordinate[] c = g.getCoordinates();
for (int i = 0, ii = c.length; i < ii; i++) {
c[i].z = 42 + i;
}
}
private void writeFeatures(final ShapefileFeatureStore s, final Collection<Feature> fc)
throws Exception {
final FeatureType sft = fc.iterator().next().getType();
s.createFeatureType(sft);
FeatureWriter fw = s.getFeatureWriter(QueryBuilder.all(sft.getName().toString()));
Iterator<Feature> it = fc.iterator();
while (it.hasNext()) {
Feature feature = it.next();
Feature newFeature = fw.next();
FeatureExt.copy(feature, newFeature, false);
fw.write();
}
fw.close();
}
private void runWriteReadTest(final Geometry geom, final boolean d3) throws Exception {
// make features
final FeatureTypeBuilder ftb = new FeatureTypeBuilder();
ftb.setName("Junk");
ftb.addAttribute(geom.getClass()).setName("a").setCRS(CommonCRS.WGS84.normalizedGeographic()).addRole(AttributeRole.DEFAULT_GEOMETRY);
final FeatureType type = ftb.build();
Collection<Feature> features = new ArrayList<>();
for (int i = 0, ii = 20; i < ii; i++) {
final Feature feature = type.newInstance();
feature.setPropertyValue("a", (Geometry) geom.clone());
features.add(feature);
}
// set up file
File tmpFile = getTempFile();
tmpFile.delete();
// write features
ShapefileFeatureStore shapeFeatureStore = new ShapefileFeatureStore(tmpFile.toURI());
shapeFeatureStore.createFeatureType(type);
writeFeatures(shapeFeatureStore, features);
// read features
shapeFeatureStore = new ShapefileFeatureStore(tmpFile.toURI());
FeatureCollection fc = loadFeatures(shapeFeatureStore);
FeatureIterator fci = fc.iterator();
// verify
while (fci.hasNext()) {
Feature f = fci.next();
Geometry fromShape = (Geometry) FeatureExt.getDefaultGeometryAttributeValue(f);
if (fromShape instanceof GeometryCollection) {
if (!(geom instanceof GeometryCollection)) {
fromShape = ((GeometryCollection) fromShape)
.getGeometryN(0);
}
}
try {
Coordinate[] c1 = geom.getCoordinates();
Coordinate[] c2 = fromShape.getCoordinates();
for (int cc = 0, ccc = c1.length; cc < ccc; cc++) {
if (d3)
assertTrue(c1[cc].equals3D(c2[cc]));
else
assertTrue(c1[cc].equals2D(c2[cc]));
}
} catch (Throwable t) {
fail("Bogus : " + Arrays.asList(geom.getCoordinates()) + " : "
+ Arrays.asList(fromShape.getCoordinates()));
}
}
fci.close();
tmpFile.delete();
}
private ShapefileFeatureStore createDataStore(final File f) throws Exception {
Collection<Feature> fc = createFeatureCollection();
ShapefileFeatureStore sds = new ShapefileFeatureStore(f.toURI());
writeFeatures(sds, fc);
return sds;
}
private ShapefileFeatureStore createDataStore() throws Exception {
return createDataStore(getTempFile());
}
/**
* This is useful to dump a UTF16 character to an UT16 escape sequence,
* basically the only way to represent the chars we don't have on the
* keyboard (such as chinese ones :))
*
* @param c
* @return
*/
static public String charToHex(final char c) {
// Returns hex String representation of char c
byte hi = (byte) (c >>> 8);
byte lo = (byte) (c & 0xff);
return byteToHex(hi) + byteToHex(lo);
}
static public String byteToHex(final byte b) {
// Returns hex String representation of byte b
char[] hexDigit = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f' };
char[] array = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
return new String(array);
}
}