/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2007-2012, 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.geotools.data.ogr.bridj;
import static org.bridj.Pointer.allocateInt;
import static org.bridj.Pointer.allocatePointer;
import static org.bridj.Pointer.pointerToBytes;
import static org.bridj.Pointer.pointerToCString;
import static org.bridj.Pointer.pointerToPointer;
import static org.geotools.data.ogr.bridj.BridjUtilities.getCString;
import static org.geotools.data.ogr.bridj.BridjUtilities.pointerToCStrings;
import static org.geotools.data.ogr.bridj.CplErrorLibrary.CPLGetLastErrorMsg;
import static org.geotools.data.ogr.bridj.OgrLibrary.*;
import static org.geotools.data.ogr.bridj.OsrLibrary.*;
import java.io.IOException;
import org.bridj.Pointer;
import org.geotools.data.ogr.OGR;
import org.geotools.data.ogr.bridj.OgrLibrary.OGRFieldType;
import org.geotools.data.ogr.bridj.OgrLibrary.OGRJustification;
import org.geotools.data.ogr.bridj.OgrLibrary.OGRwkbByteOrder;
import org.geotools.data.ogr.bridj.OgrLibrary.OGRwkbGeometryType;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
/**
* Interacts with OGR via the bridj library.
*
* @author Andrea Aime, GeoSolutions
* @author Justin Deoliveira, OpenGeo
*/
public class BridjOGR implements OGR {
static {
GdalInit.init();
// perform OGR format registration once
if (OGRGetDriverCount() == 0) {
OGRRegisterAll();
}
}
@Override
public int GetDriverCount() {
return OGRGetDriverCount();
}
@Override
public Object GetDriver(int i) {
return OGRGetDriver(i);
}
@Override
public Object GetDriverByName(String name) {
return OGRGetDriverByName(pointerToCString(name));
}
@Override
public Object OpenShared(String dataSourceName, int mode) {
return OGROpenShared(pointerToCString(dataSourceName), mode, null);
}
@Override
public Object Open(String dataSourceName, int mode) {
return OGROpen(pointerToCString(dataSourceName), mode, null);
}
@Override
public void CheckError(int code) throws IOException {
if (code == OGRERR_NONE) {
return;
}
String error = getCString(CPLGetLastErrorMsg());
switch (code) {
case OGRERR_CORRUPT_DATA:
throw new IOException("OGR reported a currupt data error: " + error);
case OGRERR_FAILURE:
throw new IOException("OGR reported a generic failure: " + error);
case OGRERR_INVALID_HANDLE:
throw new IOException("OGR reported an invalid handle error: " + error);
case OGRERR_NOT_ENOUGH_DATA:
throw new IOException("OGR reported not enough data was provided in the last call: " + error);
case OGRERR_NOT_ENOUGH_MEMORY:
throw new IOException("OGR reported not enough memory is available: " + error);
case OGRERR_UNSUPPORTED_GEOMETRY_TYPE:
throw new IOException("OGR reported a unsupported geometry type error: " + error);
case OGRERR_UNSUPPORTED_OPERATION:
throw new IOException("OGR reported a unsupported operation error: " + error);
case OGRERR_UNSUPPORTED_SRS:
throw new IOException("OGR reported a unsupported SRS error: " + error);
default:
throw new IOException("OGR reported an unrecognized error code: " + code);
}
}
@Override
public String GetLastErrorMsg() {
return getCString(CPLGetLastErrorMsg());
}
@Override
public String DriverGetName(Object driver) {
return getCString(OGR_Dr_GetName((Pointer<?>)driver));
}
@Override
public Object DriverOpen(Object driver, String dataSourceName, int mode) {
return OGR_Dr_Open((Pointer<?>)driver, pointerToCString(dataSourceName), mode);
}
@Override
public Object DriverCreateDataSource(Object driver, String dataSourceName,
String[] opts) {
return OGR_Dr_CreateDataSource((Pointer<?>)driver, pointerToCString(dataSourceName),
pointerToCStrings(opts));
}
@Override
public void DriverRelease(Object driver) {
((Pointer<?>)driver).release();
}
@Override
public Object DataSourceGetDriver(Object dataSource) {
return (Pointer<?>) OGR_DS_GetDriver((Pointer<?>)dataSource);
}
@Override
public int DataSourceGetLayerCount(Object dataSource) {
return OGR_DS_GetLayerCount((Pointer<?>)dataSource);
}
@Override
public Object DataSourceGetLayer(Object dataSource, int i) {
return OGR_DS_GetLayer((Pointer<?>)dataSource, i);
}
@Override
public Object DataSourceGetLayerByName(Object dataSource, String name) {
return OGR_DS_GetLayerByName((Pointer<?>)dataSource, pointerToCString(name));
}
@Override
public void DataSourceRelease(Object dataSource) {
OGRUtils.releaseDataSource((Pointer<?>)dataSource);
}
@Override
public Object DataSourceCreateLayer(Object dataSource, String name,
Object spatialReference, long geomType, String[] opts) {
return OGR_DS_CreateLayer((Pointer<?>)dataSource, pointerToCString(name),
(Pointer<?>)spatialReference, OGRwkbGeometryType.fromValue(geomType),
BridjUtilities.pointerToCStrings(opts));
}
@Override
public Object DataSourceExecuteSQL(Object dataSource, String sql, Object spatialFilter) {
return OGR_DS_ExecuteSQL((Pointer<?>)dataSource, pointerToCString(sql), (Pointer<?>)spatialFilter, null);
}
@Override
public Object LayerGetLayerDefn(Object layer) {
return OGR_L_GetLayerDefn((Pointer<?>)layer);
}
@Override
public int LayerGetFieldCount(Object layerDefn) {
return OGR_FD_GetFieldCount((Pointer<?>)layerDefn);
}
@Override
public Object LayerGetFieldDefn(Object layerDefn, int i) {
return OGR_FD_GetFieldDefn((Pointer<?>)layerDefn, i);
}
@Override
public String LayerGetName(Object layer) {
return getCString(OGR_L_GetName((Pointer<?>)layer));
}
@Override
public long LayerGetGeometryType(Object layerDefn) {
return OGR_FD_GetGeomType((Pointer<?>)layerDefn).value();
}
@Override
public Object LayerGetSpatialRef(Object layer) {
return OGR_L_GetSpatialRef((Pointer<?>)layer);
}
@Override
public Object LayerGetExtent(Object layer) {
Pointer<OGREnvelope> boundsPtr = Pointer.allocate(OGREnvelope.class);
int code = OGR_L_GetExtent((Pointer<?>)layer, boundsPtr, 0);
if (code == OGRERR_FAILURE) {
return null;
}
return boundsPtr;
}
@Override
public long LayerGetFeatureCount(Object layer) {
return OGR_L_GetFeatureCount((Pointer<?>)layer, 0);
}
@Override
public void LayerRelease(Object layer) {
OGRUtils.releaseLayer((Pointer<?>)layer);
}
@Override
public void LayerReleaseLayerDefn(Object layerDefn) {
OGRUtils.releaseDefinition((Pointer<?>) layerDefn);
}
@Override
public boolean LayerCanDeleteFeature(Object layer) {
return OGR_L_TestCapability((Pointer<?>)layer, pointerToCString(OLCDeleteFeature)) != 0;
}
@Override
public boolean LayerCanWriteRandom(Object layer) {
return OGR_L_TestCapability((Pointer<?>)layer, pointerToCString(OLCRandomWrite)) != 0;
}
@Override
public boolean LayerCanWriteSequential(Object layer) {
return OGR_L_TestCapability((Pointer<?>)layer,pointerToCString(OLCSequentialWrite)) != 0;
}
@Override
public boolean LayerCanCreateField(Object layer) {
return OGR_L_TestCapability((Pointer<?>)layer, pointerToCString(OLCCreateField)) != 0;
}
@Override
public boolean LayerCanIgnoreFields(Object layer) {
return OGR_L_TestCapability((Pointer<?>)layer, pointerToCString(OLCIgnoreFields)) != 0;
}
@Override
public void LayerCreateField(Object layer, Object fieldDefn, int approx) {
OGR_L_CreateField((Pointer<?>)layer, (Pointer<?>)fieldDefn, approx);
}
@Override
public void LayerSyncToDisk(Object layer) {
OGR_L_SyncToDisk((Pointer<?>)layer);
}
@Override
public Object LayerNewFeature(Object layerDefn) {
return OGR_F_Create((Pointer<?>)layerDefn);
}
@Override
public ReferencedEnvelope toEnvelope(Object extent,
CoordinateReferenceSystem crs) {
OGREnvelope bounds = ((Pointer<OGREnvelope>)extent).get();
return new ReferencedEnvelope(bounds.MinX(), bounds.MaxX(), bounds.MinY(),
bounds.MaxY(), crs);
}
@Override
public void LayerSetSpatialFilter(Object layer, Object geometry) {
OGR_L_SetSpatialFilter((Pointer<?>)layer, (Pointer<?>)geometry);
}
@Override
public void LayerSetAttributeFilter(Object layer, String attFilter) {
OGR_L_SetAttributeFilter((Pointer<?>)layer, pointerToCString(attFilter));
}
@Override
public int LayerSetIgnoredFields(Object layer, String[] fields) {
Pointer<Pointer<Byte>> ifPtr = BridjUtilities.pointerToCStrings(fields);
return OGR_L_SetIgnoredFields((Pointer<?>)layer, ifPtr);
}
@Override
public void LayerResetReading(Object layer) {
OGR_L_ResetReading((Pointer<?>)layer);
}
@Override
public Object LayerGetNextFeature(Object layer) {
return OGR_L_GetNextFeature((Pointer<?>)layer);
}
@Override
public boolean LayerDeleteFeature(Object layer, long fid) {
return OGR_L_DeleteFeature((Pointer<?>)layer, fid) == 0;
}
@Override
public int LayerSetFeature(Object layer, Object feature) {
return OGR_L_SetFeature((Pointer<?>)layer, (Pointer<?>)feature);
}
@Override
public int LayerCreateFeature(Object layer, Object feature) {
return OGR_L_CreateFeature((Pointer<?>)layer, (Pointer<?>)feature);
}
@Override
public String LayerGetFIDColumnName(Object layer) {
return getCString(OGR_L_GetFIDColumn((Pointer<?>) layer));
}
@Override
public String FieldGetName(Object field) {
return getCString(OGR_Fld_GetNameRef((Pointer<?>)field));
}
@Override
public long FieldGetType(Object field) {
return OGR_Fld_GetType((Pointer<?>)field).value();
}
@Override
public int FieldGetWidth(Object field) {
return OGR_Fld_GetWidth((Pointer<?>)field);
}
@Override
public void FieldSetWidth(Object field, int width) {
OGR_Fld_SetWidth((Pointer<?>)field, width);
}
@Override
public void FieldSetJustifyRight(Object field) {
OGR_Fld_SetJustify((Pointer<?>)field, OGRJustification.OJRight);
}
@Override
public void FieldSetPrecision(Object field, int precision) {
OGR_Fld_SetPrecision((Pointer<?>)field, 15);
}
@Override
public boolean FieldIsIntegerType(long type) {
return type == OGRFieldType.OFTInteger.value();
}
@Override
public boolean FieldIsRealType(long type) {
return type == OGRFieldType.OFTReal.value();
}
@Override
public boolean FieldIsBinaryType(long type) {
return type == OGRFieldType.OFTBinary.value();
}
@Override
public boolean FieldIsDateType(long type) {
return type == OGRFieldType.OFTDate.value();
}
@Override
public boolean FieldIsTimeType(long type) {
return type == OGRFieldType.OFTTime.value();
}
@Override
public boolean FieldIsDateTimeType(long type) {
return type == OGRFieldType.OFTDateTime.value();
}
@Override
public boolean FieldIsIntegerListType(long type) {
return type == OGRFieldType.OFTIntegerList.value();
}
@Override
public boolean FieldIsRealListType(long type) {
return type == OGRFieldType.OFTRealList.value();
}
@Override
public Object CreateStringField(String name) {
return OGR_Fld_Create(pointerToCString(name), OGRFieldType.OFTString);
}
@Override
public Object CreateIntegerField(String name) {
return OGR_Fld_Create(pointerToCString(name), OGRFieldType.OFTInteger);
}
@Override
public Object CreateRealField(String name) {
return OGR_Fld_Create(pointerToCString(name), OGRFieldType.OFTReal);
}
@Override
public Object CreateBinaryField(String name) {
return OGR_Fld_Create(pointerToCString(name), OGRFieldType.OFTBinary);
}
@Override
public Object CreateDateField(String name) {
return OGR_Fld_Create(pointerToCString(name), OGRFieldType.OFTDate);
}
@Override
public Object CreateTimeField(String name) {
return OGR_Fld_Create(pointerToCString(name), OGRFieldType.OFTTime);
}
@Override
public Object CreateDateTimeField(String name) {
return OGR_Fld_Create(pointerToCString(name), OGRFieldType.OFTDateTime);
}
@Override
public long FeatureGetFID(Object feature) {
return OGR_F_GetFID((Pointer<?>)feature);
}
@Override
public boolean FeatureIsFieldSet(Object feature, int i) {
return OGR_F_IsFieldSet((Pointer<?>)feature, i) != 0;
}
@Override
public void FeatureSetGeometryDirectly(Object feature, Object geometry) {
OGR_F_SetGeometryDirectly((Pointer<?>)feature, (Pointer<?>)geometry);
}
@Override
public Object FeatureGetGeometry(Object feature) {
return OGR_F_GetGeometryRef((Pointer<?>)feature);
}
@Override
public void FeatureUnsetField(Object feature, int i) {
OGR_F_UnsetField((Pointer<?>)feature, i);
}
@Override
public void FeatureSetFieldInteger(Object feature, int field, int value) {
OGR_F_SetFieldInteger((Pointer<?>)feature, field, value);
}
@Override
public void FeatureSetFieldDouble(Object feature, int field, double value) {
OGR_F_SetFieldDouble((Pointer<?>)feature, field, value);
}
@Override
public void FeatureSetFieldBinary(Object feature, int field, int length, byte[] value) {
OGR_F_SetFieldBinary((Pointer<?>)feature, field, value.length, pointerToBytes(value));
}
@Override
public void FeatureSetFieldDateTime(Object feature, int field, int year,
int month, int day, int hour, int minute, int second, int tz) {
OGR_F_SetFieldDateTime((Pointer<?>)feature, field, year, month, day, hour, minute, second, tz);
}
@Override
public void FeatureSetFieldString(Object feature, int field, String str) {
OGR_F_SetFieldString((Pointer<?>)feature, field, pointerToCString(str));
}
@Override
public String FeatureGetFieldAsString(Object feature, int i) {
return getCString(OGR_F_GetFieldAsString((Pointer<?>)feature, i));
}
@Override
public int FeatureGetFieldAsInteger(Object feature, int i) {
return OGR_F_GetFieldAsInteger((Pointer<?>)feature, i);
}
@Override
public double FeatureGetFieldAsDouble(Object feature, int i) {
return OGR_F_GetFieldAsDouble((Pointer<?>)feature, i);
}
@Override
public void FeatureGetFieldAsDateTime(Object feature, int i, int[] yeara, int[] montha,
int[] daya, int[] houra, int[] minutea, int[] seconda, int[] tzFlag) {
Pointer<Integer> year = allocateInt();
Pointer<Integer> month = allocateInt();
Pointer<Integer> day = allocateInt();
Pointer<Integer> hour = allocateInt();
Pointer<Integer> minute = allocateInt();
Pointer<Integer> second = allocateInt();
Pointer<Integer> timeZone = allocateInt();
OGR_F_GetFieldAsDateTime((Pointer<?>)feature, i, year, month, day, hour, minute, second, timeZone);
yeara[0] = year.getInt();
montha[0] = month.getInt();
daya[0] = day.getInt();
houra[0] = hour.getInt();
minutea[0] = minute.getInt();
seconda[0] = second.getInt();
tzFlag[0] = timeZone.getInt();
}
@Override
public void FeatureDestroy(Object feature) {
OGR_F_Destroy((Pointer<?>)feature);
}
@Override
public long GetPointType() {
return OGRwkbGeometryType.wkbPoint.value();
}
@Override
public long GetPoint25DType() {
return OGRwkbGeometryType.wkbPoint25D.value();
}
@Override
public long GetLinearRingType() {
return OGRwkbGeometryType.wkbLinearRing.value();
}
@Override
public long GetLineStringType() {
return OGRwkbGeometryType.wkbLineString.value();
}
@Override
public long GetLineString25DType() {
return OGRwkbGeometryType.wkbLineString25D.value();
}
@Override
public long GetPolygonType() {
return OGRwkbGeometryType.wkbPolygon.value();
}
@Override
public long GetPolygon25DType() {
return OGRwkbGeometryType.wkbPolygon25D.value();
}
@Override
public long GetMultiPointType() {
return OGRwkbGeometryType.wkbMultiPoint.value();
}
@Override
public long GetMultiLineStringType() {
return OGRwkbGeometryType.wkbMultiLineString.value();
}
@Override
public long GetMultiLineString25DType() {
return OGRwkbGeometryType.wkbMultiLineString25D.value();
}
@Override
public long GetMultiPolygonType() {
return OGRwkbGeometryType.wkbMultiPolygon.value();
}
@Override
public long GetMultiPolygon25DType() {
return OGRwkbGeometryType.wkbMultiPolygon25D.value();
}
@Override
public long GetGeometryCollectionType() {
return OGRwkbGeometryType.wkbGeometryCollection.value();
}
@Override
public long GetGeometryCollection25DType() {
return OGRwkbGeometryType.wkbGeometryCollection25D.value();
}
@Override
public long GetGeometryNoneType() {
return OGRwkbGeometryType.wkbNone.value();
}
@Override
public long GetGeometryUnknownType() {
return OGRwkbGeometryType.wkbUnknown.value();
}
@Override
public int GeometryGetWkbSize(Object geom) {
return OGR_G_WkbSize((Pointer<?>)geom);
}
@Override
public int GeometryExportToWkb(Object geom, byte[] wkb) {
Pointer<Byte> p = pointerToBytes(wkb);
int ret = OGR_G_ExportToWkb((Pointer<?>)geom, OGRwkbByteOrder.wkbXDR, p);
System.arraycopy(p.getBytes(), 0, wkb, 0, wkb.length);
return ret;
}
@Override
public Object GeometryCreateFromWkb(byte[] wkb, int[] ret) {
Pointer<Pointer<?>> ptr = allocatePointer();
ret[0] = OGR_G_CreateFromWkb(pointerToBytes(wkb), null, ptr, wkb.length);
return ptr.getPointer(Pointer.class);
}
@Override
public String GeometryExportToWkt(Object geom, int[] ret) {
Pointer<Pointer<Byte>> wktPtr = allocatePointer(Byte.class);
ret[0] = OGR_G_ExportToWkt((Pointer<?>)geom, wktPtr);
return getCString(wktPtr.getPointer(Byte.class));
}
@Override
public Object GeometryCreateFromWkt(String wkt, int[] ret) {
Pointer<Pointer<Byte>> ptr = pointerToPointer(pointerToCString(wkt));
Pointer<Pointer<?>> geom = allocatePointer();
ret[0] = OGR_G_CreateFromWkt(ptr, null, geom);
return geom.getPointer(Pointer.class);
}
@Override
public void GeometryDestroy(Object geometry) {
OGR_G_DestroyGeometry((Pointer<?>)geometry);
}
@Override
public String SpatialRefGetAuthorityCode(Object spatialRef, String authority) {
return getCString(OSRGetAuthorityCode((Pointer<?>)spatialRef, pointerToCString(authority)));
}
@Override
public String SpatialRefExportToWkt(Object spatialRef) {
Pointer<Pointer<Byte>> wktPtr = allocatePointer(Byte.class);
OSRExportToWkt((Pointer<?>)spatialRef, wktPtr);
return getCString(wktPtr.getPointer(Byte.class));
}
@Override
public void SpatialRefRelease(Object spatialRef) {
OGRUtils.releaseSpatialReference((Pointer<?>) spatialRef);
}
@Override
public Object NewSpatialRef(String wkt) {
return OSRNewSpatialReference(pointerToCString(wkt));
}
}