package jeql.command.db.sde;
import java.sql.Date;
import java.sql.SQLException;
import java.util.Calendar;
import jeql.api.row.BasicRow;
import jeql.api.row.Row;
import jeql.api.row.RowSchema;
import jeql.engine.ConfigurationException;
import jeql.api.error.*;
import jeql.std.geom.GeomFunction;
import com.esri.sde.sdk.client.SeColumnDefinition;
import com.esri.sde.sdk.client.SeException;
import com.esri.sde.sdk.client.SeQuery;
import com.esri.sde.sdk.client.SeRow;
import com.esri.sde.sdk.client.SeShape;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.io.sde.SdeReader;
public class SdeRowMapper {
private SdeReader sdeRdr = new SdeReader(GeomFunction.geomFactory);
public SdeRowMapper() {
}
public RowSchema getSchema(SeQuery query) throws SeException {
int ncols = query.getNumColumns();
String[] names = new String[ncols];
Class[] types = new Class[ncols];
for (int i = 0; i < ncols; i++) {
SeColumnDefinition colDef = query.describeColumn(i);
names[i] = colDef.getName();
types[i] = mapColumnType(colDef);
if (types[i] == null) {
throw new ExecutionException("SQL type is not currently handled");
}
}
RowSchema schema = new RowSchema(names, types);
return schema;
}
public Row createRow(RowSchema schema, SeRow seRow) throws Exception {
BasicRow row = new BasicRow(schema.size());
for (int i = 0; i < schema.size(); i++) {
row.setValue(i, mapColumnValue(seRow, i, schema.getType(i)));
}
return row;
}
/**
*
* @param rm
* @param colIndex
* @return null if the column type is not handled
* @throws SQLException
*/
protected Class mapColumnType(SeColumnDefinition colDef)
// throws SeException
{
int type = colDef.getType();
switch (type) {
case SeColumnDefinition.TYPE_INT16:
case SeColumnDefinition.TYPE_INT32:
return Integer.class;
case SeColumnDefinition.TYPE_INT64:
case SeColumnDefinition.TYPE_FLOAT32:
case SeColumnDefinition.TYPE_FLOAT64:
return Double.class;
case SeColumnDefinition.TYPE_SHAPE:
return Geometry.class;
case SeColumnDefinition.TYPE_DATE:
return Date.class;
default:
return String.class;
}
}
protected Object mapColumnValue(SeRow row, int columnIndex, Class destType)
throws Exception {
if (destType == String.class) {
return row.getString(columnIndex);
}
if (destType == Integer.class) {
// not very efficient? (cache types for columns?)
if (row.getColumnDef(columnIndex).getType() == SeColumnDefinition.TYPE_INT16)
return toInteger((Short) row.getShort(columnIndex));
return row.getInteger(columnIndex);
}
if (destType == Double.class) {
return row.getDouble(columnIndex);
}
if (destType == Date.class) {
Calendar cal = row.getTime(columnIndex);
if (cal == null) return cal;
return cal.getTime();
}
if (destType == Geometry.class) {
return toGeometry(row.getShape(columnIndex));
}
throw new ConfigurationException("Unhandled SDE value mapping for class "
+ destType.getName());
}
private static final Integer toInteger(Short val) {
return new Integer(val.intValue());
}
private Geometry toGeometry(SeShape shape) throws SeException {
try {
return sdeRdr.read(shape);
}
// ignore geometry conversion errors
catch (IllegalArgumentException e) {
return null;
}
// return SeShapeConverter.convert(shape);
}
}