/*
* 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.indexed;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
import org.geotoolkit.ShapeTestData;
import org.geotoolkit.data.FeatureStore;
import org.apache.sis.storage.DataStoreException;
import org.geotoolkit.data.FeatureStoreUtilities;
import org.geotoolkit.data.FeatureReader;
import org.geotoolkit.data.FeatureWriter;
import org.geotoolkit.data.query.Query;
import org.geotoolkit.data.shapefile.ShapefileFeatureStore;
import org.geotoolkit.data.shapefile.lock.ShpFileType;
import org.geotoolkit.data.shapefile.AbstractTestCaseSupport;
import org.geotoolkit.factory.FactoryFinder;
import org.geotoolkit.factory.FactoryRegistryException;
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.filter.identity.FeatureId;
import org.opengis.filter.identity.Identifier;
import org.opengis.geometry.BoundingBox;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Envelope;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryCollection;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import org.apache.sis.feature.FeatureExt;
import org.apache.sis.feature.builder.FeatureTypeBuilder;
import org.apache.sis.internal.feature.AttributeConvention;
import org.geotoolkit.data.query.QueryBuilder;
import org.geotoolkit.data.session.Session;
import org.apache.sis.referencing.CommonCRS;
import org.geotoolkit.test.TestData;
import org.opengis.util.GenericName;
import org.geotoolkit.geometry.DefaultBoundingBox;
import static org.junit.Assert.*;
import org.opengis.feature.Feature;
import org.opengis.feature.FeatureType;
import org.opengis.feature.PropertyType;
/**
*
* @version $Id$
* @author Ian Schneider
* @module
*/
public class IndexedShapefileDataStoreTest 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";
protected FeatureCollection loadFeatures(final String resource, final Query q)
throws Exception {
URL url = ShapeTestData.url(resource);
IndexedShapefileFeatureStore s = new IndexedShapefileFeatureStore(url.toURI());
final FeatureCollection features;
if(q == null){
features = s.createSession(true).getFeatureCollection(QueryBuilder.all(s.getName()));
}else{
features = s.createSession(true).getFeatureCollection(q);
}
s.close();
return features;
}
protected FeatureCollection loadFeatures(final String resource, final Charset charset,
final Query q) throws Exception {
URL url = ShapeTestData.url(resource);
ShapefileFeatureStore s = new IndexedShapefileFeatureStore(url.toURI(), null, false, true, IndexType.QIX, charset);
final FeatureCollection features;
if(q == null){
features = s.createSession(true).getFeatureCollection(QueryBuilder.all(s.getName()));
}else{
features = s.createSession(true).getFeatureCollection(q);
}
s.close();
return features;
}
protected FeatureCollection loadFeatures(final IndexedShapefileFeatureStore s)
throws Exception {
return s.createSession(false).getFeatureCollection(QueryBuilder.all(s.getName()));
}
@Test
public void testLoad() throws Exception {
loadFeatures(STATE_POP, null);
}
@Test
public void testLoadDanishChars() throws Exception {
FeatureCollection fc = loadFeatures(DANISH, null);
Feature first = firstFeature(fc);
// Charl�tte, if you can read it with your OS charset
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 name = (String) first.getPropertyValue("NAME");
assertEquals("\u9ed1\u9f99\u6c5f\u7701", name);
} catch (UnsupportedCharsetException no) {
// this JDK has not been installed with the required
// lanaguage
}
}
@Test
public void testSchema() throws Exception {
URL url = ShapeTestData.url(STATE_POP);
IndexedShapefileFeatureStore s = new IndexedShapefileFeatureStore(url.toURI());
FeatureType schema = s.getFeatureType(s.getName().toString());
Collection<? extends PropertyType> types = schema.getProperties(true);
assertEquals("Number of Attributes", 256, types.size());
assertNotNull(FeatureExt.getCRS(schema));
}
@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());
IndexedShapefileFeatureStore s = new IndexedShapefileFeatureStore(u.toURI());
loadFeatures(s);
s.close();
}
/**
* Test envelope versus old DataSource
*/
@Test
public void testEnvelope() throws Exception {
FeatureCollection features = loadFeatures(STATE_POP, null);
testEnvelope(features, IndexType.QIX);
testEnvelope(features, IndexType.NONE);
}
private void testEnvelope(final FeatureCollection features, final IndexType treeType)
throws MalformedURLException, IOException, DataStoreException, URISyntaxException {
IndexedShapefileFeatureStore s = new IndexedShapefileFeatureStore(ShapeTestData
.url(STATE_POP).toURI(), null, true, true, treeType,null);
GenericName typeName = s.getName();
FeatureCollection all = s.createSession(true).getFeatureCollection(QueryBuilder.all(typeName));
assertEquals(features.getEnvelope(), all.getEnvelope());
s.close();
}
@Test
public void testCreateAndReadQIX() throws Exception {
File shpFile = copyShapefiles(STATE_POP);
URL url = shpFile.toURI().toURL();
String filename = url.getFile();
filename = filename.substring(0, filename.lastIndexOf("."));
File file = new File(filename + ".qix");
if (file.exists()) {
file.delete();
}
file.deleteOnExit();
IndexedShapefileFeatureStore ds = new IndexedShapefileFeatureStore(url.toURI(), null, true, true, IndexType.QIX,null);
FeatureIterator indexIter = ds.getFeatureReader(QueryBuilder.all(ds.getName()));
GeometryFactory factory = new GeometryFactory();
double area = Double.MAX_VALUE;
Feature smallestFeature = null;
while (indexIter.hasNext()) {
Feature newFeature = indexIter.next();
BoundingBox bounds = DefaultBoundingBox.castOrCopy(FeatureExt.getEnvelope(newFeature));
Geometry geometry = factory.toGeometry(new JTSEnvelope2D(
bounds));
double newArea = geometry.getArea();
if (smallestFeature == null || newArea < area) {
smallestFeature = newFeature;
area = newArea;
}
}
indexIter.close();
IndexedShapefileFeatureStore ds2 = new IndexedShapefileFeatureStore(url.toURI(),
null, false, false, IndexType.NONE,null);
Envelope newBounds = (JTSEnvelope2D)ds.getEnvelope(QueryBuilder.all(ds2.getNames().iterator().next()));
double dx = newBounds.getWidth() / 4;
double dy = newBounds.getHeight() / 4;
newBounds = new Envelope(newBounds.getMinX() + dx, newBounds.getMaxX()
- dx, newBounds.getMinY() + dy, newBounds.getMaxY() - dy);
CoordinateReferenceSystem crs = FeatureExt.getCRS(ds.getFeatureType());
performQueryComparison(ds, ds2, new JTSEnvelope2D(newBounds, crs));
performQueryComparison(ds, ds2, new JTSEnvelope2D(FeatureExt.getEnvelope(smallestFeature)));
assertTrue(file.exists());
ds.close();
ds2.close();
}
@Test
public void testFidFilter() throws Exception {
File shpFile = copyShapefiles(STATE_POP);
URL url = shpFile.toURI().toURL();
IndexedShapefileFeatureStore ds = new IndexedShapefileFeatureStore(url.toURI(), null, true, true, IndexType.NONE,null);
FeatureCollection features = ds.createSession(true).getFeatureCollection(QueryBuilder.all(ds.getName()));
FeatureIterator indexIter = features.iterator();
Set<String> expectedFids = new HashSet<>();
final Filter fidFilter;
try {
FilterFactory2 ff = (FilterFactory2) FactoryFinder.getFilterFactory(null);
Set<FeatureId> fids = new HashSet<>();
while (indexIter.hasNext()) {
Feature newFeature = indexIter.next();
String id = FeatureExt.getId(newFeature).getID();
expectedFids.add(id);
fids.add(ff.featureId(id));
}
fidFilter = ff.id(fids);
} finally {
indexIter.close();
}
Set<String> actualFids = new HashSet<>();
{
indexIter = ds.getFeatureReader(QueryBuilder.filtered(ds.getName().toString(), fidFilter));
while (indexIter.hasNext()) {
Feature next = indexIter.next();
String id = FeatureExt.getId(next).getID();
actualFids.add(id);
}
indexIter.close();
}
TreeSet<String> lackingFids = new TreeSet<>(expectedFids);
lackingFids.removeAll(actualFids);
TreeSet<String> unexpectedFids = new TreeSet<>(actualFids);
unexpectedFids.removeAll(expectedFids);
String lacking = String.valueOf(lackingFids);
String unexpected = String.valueOf(unexpectedFids);
String failureMsg = "lacking fids: " + lacking + ". Unexpected ones: " + unexpected;
assertEquals(failureMsg, expectedFids.size(), actualFids.size());
assertEquals(failureMsg, expectedFids, actualFids);
}
private ArrayList performQueryComparison(
final IndexedShapefileFeatureStore indexedDS,
final IndexedShapefileFeatureStore baselineDS, final JTSEnvelope2D newBounds)
throws FactoryRegistryException,
IOException, DataStoreException {
FeatureCollection features;
FeatureIterator indexIter;
FilterFactory2 fac = (FilterFactory2) FactoryFinder.getFilterFactory(null);
String geometryName = FeatureExt.getDefaultGeometryAttribute(indexedDS.getFeatureType()).getName().tip().toString();
Filter filter = fac.bbox(fac.property(geometryName), newBounds);
features = indexedDS.createSession(true).getFeatureCollection(QueryBuilder.filtered(indexedDS.getName().toString(),filter));
FeatureCollection features2 = baselineDS.createSession(true).getFeatureCollection(QueryBuilder.filtered(baselineDS.getName().toString(),filter));
FeatureIterator baselineIter = features2.iterator();
indexIter = features.iterator();
ArrayList baselineFeatures = new ArrayList();
ArrayList indexedFeatures = new ArrayList();
try {
while (baselineIter.hasNext()) {
baselineFeatures.add(baselineIter.next());
}
while (indexIter.hasNext()) {
indexedFeatures.add(indexIter.next());
}
assertFalse(indexIter.hasNext());
assertFalse(baselineIter.hasNext());
assertTrue(baselineFeatures.containsAll(indexedFeatures));
assertTrue(indexedFeatures.containsAll(baselineFeatures));
} finally {
indexIter.close();
baselineIter.close();
}
return indexedFeatures;
}
@Test
public void testLoadAndVerify() throws Exception {
FeatureCollection features = loadFeatures(STATE_POP, null);
int count = features.size();
assertTrue("Got Features", count > 0);
// assertEquals("Number of Features loaded", 49, count); // FILE CORRECT
// assertEquals("Number of Features loaded", 3, count); // JAR WRONG
FeatureType schema = firstFeature(features).getType();
assertNotNull(schema.getProperty(AttributeConvention.GEOMETRY_PROPERTY.toString()));
assertEquals("Number of Attributes", 256, schema.getProperties(true).size());
assertEquals("Value of statename is wrong", firstFeature(features)
.getPropertyValue("STATE_NAME"), "Illinois");
assertEquals("Value of land area is wrong", ((Double) firstFeature(
features).getPropertyValue("LAND_KM")).doubleValue(), 143986.61,
0.001);
}
private IndexedShapefileFeatureStore createDataStore(final File f) throws Exception {
Collection<Feature> fc = createFeatureCollection();
f.createNewFile();
IndexedShapefileFeatureStore sds = new IndexedShapefileFeatureStore(f.toURI());
writeFeatures(sds, fc);
return sds;
}
private IndexedShapefileFeatureStore createDataStore() throws Exception {
return createDataStore(getTempFile());
}
/**
* 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 {
IndexedShapefileFeatureStore sds = createDataStore();
loadFeatures(sds);
FeatureWriter writer = null;
try {
writer = sds.getFeatureWriter(QueryBuilder.all(sds.getName().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();
sds.close();
}
/**
* Create a test file, then continue removing the first entry until there
* are no features left.
*/
@Test
public void testRemoveFromFrontAndClose() throws Throwable {
IndexedShapefileFeatureStore sds = createDataStore();
int idx = loadFeatures(sds).size();
while (idx > 0) {
FeatureWriter writer = null;
try {
writer = sds.getFeatureWriter(QueryBuilder.all(sds.getName().toString()));
writer.next();
writer.remove();
} finally {
if (writer != null) {
writer.close();
writer = null;
}
}
assertEquals(--idx, loadFeatures(sds).size());
}
sds.close();
}
/**
* Create a test file, then continue removing the first entry until there
* are no features left.
*/
@Test
public void testRemoveFromFrontAndCloseTransaction() throws Throwable {
IndexedShapefileFeatureStore sds = createDataStore();
int idx = loadFeatures(sds).size();
while (idx > 0) {
FeatureWriter writer = null;
try {
writer = sds.getFeatureWriter(QueryBuilder.all(sds.getName().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 last entry until there are
* no features left.
*/
@Test
public void testRemoveFromBackAndClose() throws Throwable {
IndexedShapefileFeatureStore 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());
}
sds.close();
}
@Test
public void testTestTransaction() throws Exception {
final IndexedShapefileFeatureStore sds = createDataStore();
final long idx = sds.getCount(QueryBuilder.all(sds.getName().toString()));
final Session session = sds.createSession(true);
Feature[] newFeatures1 = new Feature[1];
Feature[] newFeatures2 = new Feature[2];
GeometryFactory fac = new GeometryFactory();
newFeatures1[0] = sds.getFeatureType().newInstance();
newFeatures1[0].setPropertyValue("a",fac.createPoint(new Coordinate(0, 0)));
newFeatures2[0] = sds.getFeatureType().newInstance();
newFeatures2[0].setPropertyValue("a",fac.createPoint(new Coordinate(0, 0)));
newFeatures2[1] = sds.getFeatureType().newInstance();
newFeatures2[1].setPropertyValue("a",fac.createPoint(new Coordinate(0, 0)));
session.addFeatures(sds.getName().toString(),FeatureStoreUtilities.collection(newFeatures1));
session.addFeatures(sds.getName().toString(),FeatureStoreUtilities.collection(newFeatures2));
session.commit();
assertEquals(idx + 3, sds.getCount(QueryBuilder.all(sds.getName().toString())));
sds.close();
}
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 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;
}
@Test
public void testAttributesWriting() throws Exception {
Collection<Feature> features = createFeatureCollection();
File tmpFile = getTempFile();
tmpFile.createNewFile();
IndexedShapefileFeatureStore s = new IndexedShapefileFeatureStore(tmpFile.toURI());
writeFeatures(s, features);
s.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) {
throw new Exception("Error in " + testName, e);
}
}
}
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 IndexedShapefileFeatureStore s, final Collection<Feature> fc)
throws Exception {
final FeatureType type = fc.iterator().next().getType();
s.createFeatureType(type);
final FeatureWriter fw = s.getFeatureWriter(QueryBuilder.all(type.getName().toString()));
final 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();
assertEquals(20, s.getCount(QueryBuilder.all(type.getName())));
}
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());
final FeatureType type = ftb.build();
final Collection<Feature> features = new ArrayList<>();
for (int i = 0, ii = 20; i < ii; i++) {
Feature feature = type.newInstance();
feature.setPropertyValue("a", geom.clone());
features.add(feature);
}
// set up file
File tmpFile = getTempFile();
tmpFile.delete();
// write features
IndexedShapefileFeatureStore s = new IndexedShapefileFeatureStore(tmpFile.toURI());
s.createFeatureType(type);
writeFeatures(s, features);
s.close();
// read features
s = new IndexedShapefileFeatureStore(tmpFile.toURI());
FeatureCollection fc = loadFeatures(s);
FeatureIterator fci = fc.iterator();
// verify
try{
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()));
}
}
}finally{
fci.close();
s.close();
tmpFile.delete();
}
}
@Test
public void testIndexOutOfDate() throws Exception {
File shpFile = copyShapefiles(STATE_POP);
ShpFileType fix = ShpFileType.FIX;
File fixFile = sibling(shpFile, fix.extension);
fixFile.delete();
IndexedShapefileFeatureStore ds = new IndexedShapefileFeatureStore(shpFile.toURI());
assertFalse(ds.needsGeneration(fix));
long fixMod = fixFile.lastModified();
shpFile.setLastModified(fixMod+1000);
assertTrue(ds.needsGeneration(fix));
fixFile.setLastModified(shpFile.lastModified());
assertFalse(ds.needsGeneration(fix));
assertTrue(fixFile.delete());
assertTrue(ds.needsGeneration(fix));
ds.close();
}
/**
* Issueing a request, whether its a query, update or delete, with a fid filter where feature
* ids match the {@code <typeName>.<number>} structure but the {@code <typeName>} part does not
* match the actual typeName, shoud ensure the invalid fids are ignored
*
* @throws java.lang.Exception
*/
@Test
public void testWipesOutInvalidFidsFromFilters() throws Exception {
final IndexedShapefileFeatureStore ds = createDataStore();
final Session session = ds.createSession(true);
final String validFid1, validFid2, invalidFid1, invalidFid2;
try (FeatureIterator features = ds.getFeatureReader(QueryBuilder.all(ds.getName().toString()))) {
validFid1 = FeatureExt.getId(features.next()).getID();
validFid2 = FeatureExt.getId(features.next()).getID();
invalidFid1 = "_" + FeatureExt.getId(features.next()).getID();
invalidFid2 = FeatureExt.getId(features.next()).getID()+ "abc";
}
FilterFactory2 ff = (FilterFactory2) FactoryFinder.getFilterFactory(null);
Set<Identifier> ids = new HashSet<>();
ids.add(ff.featureId(validFid1));
ids.add(ff.featureId(validFid2));
ids.add(ff.featureId(invalidFid1));
ids.add(ff.featureId(invalidFid2));
Filter fidFilter = ff.id(ids);
final FeatureType schema = ds.getFeatureType();
final String typeName = schema.getName().tip().toString();
//get a property of type String to update its value by the given filter
assertEquals(2, count(ds, typeName, fidFilter));
session.updateFeatures(ds.getName().toString(),fidFilter, Collections.singletonMap("f", "modified"));
session.commit();
Filter modifiedFilter = ff.equals(ff.property("f"), ff.literal("modified"));
assertEquals(2, count(ds, typeName, modifiedFilter));
final long initialCount = ds.getCount(QueryBuilder.all(ds.getName().toString()));
session.removeFeatures(ds.getName().toString(),fidFilter);
session.commit();
final long afterCount = ds.getCount(QueryBuilder.all(ds.getName().toString()));
assertEquals(initialCount - 2, afterCount);
}
private int count(final FeatureStore ds, final String typeName, final Filter filter) throws Exception {
FeatureReader reader;
reader = ds.getFeatureReader(QueryBuilder.filtered(typeName, filter));
int count = 0;
try {
while (reader.hasNext()) {
reader.next();
count++;
}
} finally {
reader.close();
}
return count;
}
}