use of org.apache.sis.feature.AbstractFeature in project sis by apache.
the class FeatureIterator method read.
/**
* Executes the given action for the next feature or for all remaining features.
* The features are assumed static, with one feature per line.
* This method is for {@link #tryAdvance(Consumer)} and {@link #forEachRemaining(Consumer)} implementations.
*
* <p><b>Multi-threading:</b>
* {@code Iter} does not need to be thread-safe, so we do not perform synchronization for its {@link #values}.
* Accesses to {@code Store} fields need to be thread-safe, but this method uses only immutable or thread-safe
* objects from {@link Store}, so there is no need for {@code synchronize(Store.this)} statement.
* The only object that need synchronization is {@link Store#source}, which is already synchronized.</p>
*
* @param action the action to execute.
* @param all {@code true} for executing the given action on all remaining features.
* @return {@code false} if there is no remaining feature after this method call.
* @throws IOException if an I/O error occurred while reading a feature.
* @throws IllegalArgumentException if parsing of a number failed, or other error.
* @throws DateTimeException if parsing of a date failed.
*/
private boolean read(final Consumer<? super AbstractFeature> action, final boolean all) throws IOException {
final FixedSizeList elements = new FixedSizeList(values);
String line;
while ((line = store.readLine()) != null) {
Store.split(line, elements);
final AbstractFeature feature = store.featureType.newInstance();
int i, n = elements.size();
for (i = 0; i < n; i++) {
values[i] = converters[i].apply((String) values[i]);
feature.setPropertyValue(propertyNames[i], values[i]);
}
n = values.length;
for (; i < n; i++) {
// For omitted elements, reuse previous value.
feature.setPropertyValue(propertyNames[i], values[i]);
}
action.accept(feature);
if (!all)
return true;
elements.clear();
}
return false;
}
use of org.apache.sis.feature.AbstractFeature in project sis by apache.
the class MovingFeatureIterator method createMovingFeature.
/**
* Creates the moving feature of the given name.
* This method can only be invoked after {@link #readMoving(Consumer, boolean)}.
*
* @param featureName name of the feature to create.
* @param np number of properties, ignoring the ones before the trajectory column.
*/
@SuppressWarnings("unchecked")
private AbstractFeature createMovingFeature(final String featureName, final MovingFeature mf, final int np) {
final AbstractFeature feature = store.featureType.newInstance();
feature.setPropertyValue(propertyNames[0], featureName);
mf.storeTimeRange(propertyNames[1], propertyNames[2], feature);
int column = 0;
if (store.hasTrajectories()) {
mf.storeGeometry(featureName, column, store.spatialDimensionCount(), store.geometries, (AbstractAttribute) feature.getProperty(propertyNames[TRAJECTORY_COLUMN]), this);
column++;
}
while (column < np) {
mf.storeAttribute(column, (AbstractAttribute<?>) feature.getProperty(propertyNames[TRAJECTORY_COLUMN + column]));
column++;
}
return feature;
}
use of org.apache.sis.feature.AbstractFeature in project sis by apache.
the class StoreTest method testMovingFeatures.
/**
* Tests reading the data as a moving features. In the following data:
*
* {@preformat text
* a, 10, 150, 11.0 2.0 12.0 3.0, walking, 1
* b, 10, 190, 10.0 2.0 11.0 3.0, walking, 2
* a, 150, 190, 12.0 3.0 10.0 3.0
* c, 10, 190, 12.0 1.0 10.0 2.0 11.0 3.0, vehicle, 1
* }
*
* the two rows for the "a" features shall be merged in a single trajectory.
*
* @throws DataStoreException if an error occurred while parsing the data.
*/
@Test
public void testMovingFeatures() throws DataStoreException {
isMovingFeature = true;
try (Store store = new Store(null, new StorageConnector(testData()))) {
verifyFeatureType(store.featureType, Polyline.class, Integer.MAX_VALUE);
assertEquals("foliation", Foliation.TIME, store.foliation);
final Iterator<AbstractFeature> it = store.features(false).iterator();
assertPropertyEquals(it.next(), "a", "12:33:51", "12:36:51", new double[] { 11, 2, 12, 3, 10, 3 }, singletonList("walking"), Arrays.asList(1, 2));
assertPropertyEquals(it.next(), "b", "12:33:51", "12:36:51", new double[] { 10, 2, 11, 3 }, singletonList("walking"), singletonList(2));
assertPropertyEquals(it.next(), "c", "12:33:51", "12:36:51", new double[] { 12, 1, 10, 2, 11, 3 }, singletonList("vehicle"), singletonList(1));
assertFalse(it.hasNext());
}
}
use of org.apache.sis.feature.AbstractFeature in project sis by apache.
the class InputFeatureStream method internalReadFeature.
/**
* Read next feature responding to the SQL query.
* @return Feature, null if no more feature is available.
* @throws SQLNotNumericException if a field expected numeric isn't.
* @throws SQLNotDateException if a field expected of date kind, isn't.
* @throws SQLNoSuchFieldException if a field doesn't exist.
* @throws SQLIllegalParameterException if a parameter is illegal in the query.
* @throws SQLInvalidStatementException if the SQL statement is invalid.
* @throws SQLConnectionClosedException if the connection is closed.
* @throws SQLUnsupportedParsingFeatureException if a SQL ability is not currently available through this driver.
* @throws SQLFeatureNotSupportedException if a SQL ability is not currently available through this driver.
* @throws InvalidShapefileFormatException if the shapefile format is invalid.
* @throws SQLNoDirectAccessAvailableException if the underlying SQL statement requires a direct access in the shapefile, but the shapefile cannot allow it.
*/
private AbstractFeature internalReadFeature() throws SQLConnectionClosedException, SQLInvalidStatementException, SQLIllegalParameterException, SQLNoSuchFieldException, SQLUnsupportedParsingFeatureException, SQLNotNumericException, SQLNotDateException, SQLFeatureNotSupportedException, InvalidShapefileFormatException, SQLNoDirectAccessAvailableException {
try {
if (this.endOfFile) {
return null;
}
int previousRecordNumber = this.rs.getRowNum();
if (this.rs.next() == false) {
this.endOfFile = true;
return null;
}
int currentRecordNumber = this.rs.getRowNum();
// On the shapefile, only jump in another place if a direct access is needed.
boolean directAccesRequired = currentRecordNumber != (previousRecordNumber + 1);
if (directAccesRequired) {
try {
if (LOGGER.isLoggable(Level.FINER)) {
MessageFormat format = new MessageFormat(this.rsc.getString("log.shapefile_reading_with_direct_access"));
LOGGER.finer(format.format(new Object[] { previousRecordNumber, currentRecordNumber }));
}
this.shapefileReader.setRowNum(currentRecordNumber);
} catch (SQLInvalidRecordNumberForDirectAccessException e) {
// This would be an internal API problem, because as soon as we handle a shapefile index, we shall go through its relative shape feature file correctly.
throw new RuntimeException(e.getMessage(), e);
}
} else {
if (LOGGER.isLoggable(Level.FINER)) {
MessageFormat format = new MessageFormat(this.rsc.getString("log.shapefile_reading_with_sequential_access"));
LOGGER.finer(format.format(new Object[] { previousRecordNumber, currentRecordNumber }));
}
}
AbstractFeature feature = this.featuresType.newInstance();
this.shapefileReader.completeFeature(feature);
DBFDatabaseMetaData metadata = (DBFDatabaseMetaData) this.connection.getMetaData();
try (DBFBuiltInMemoryResultSetForColumnsListing rsDatabase = (DBFBuiltInMemoryResultSetForColumnsListing) metadata.getColumns(null, null, null, null)) {
while (rsDatabase.next()) {
String fieldName = rsDatabase.getString("COLUMN_NAME");
Object fieldValue = this.rs.getObject(fieldName);
// FIXME To allow features to be filled again, the values are converted to String again : feature should allow any kind of data.
String stringValue;
if (fieldValue == null) {
stringValue = null;
} else {
if (fieldValue instanceof Integer || fieldValue instanceof Long) {
// Avoid thousand separator.
stringValue = MessageFormat.format("{0,number,#0}", fieldValue);
} else {
if (fieldValue instanceof Double || fieldValue instanceof Float) {
// Avoid thousand separator.
DecimalFormat df = new DecimalFormat();
df.setGroupingUsed(false);
stringValue = df.format(fieldValue);
} else
stringValue = fieldValue.toString();
}
}
feature.setPropertyValue(fieldName, stringValue);
}
return feature;
} catch (SQLNoResultException e) {
// This an internal trouble, if it occurs.
throw new RuntimeException(e.getMessage(), e);
}
} catch (SQLNoResultException e) {
// We are trying to prevent this. If it occurs, we have an internal problem.
throw new RuntimeException(e.getMessage(), e);
}
}
use of org.apache.sis.feature.AbstractFeature in project sis by apache.
the class WriterTest method testFeatures.
/**
* Writes way points, routes or tracks in the given store.
*
* @param store the store where to write.
* @param type the kind of feature to write: way point, route or track.
*/
private void testFeatures(final Store store, final Type type) throws Exception {
final Types types = Types.DEFAULT;
/*
* Way Points as defined in "waypoint.xml" test file.
* Appear also in "route.xml" and "track.xml" files.
*/
final AbstractFeature point1 = types.wayPoint.newInstance();
point1.setPropertyValue("sis:geometry", new Point(15, 10));
point1.setPropertyValue("time", Instant.parse("2010-01-10T00:00:00Z"));
point1.setPropertyValue("name", "first point");
point1.setPropertyValue("cmt", "first comment");
point1.setPropertyValue("desc", "first description");
point1.setPropertyValue("src", "first source");
point1.setPropertyValue("sym", "first symbol");
point1.setPropertyValue("type", "first type");
point1.setPropertyValue("ele", 140.0);
point1.setPropertyValue("magvar", 35.0);
point1.setPropertyValue("geoidheight", 112.32);
point1.setPropertyValue("sat", 11);
point1.setPropertyValue("hdop", 15.15);
point1.setPropertyValue("vdop", 14.14);
point1.setPropertyValue("pdop", 13.13);
point1.setPropertyValue("ageofdgpsdata", 55.55);
point1.setPropertyValue("dgpsid", 256);
point1.setPropertyValue("fix", Fix.NONE);
point1.setPropertyValue("link", Arrays.asList(new Link(new URI("http://first-address1.org")), new Link(new URI("http://first-address2.org")), new Link(new URI("http://first-address3.org"))));
final AbstractFeature point3 = types.wayPoint.newInstance();
point3.setPropertyValue("sis:geometry", new Point(35, 30));
point3.setPropertyValue("time", Instant.parse("2010-01-30T00:00:00Z"));
point3.setPropertyValue("name", "third point");
point3.setPropertyValue("cmt", "third comment");
point3.setPropertyValue("desc", "third description");
point3.setPropertyValue("src", "third source");
point3.setPropertyValue("sym", "third symbol");
point3.setPropertyValue("type", "third type");
point3.setPropertyValue("ele", 150.0);
point3.setPropertyValue("magvar", 25.0);
point3.setPropertyValue("geoidheight", 142.32);
point3.setPropertyValue("sat", 35);
point3.setPropertyValue("hdop", 35.15);
point3.setPropertyValue("vdop", 34.14);
point3.setPropertyValue("pdop", 33.13);
point3.setPropertyValue("ageofdgpsdata", 85.55);
point3.setPropertyValue("dgpsid", 456);
point3.setPropertyValue("fix", Fix.THREE_DIMENSIONAL);
point3.setPropertyValue("link", Arrays.asList(new Link(new URI("http://third-address1.org")), new Link(new URI("http://third-address2.org"))));
final AbstractFeature point2 = types.wayPoint.newInstance();
point2.setPropertyValue("sis:geometry", new Point(25, 20));
final List<AbstractFeature> wayPoints = Arrays.asList(point1, point2, point3);
final List<AbstractFeature> features;
switch(type) {
case WAY_POINT:
{
features = wayPoints;
break;
}
case ROUTE:
{
final AbstractFeature route1 = types.route.newInstance();
route1.setPropertyValue("name", "Route name");
route1.setPropertyValue("cmt", "Route comment");
route1.setPropertyValue("desc", "Route description");
route1.setPropertyValue("src", "Route source");
route1.setPropertyValue("type", "Route type");
route1.setPropertyValue("number", 7);
route1.setPropertyValue("rtept", wayPoints);
route1.setPropertyValue("link", Arrays.asList(new Link(new URI("http://route-address1.org")), new Link(new URI("http://route-address2.org")), new Link(new URI("http://route-address3.org"))));
final AbstractFeature route2 = types.route.newInstance();
features = Arrays.asList(route1, route2);
break;
}
case TRACK:
{
final AbstractFeature seg1 = types.trackSegment.newInstance();
final AbstractFeature seg2 = types.trackSegment.newInstance();
seg1.setPropertyValue("trkpt", wayPoints);
final AbstractFeature track1 = types.track.newInstance();
track1.setPropertyValue("name", "Track name");
track1.setPropertyValue("cmt", "Track comment");
track1.setPropertyValue("desc", "Track description");
track1.setPropertyValue("src", "Track source");
track1.setPropertyValue("type", "Track type");
track1.setPropertyValue("number", 7);
track1.setPropertyValue("trkseg", Arrays.asList(seg1, seg2));
track1.setPropertyValue("link", Arrays.asList(new Link(new URI("http://track-address1.org")), new Link(new URI("http://track-address2.org")), new Link(new URI("http://track-address3.org"))));
final AbstractFeature track2 = types.track.newInstance();
features = Arrays.asList(track1, track2);
break;
}
default:
throw new AssertionError(type);
}
/*
* Add minimalist metadata and marshal.
*/
final Bounds bounds = new Bounds();
bounds.westBoundLongitude = -20;
bounds.eastBoundLongitude = 30;
bounds.southBoundLatitude = 10;
bounds.northBoundLatitude = 40;
final Metadata metadata = new Metadata();
metadata.bounds = bounds;
metadata.creator = "DataProducer";
store.write(metadata, features.stream());
}
Aggregations