* @param options OGR data source/layer creation options
* @throws IOException
*/
public void createSchema(SimpleFeatureCollection data, boolean approximateFields,
String[] options) throws IOException {
Pointer dataSource = null;
Pointer layer = null;
SimpleFeatureType schema = data.getSchema();
SimpleFeatureIterator features;
try {
// either open datasource, or try creating one
Pointer<Pointer<Byte>> optionsPointer = null;
if (options != null && options.length > 0) {
optionsPointer = pointerToCStrings(options);
}
dataSource = openOrCreateDataSource(options, dataSource, optionsPointer);
FeatureTypeMapper mapper = new FeatureTypeMapper();
layer = createNewLayer(schema, dataSource, optionsPointer, mapper);
// check the ability to create fields
if (OGR_L_TestCapability(layer, pointerToCString(OLCCreateField)) == 0) {
throw new DataSourceException(
"OGR reports it's not possible to create fields on this layer");
}
// create fields
Map<String, String> nameMap = new HashMap<String, String>();
for (int i = 0, j = 0; i < schema.getAttributeCount(); i++) {
AttributeDescriptor ad = schema.getDescriptor(i);
if (ad == schema.getGeometryDescriptor()) {
continue;
}
Pointer fieldDefinition = mapper.getOGRFieldDefinition(ad);
OGR_L_CreateField(layer, fieldDefinition, approximateFields ? 1 : 0);
// the data source might have changed the name of the field, map them
String newName = getCString(OGR_Fld_GetNameRef(fieldDefinition));
nameMap.put(newName, ad.getLocalName());
j++;
}
// get back the feature definition
Pointer layerDefinition = OGR_L_GetLayerDefn(layer);
// remap positions, as the store might add extra attributes (and the field api is
// positional)
Map<Integer, Integer> indexMap = new HashMap<Integer, Integer>();
int count = OGR_FD_GetFieldCount(layerDefinition);
for (int i = 0; i < count; i++) {
Pointer fd = OGR_FD_GetFieldDefn(layerDefinition, i);
String newName = getCString(OGR_Fld_GetNameRef(fd));
if (newName != null) {
String oldName = nameMap.get(newName);
for (int j = 0; j < schema.getAttributeCount(); j++) {
if (schema.getDescriptor(j).getLocalName().equals(oldName)) {
indexMap.put(j, i);
}
}
}
}
// iterate and write out without going throught the ContentDataStore api, which
// assumes it's possible to let go of it later
GeometryMapper geomMapper = new GeometryMapper.WKB(new GeometryFactory());
features = data.features();
while (features.hasNext()) {
SimpleFeature feature = features.next();
// create the equivalent ogr feature
Pointer ogrFeature = OGR_F_Create(layerDefinition);
for (int i = 0; i < schema.getAttributeCount(); i++) {
Object value = feature.getAttribute(i);
if (value instanceof Geometry) {
// using setGeoemtryDirectly the feature becomes the owner of the generated
// OGR geometry and we don't have to .delete() it (it's faster, too)
Pointer geometry = geomMapper.parseGTGeometry((Geometry) value);
OGR_F_SetGeometryDirectly(ogrFeature, geometry);
} else {
// remap index
int ogrIndex = indexMap.get(i);
FeatureMapper.setFieldValue(layerDefinition, ogrFeature, ogrIndex, value);