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: package org.geotools.data.postgis;
017:
018: import java.io.IOException;
019: import java.sql.SQLException;
020: import java.util.logging.Logger;
021:
022: import org.geotools.data.FeatureReader;
023: import org.geotools.data.jdbc.FeatureTypeInfo;
024: import org.geotools.data.jdbc.JDBCTextFeatureWriter;
025: import org.geotools.data.jdbc.QueryData;
026:
027: import org.geotools.feature.AttributeType;
028: import org.geotools.feature.Feature;
029: import org.geotools.feature.FeatureType;
030: import org.geotools.filter.Filter;
031: import org.geotools.filter.FilterFactory;
032: import org.geotools.filter.FilterFactoryFinder;
033: import org.geotools.filter.SQLEncoderException;
034:
035: import com.vividsolutions.jts.geom.Geometry;
036: import com.vividsolutions.jts.io.WKBWriter;
037: import com.vividsolutions.jts.io.WKTWriter;
038:
039: /**
040: * An implementation of FeatureWriter that will work over a result set.
041: *
042: * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/plugin/postgis/src/main/java/org/geotools/data/postgis/PostgisFeatureWriter.java $
043: */
044: public class PostgisFeatureWriter extends JDBCTextFeatureWriter {
045:
046: private static final Logger LOGGER = org.geotools.util.logging.Logging
047: .getLogger("org.geotools.data.jdbc");
048:
049: /** Well Known Text writer (from JTS). */
050: protected static WKTWriter geometryWriter = new WKTWriter();
051:
052: private boolean WKBEnabled;
053: private boolean byteaWKB;
054:
055: private PostgisSQLBuilder sqlBuilder;
056:
057: /**
058: *
059: * @param fReader
060: * @param queryData
061: * @param WKBEnabled
062: * @param byteaWKB -- true if you're using postgis 1.0+. they changed how to do wkb writing.
063: * @throws IOException
064: */
065: public PostgisFeatureWriter(FeatureReader fReader,
066: QueryData queryData, boolean WKBEnabled, boolean byteaWKB,
067: PostgisSQLBuilder sqlBuilder) throws IOException {
068:
069: super (fReader, queryData);
070: this .WKBEnabled = WKBEnabled;
071: this .byteaWKB = byteaWKB;
072: this .sqlBuilder = sqlBuilder;
073: }
074:
075: protected String getGeometryInsertText(Geometry geom, int srid)
076: throws IOException {
077: if (geom == null) {
078: return "null";
079: }
080:
081: if (WKBEnabled) {
082: //String wkb = WKBEncoder.encodeGeometryHex(geom);
083: String wkb = WKBWriter.bytesToHex(new WKBWriter()
084: .write(geom));
085: if (byteaWKB)
086: return "setSRID('" + wkb + "'::geometry," + srid + ")";
087: else
088: return "GeomFromWKB('" + wkb + "', " + srid + ")";
089: }
090: String geoText = geometryWriter.write(geom);
091: return "GeometryFromText('" + geoText + "', " + srid + ")";
092: }
093:
094: /**
095: * Returns true if the WKB format is used to transfer geometries, false
096: * otherwise
097: *
098: */
099: public boolean isWKBEnabled() {
100: return WKBEnabled;
101: }
102:
103: /**
104: * If turned on, WKB will be used to transfer geometry data instead of WKT
105: *
106: * @param enabled
107: */
108: public void setWKBEnabled(boolean enabled) {
109: WKBEnabled = enabled;
110: }
111:
112: /**
113: * DJB: this is the javadoc from the superclass, but this wasnt being done.
114: *
115: * Encodes the tableName, default is to do nothing, but postgis will
116: * override and put double quotes around the tablename.
117: */
118: protected String encodeName(String tableName) {
119: return sqlBuilder.encodeTableName(tableName);
120: }
121:
122: protected String encodeColumnName(String colName) {
123: return sqlBuilder.encodeColumnName(colName);
124: }
125:
126: /**
127: * For postgres >= 8.1 NOWAIT is used (meaning you get a response).
128: * Prior versions will block during concurrent editing.
129: */
130: protected String makeSelectForUpdateSql(Feature current) {
131: FeatureTypeInfo ftInfo = queryData.getFeatureTypeInfo();
132: FeatureType featureType = ftInfo.getSchema();
133: String tableName = featureType.getTypeName();
134:
135: FilterFactory ff = FilterFactoryFinder.createFilterFactory();
136: Filter fid = ff.createFidFilter(current.getID());
137:
138: StringBuffer sql = new StringBuffer("SELECT ");
139: //fid will be picked up automatically
140: sqlBuilder.sqlColumns(sql, mapper, new AttributeType[] {});
141: sqlBuilder.sqlFrom(sql, tableName);
142: try {
143: sqlBuilder.sqlWhere(sql, fid);
144: } catch (SQLEncoderException e) {
145: e.printStackTrace();
146: }
147: sql.append(" FOR UPDATE");
148:
149: //determine if "NOWAIT" is supported (postgres >= 8.1)
150: try {
151: int major = queryData.getConnection().getMetaData()
152: .getDatabaseMajorVersion();
153: int minor = queryData.getConnection().getMetaData()
154: .getDatabaseMinorVersion();
155: if ((major > 8) || ((major == 8) && minor >= 1)) {
156: sql.append(" NOWAIT"); //horray, no blocking!
157: } else {
158: LOGGER
159: .warning("To fully support concurrent edits, please upgrade to postgres >= 8.1; the version currently in use will block");
160: }
161: } catch (SQLException e) { //we couldn't get the version :(
162: LOGGER
163: .warning("Failed to determine postgres version; assuming < 8.1");
164: }
165:
166: return (sql.toString());
167: }
168: }
|