001: /*
002: * GeoTools - OpenSource mapping toolkit
003: * http://geotools.org
004: * (C) 2002-2006, GeoTools Project Managment Committee (PMC)
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation;
009: * version 2.1 of the License.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: */
016:
017: package org.geotools.data.jdbc.attributeio;
018:
019: import java.io.IOException;
020: import java.sql.PreparedStatement;
021: import java.sql.ResultSet;
022: import java.sql.SQLException;
023: import java.sql.Types;
024:
025: import org.geotools.data.DataSourceException;
026: import org.geotools.factory.Hints;
027:
028: import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
029: import com.vividsolutions.jts.geom.Geometry;
030: import com.vividsolutions.jts.geom.GeometryFactory;
031: import com.vividsolutions.jts.geom.PrecisionModel;
032: import com.vividsolutions.jts.geom.impl.CoordinateArraySequenceFactory;
033: import com.vividsolutions.jts.io.InStream;
034: import com.vividsolutions.jts.io.WKBReader;
035: import com.vividsolutions.jts.io.WKBWriter;
036:
037: /**
038: * An attribute IO implementation that can manage the WKB
039: *
040: * @author Andrea Aime
041: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/jdbc/src/main/java/org/geotools/data/jdbc/attributeio/WKBAttributeIO.java $
042: * @since 2.4.1
043: */
044: public class WKBAttributeIO implements AttributeIO {
045: WKBReader wkbr;
046: ByteArrayInStream inStream = new ByteArrayInStream();
047:
048: public WKBAttributeIO() {
049: wkbr = new WKBReader();
050: }
051:
052: public WKBAttributeIO(Hints hints) {
053: // setup the geometry factory according to the hints
054: GeometryFactory gf = (GeometryFactory) hints
055: .get(Hints.JTS_GEOMETRY_FACTORY);
056: if (gf == null) {
057: PrecisionModel pm = (PrecisionModel) hints
058: .get(Hints.JTS_PRECISION_MODEL);
059: if (pm == null)
060: pm = new PrecisionModel();
061: Integer SRID = (Integer) hints.get(Hints.JTS_SRID);
062: int srid = SRID == null ? 0 : SRID.intValue();
063: CoordinateSequenceFactory csFactory = (CoordinateSequenceFactory) hints
064: .get(Hints.JTS_COORDINATE_SEQUENCE_FACTORY);
065: if (csFactory == null)
066: csFactory = CoordinateArraySequenceFactory.instance();
067: gf = new GeometryFactory(pm, srid, csFactory);
068: }
069: wkbr = new WKBReader(gf);
070: }
071:
072: /**
073: * This method will convert a Well Known Binary representation to a
074: * JTS Geometry object.
075: *
076: * @param wkb te wkb encoded byte array
077: *
078: * @return a JTS Geometry object that is equivalent to the WTB
079: * representation passed in by param wkb
080: *
081: * @throws IOException if more than one geometry object was found in the
082: * WTB representation, or if the parser could not parse the WKB
083: * representation.
084: */
085: private Geometry WKB2Geometry(byte[] wkbBytes) throws IOException {
086: // convert the byte[] to a JTS Geometry object
087:
088: 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
089: return null;
090: try {
091: inStream.setBytes(wkbBytes);
092: return wkbr.read(inStream);
093: } catch (Exception e) {
094: throw new DataSourceException(
095: "An exception occurred while parsing WKB data", e);
096: }
097: }
098:
099: /**
100: * @see org.geotools.data.jdbc.attributeio.AttributeIO#read(java.sql.ResultSet,
101: * int)
102: */
103: public Object read(ResultSet rs, int position) throws IOException {
104: try {
105: byte bytes[] = rs.getBytes(position);
106: if (bytes == null) // ie. its a null column -> return a null geometry!
107: return null;
108: return WKB2Geometry(bytes);
109: } catch (SQLException e) {
110: throw new DataSourceException(
111: "SQL exception occurred while reading the geometry.",
112: e);
113: }
114: }
115:
116: /**
117: * Unsupported, will throw an UnsupportedOperationException
118: * @see org.geotools.data.jdbc.attributeio.AttributeIO#write(java.sql.ResultSet,
119: * int, java.lang.Object)
120: */
121: public void write(ResultSet rs, int position, Object value)
122: throws IOException {
123: try {
124: if (value == null) {
125: rs.updateNull(position);
126: } else {
127: rs.updateBytes(position, new WKBWriter()
128: .write((Geometry) value));
129: }
130: } catch (SQLException e) {
131: throw new DataSourceException(
132: "SQL exception occurred while reading the geometry.",
133: e);
134: }
135: }
136:
137: /**
138: * @see org.geotools.data.jdbc.attributeio.AttributeIO#write(java.sql.PreparedStatement, int, java.lang.Object)
139: */
140: public void write(PreparedStatement ps, int position, Object value)
141: throws IOException {
142: try {
143: if (value == null) {
144: ps.setNull(position, Types.OTHER);
145: } else {
146: ps.setBytes(position, new WKBWriter()
147: .write((Geometry) value));
148: }
149: } catch (SQLException e) {
150: throw new DataSourceException(
151: "SQL exception occurred while reading the geometry.",
152: e);
153: }
154:
155: }
156:
157: /**
158: * Accelerates data loading compared to the plain InStream shipped along with JTS
159: * @author Andrea Aime - TOPP
160: *
161: */
162: private static class ByteArrayInStream implements InStream {
163:
164: byte[] buffer;
165: int position;
166:
167: public void setBytes(final byte[] buffer) {
168: this .buffer = buffer;
169: this .position = 0;
170: }
171:
172: public void read(final byte[] buf) throws IOException {
173: final int size = buf.length;
174: System.arraycopy(buffer, position, buf, 0, size);
175: position += size;
176: }
177:
178: }
179: }
|