/* * GeoTools - The Open Source Java GIS Toolkit * http://geotools.org * * (C) 2002-2008, 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.teradata; import java.io.IOException; import java.io.InputStream; import java.sql.Blob; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Types; import org.geotools.data.DataSourceException; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.GeometryFactory; import com.vividsolutions.jts.io.InStream; import com.vividsolutions.jts.io.WKBReader; import com.vividsolutions.jts.io.WKBWriter; /** * An attribute IO implementation that can manage the WKB * * @author Andrea Aime * * @source $URL: http://svn.osgeo.org/geotools/trunk/modules/plugin/jdbc/jdbc-teradata/src/main/java/org/geotools/data/teradata/WKBAttributeIO.java $ * @since 2.4.1 */ public class WKBAttributeIO { WKBReader wkbr; ByteArrayInStream byteArrayInStream = new ByteArrayInStream(); InputStreamInStream inputStreamInStream = new InputStreamInStream(); public WKBAttributeIO() { wkbr = new WKBReader(); } public WKBAttributeIO(GeometryFactory gf) { wkbr = new WKBReader(gf); } /** * This method will convert a Well Known Binary representation to a JTS * Geometry object. * * @return a JTS Geometry object that is equivalent to the WTB * representation passed in by param wkb * @throws IOException * if more than one geometry object was found in the WTB * representation, or if the parser could not parse the WKB * representation. */ public Geometry wkb2Geometry(byte[] wkbBytes) throws IOException { if (wkbBytes == null) // DJB: null value from database --> null geometry // (the same behavior as WKT). NOTE: sending back // a GEOMETRYCOLLECTION(EMPTY) is also a // possibility, but this is not the same as NULL return null; try { byteArrayInStream.setBytes(wkbBytes); return wkbr.read(byteArrayInStream); } catch (Exception e) { throw new DataSourceException("An exception occurred while parsing WKB data", e); } } public Geometry wkb2Geometry(InputStream inputStream) throws IOException { if (inputStream == null) // DJB: null value from database --> null // geometry (the same behavior as WKT). NOTE: // sending back a GEOMETRYCOLLECTION(EMPTY) is // also a possibility, but this is not the same // as NULL return null; try { inputStreamInStream.setIn(inputStream); return wkbr.read(inputStreamInStream); } catch (Exception e) { throw new DataSourceException("An exception occurred while parsing WKB data", e); } } /** * @see org.geotools.data.jdbc.attributeio.AttributeIO#read(java.sql.ResultSet, * int) */ public Geometry read(ResultSet rs, String columnName) throws IOException { try { return read(rs, rs.findColumn(columnName)); } catch (SQLException e) { throw new IllegalArgumentException("columnName " + e + " is not a column in result set"); } } /** * @see org.geotools.data.jdbc.attributeio.AttributeIO#read(java.sql.ResultSet, * int) */ public Geometry read(ResultSet rs, int columnIndex) throws IOException { try { switch (rs.getMetaData().getColumnType(columnIndex)) { case Types.BLOB: return readFromBlob(rs, columnIndex); default: return readFromBytes(rs, columnIndex); } } catch (SQLException e) { throw new DataSourceException("SQL exception occurred while reading the geometry.", e); } } /** * @see org.geotools.data.jdbc.attributeio.AttributeIO#read(java.sql.ResultSet, * int) */ private Geometry readFromBytes(ResultSet rs, int columnIndex) throws IOException { try { return wkb2Geometry(rs.getBytes(columnIndex)); } catch (SQLException e) { throw new DataSourceException("SQL exception occurred while reading the geometry.", e); } } private Geometry doReadFromBlob(Blob blob) throws IOException { if (blob == null) { return null; } InputStream is = null; try { is = blob.getBinaryStream(); if (is == null || is.available() == 0) // ie. its a 0 length column // -> return a null geometry! return null; return wkb2Geometry(is); } catch (SQLException e) { throw new DataSourceException("SQL exception occurred while reading the geometry.", e); } finally { if (is != null) { is.close(); } } } /** * @see org.geotools.data.jdbc.attributeio.AttributeIO#read(java.sql.ResultSet, * int) */ private Geometry readFromBlob(ResultSet rs, int columnIndex) throws IOException { try { return doReadFromBlob(rs.getBlob(columnIndex)); } catch (SQLException e) { throw new DataSourceException("SQL exception occurred while reading the geometry.", e); } } /** * @see org.geotools.data.jdbc.attributeio.AttributeIO#write(java.sql.PreparedStatement, * int, java.lang.Object) */ public void write(PreparedStatement ps, int position, Object value) throws IOException { try { if (value == null) { ps.setNull(position, Types.OTHER); } else { ps.setBytes(position, new WKBWriter().write((Geometry) value)); } } catch (SQLException e) { throw new DataSourceException("SQL exception occurred while reading the geometry.", e); } } /** * Turns a char that encodes four bits in hexadecimal notation into a byte * * @param c */ public static byte getFromChar(char c) { if (c <= '9') { return (byte) (c - '0'); } else if (c <= 'F') { return (byte) (c - 'A' + 10); } else { return (byte) (c - 'a' + 10); } } /** * Accelerates data loading compared to the plain InStream shipped along * with JTS * * @author Andrea Aime - TOPP */ private static class ByteArrayInStream implements InStream { byte[] buffer; int position; public void setBytes(final byte[] buffer) { this.buffer = buffer; this.position = 0; } public void read(final byte[] buf) throws IOException { final int size = buf.length; System.arraycopy(buffer, position, buf, 0, size); position += size; } } private static class InputStreamInStream implements InStream { private InputStream in; public void setIn(InputStream in) { this.in = in; } public void read(final byte[] buf) throws IOException { in.read(buf); } } }