/* Copyright 2013 The jeo project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.jeo.geopkg;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import io.jeo.vector.Feature;
import io.jeo.vector.FeatureCursor;
import io.jeo.vector.Field;
import io.jeo.vector.ListFeature;
import io.jeo.vector.Schema;
import io.jeo.geopkg.geom.GeoPkgGeomReader;
import io.jeo.sql.PrimaryKey;
import io.jeo.sql.PrimaryKeyColumn;
import com.vividsolutions.jts.geom.Geometry;
import io.jeo.sql.Backend.Session;
import io.jeo.sql.Backend.Results;
import io.jeo.vector.SchemaBuilder;
public class GeoPkgFeatureCursor extends FeatureCursor {
final FeatureEntry entry;
final GeoPkgWorkspace workspace;
final Schema schema;
final PrimaryKey primaryKey;
final GeoPkgGeomReader geomReader;
final List<Field> fields;
// index of primary key columns in result set
final List<Integer> pkColumns;
// reusable holder for values as BasicFeature will copy these out
final List<Object> values;
// reusable buffer for generating fid
final StringBuilder buf = new StringBuilder();
Session session;
boolean closeSession = true;
Results results;
Boolean next;
Feature feature;
GeoPkgFeatureCursor(Session session, Results results, FeatureEntry entry, GeoPkgWorkspace workspace,
Schema schema, PrimaryKey primaryKey, List<String> fields)
throws IOException {
this.session = session;
this.results = results;
this.entry = entry;
this.workspace = workspace;
this.primaryKey = primaryKey;
geomReader = new GeoPkgGeomReader();
if (!fields.isEmpty()) {
// requested fields in schema require rebuilding schema
this.schema = SchemaBuilder.select(schema, fields);
} else {
this.schema = schema;
}
this.fields = this.schema.fields();
values = new ArrayList<Object>(schema.fields().size());
pkColumns = new ArrayList<Integer>(primaryKey.getColumns().size());
int end = fields.size();
for (PrimaryKeyColumn pkcol : primaryKey.getColumns()) {
// if schema has reduced fields, they will be present in the end
int idx = this.schema.indexOf(pkcol.getName());
if (idx >= 0) {
pkColumns.add(idx);
} else {
pkColumns.add(end++);
}
}
}
public GeoPkgFeatureCursor closeSession(boolean closeSession) {
this.closeSession = closeSession;
return this;
}
@Override
public boolean hasNext() throws IOException {
if (next == null) {
try {
next = results.next();
} catch (Exception e) {
throw new IOException(e);
}
}
return next;
}
@Override
public Feature next() throws IOException {
try {
if (next != null && next) {
try {
values.clear();
for (int i = 0; i < fields.size(); i++) {
Class type = fields.get(i).type();
if (Geometry.class.isAssignableFrom(type)) {
byte[] bytes = results.getBytes(i);
values.add(bytes != null ? geomReader.read(bytes) : null);
}
else {
values.add(results.getObject(i,type));
}
}
String fid = null;
if (!pkColumns.isEmpty()) {
buf.delete(0, buf.length());
for (int i = 0; i < pkColumns.size(); i++) {
Object obj = results.getString(pkColumns.get(i));
if (obj != null) {
buf.append(obj);
}
buf.append(".");
}
if (buf.length() > 0) {
buf.setLength(buf.length() - 1);
}
fid = buf.toString();
}
return feature = new ListFeature(fid, schema, values);
} finally {
next = null;
}
}
return null;
} catch (Exception e) {
throw new IOException(e);
}
}
@Override
public void close() throws IOException {
if (results != null) {
results.close();
results = null;
}
if (session != null) {
if (closeSession) session.close();
session = null;
}
}
}