Statistics
| Revision:

svn-gvsig-desktop / trunk / extensions / extJDBC / src / com / iver / cit / gvsig / fmap / drivers / jdbc / postgis / PostGIS.java @ 25516

History | View | Annotate | Download (12.6 KB)

1
/*
2
 * Created on 26-oct-2005
3
 *
4
 * gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
5
 *
6
 * Copyright (C) 2004 IVER T.I. and Generalitat Valenciana.
7
 *
8
 * This program is free software; you can redistribute it and/or
9
 * modify it under the terms of the GNU General Public License
10
 * as published by the Free Software Foundation; either version 2
11
 * of the License, or (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU General Public License
19
 * along with this program; if not, write to the Free Software
20
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21
 *
22
 * For more information, contact:
23
 *
24
 *  Generalitat Valenciana
25
 *   Conselleria d'Infraestructures i Transport
26
 *   Av. Blasco Ib??ez, 50
27
 *   46010 VALENCIA
28
 *   SPAIN
29
 *
30
 *      +34 963862235
31
 *   gvsig@gva.es
32
 *      www.gvsig.gva.es
33
 *
34
 *    or
35
 *
36
 *   IVER T.I. S.A
37
 *   Salamanca 50
38
 *   46005 Valencia
39
 *   Spain
40
 *
41
 *   +34 963163400
42
 *   dac@iver.es
43
 */
44
package com.iver.cit.gvsig.fmap.drivers.jdbc.postgis;
45

    
46
import java.io.ByteArrayOutputStream;
47
import java.io.PrintStream;
48
import java.io.UnsupportedEncodingException;
49
import java.sql.Types;
50

    
51
import com.hardcode.gdbms.engine.values.NullValue;
52
import com.hardcode.gdbms.engine.values.Value;
53
import com.hardcode.gdbms.engine.values.ValueWriter;
54
import com.iver.cit.gvsig.fmap.core.FShape;
55
import com.iver.cit.gvsig.fmap.core.FShapeM;
56
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
57
import com.iver.cit.gvsig.fmap.core.IFeature;
58
import com.iver.cit.gvsig.fmap.core.IGeometry;
59
import com.iver.cit.gvsig.fmap.core.IGeometry3D;
60
import com.iver.cit.gvsig.fmap.core.IGeometryM;
61
import com.iver.cit.gvsig.fmap.core.IRow;
62
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
63
import com.iver.cit.gvsig.fmap.core.ShapeMFactory;
64
import com.iver.cit.gvsig.fmap.drivers.DBLayerDefinition;
65
import com.iver.cit.gvsig.fmap.drivers.DefaultJDBCDriver;
66
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
67
import com.iver.cit.gvsig.fmap.drivers.XTypes;
68

    
69
/**
70
 * @author fjp
71
 * Necesitamos que esta clase no trabaje con funciones est?ticas
72
 * porque puede haber capas que provengan de distintas bases de datos.
73
 */
74
public class PostGIS {
75

    
76
        private String toEncode;
77

    
78
        /**
79
         * Mover esto a IverUtiles
80
         *
81
         * @param val
82
         * @return
83
         */
84
        public boolean isNumeric(Value val) {
85

    
86
                switch (val.getSQLType()) {
87
                case Types.DOUBLE:
88
                case Types.FLOAT:
89
                case Types.INTEGER:
90
                case Types.SMALLINT:
91
                case Types.BIGINT:
92
                case Types.NUMERIC:
93
                case Types.REAL:
94
                case Types.TINYINT:
95
                        return true;
96
                }
97

    
98
                return false;
99
        }
100

    
101
        /**
102
         * @param dbLayerDef
103
         * @param fieldsDescr
104
         * @param bCreateGID @DEPRECATED
105
         * @return
106
         */
107
        public String getSqlCreateSpatialTable(DBLayerDefinition dbLayerDef,
108
                        FieldDescription[] fieldsDescr, boolean bCreateGID) {
109

    
110
                String resul;
111
                /* boolean bExistGID = false;
112
                for (int i = 0; i < dbLayerDef.getFieldNames().length; i++) {
113
                        if (dbLayerDef.getFieldNames()[i].equalsIgnoreCase("gid")) {
114
                                bExistGID = true;
115
                                break;
116
                        }
117
                } */
118
                /* if (bExistGID) // Usamos el existente y no a?adimos ninguno nosotros
119
                        resul = "CREATE TABLE " + dbLayerDef.getTableName() + " (";
120
                else */
121
                // FJP: NUEVO: NO TOLERAMOS CAMPOS QUE SE LLAMEN GID. Lo reservamos para uso nuestro.
122
                resul = "CREATE TABLE " + dbLayerDef.getComposedTableName()
123
                                        + " ( " + dbLayerDef.getFieldID() +" serial PRIMARY KEY ";
124
                int j=0;
125
                for (int i = 0; i < dbLayerDef.getFieldNames().length; i++) {
126
                        int fieldType = fieldsDescr[i].getFieldType();
127
                        String strType = XTypes.fieldTypeToString(fieldType);
128
                        /*
129
                         * if (fieldType == Types.VARCHAR) strType = strType + "(" +
130
                         * fieldsDescr[i].getFieldLength() + ")";
131
                         */
132
                        if (fieldsDescr[i].getFieldName().equalsIgnoreCase(dbLayerDef.getFieldID()))
133
                                continue;
134
                        resul = resul + ", " + dbLayerDef.getFieldNames()[i] + " "        + strType;
135
                        j++;
136
                }
137
                resul = resul + ");";
138
                return resul;
139
        }
140

    
141
        public String getSqlAlterTable(DBLayerDefinition dbLayerDef) {
142
                String strGeometryFieldType;
143
                strGeometryFieldType = "GEOMETRY";
144

    
145
                switch (dbLayerDef.getShapeType()) {
146
                case FShape.POINT:
147
                        strGeometryFieldType = XTypes.fieldTypeToString(XTypes.POINT2D);
148
                        break;
149
                case FShape.LINE:
150
                        strGeometryFieldType = XTypes.fieldTypeToString(XTypes.LINE2D);
151
                        break;
152
                case FShape.POLYGON:
153
                        strGeometryFieldType = XTypes.fieldTypeToString(XTypes.POLYGON2D);
154
                        break;
155
                case FShape.MULTI:
156
                        strGeometryFieldType = XTypes.fieldTypeToString(XTypes.MULTI2D);
157
                        break;
158
                case FShape.MULTIPOINT:
159
                        strGeometryFieldType = XTypes.fieldTypeToString(XTypes.MULTIPOINT);
160
                        break;
161
                }
162

    
163
                String schema = dbLayerDef.getSchema();
164
                if (schema == null || schema.equals("")){
165
                        schema = " current_schema()::Varchar ";
166
                } else {
167
                        schema = "'" +schema + "'";
168
                }
169

    
170
                String result = "SELECT AddGeometryColumn("
171
                                + schema + ", '"
172
                                + dbLayerDef.getTableName() + "', '"
173
                                + dbLayerDef.getFieldGeometry() + "', "
174
                                + DefaultJDBCDriver.removePrefix(dbLayerDef.getSRID_EPSG()) + ", '" + strGeometryFieldType + "', "
175
                                + dbLayerDef.getDimension() + ");";
176

    
177
                return result;
178
        }
179

    
180
        /**
181
         * From geotools Adds quotes to an object for storage in postgis. The object
182
         * should be a string or a number. To perform an insert strings need quotes
183
         * around them, and numbers work fine with quotes, so this method can be
184
         * called on unknown objects.
185
         *
186
         * @param value
187
         *            The object to add quotes to.
188
         *
189
         * @return a string representation of the object with quotes.
190
         */
191
        protected String addQuotes(Object value) {
192
                String retString;
193

    
194
                if (value != null) {
195
                        if (value instanceof NullValue)
196
                                retString = "null";
197
                        else
198
                                retString = "'" + doubleQuote(value) + "'";
199

    
200
                } else {
201
                        retString = "null";
202
                }
203

    
204
                return retString;
205
        }
206

    
207
        private String doubleQuote(Object obj) {
208
                String aux = obj.toString().replaceAll("'", "''");
209
                StringBuffer strBuf = new StringBuffer(aux);
210
                ByteArrayOutputStream out = new ByteArrayOutputStream(strBuf.length());
211
                PrintStream printStream = new PrintStream(out);
212
                printStream.print(aux);
213
                String aux2 = "ERROR";
214
                try {
215
                        aux2 = out.toString(toEncode);
216
                        System.out.println(aux + " " + aux2);
217
                } catch (UnsupportedEncodingException e) {
218
                        // TODO Auto-generated catch block
219
                        e.printStackTrace();
220
                }
221

    
222
                return aux2;
223
        }
224

    
225
        /**
226
         * Based in code from JUMP (VividSolutions) and Geotools Things to be aware:
227
         * We always will use Spatial Tables with Unique ID. IFeature has the same
228
         * field order than dbLayerDef.getFieldNames()
229
         *
230
         * @param dbLayerDef
231
         * @param feat
232
         * @return
233
         */
234
        public String getSqlInsertFeature(DBLayerDefinition dbLayerDef,
235
                        IFeature feat) {
236
                StringBuffer sqlBuf = new StringBuffer("INSERT INTO "
237
                                + dbLayerDef.getComposedTableName() + " (");
238
                String sql = null;
239
                int numAlphanumericFields = dbLayerDef.getFieldNames().length;
240

    
241
                for (int i = 0; i < numAlphanumericFields; i++) {
242
                        String name = dbLayerDef.getFieldsDesc()[i].getFieldName();
243
                        // if (cols.contains(name) && (!name.equals(uniqueCol) ||
244
                        // existsUnique)) {
245
                        if (name.equals(dbLayerDef.getFieldID()))
246
                                continue;
247
                        sqlBuf.append(" " + name + ",");
248
                        // }
249
                }
250
                sqlBuf.append(" " + dbLayerDef.getFieldGeometry());
251
                // sqlBuf.deleteCharAt(sqlBuf.lastIndexOf(","));
252
                sqlBuf.append(" ) VALUES (");
253
                String insertQueryHead = sqlBuf.toString();
254
                sqlBuf = new StringBuffer(insertQueryHead);
255
                for (int j = 0; j < numAlphanumericFields; j++) {
256
                        String name = dbLayerDef.getFieldsDesc()[j].getFieldName();
257
                        if (name.equals(dbLayerDef.getFieldID()))
258
                                continue;
259

    
260
                        if (isNumeric(feat.getAttribute(j)))
261
                                sqlBuf.append(feat.getAttribute(j) + ", ");
262
                        else
263
                                sqlBuf.append(addQuotes(feat.getAttribute(j)) + ", ");
264
                }
265
                IGeometry geometry=feat.getGeometry();
266
                int type=dbLayerDef.getShapeType();
267
                if (geometry.getGeometryType()!=type){
268
                        if (type==FShape.POLYGON){
269
                                geometry=ShapeFactory.createPolygon2D(new GeneralPathX(geometry.getInternalShape()));
270
                        }else if (type==FShape.LINE){
271
                                geometry=ShapeFactory.createPolyline2D(new GeneralPathX(geometry.getInternalShape()));
272
                        }else if (type==(FShape.POLYGON|FShape.Z)){
273
                                geometry=ShapeFactory.createPolygon3D(new GeneralPathX(geometry.getInternalShape()),((IGeometry3D)geometry).getZs());
274
                        }else if (type==(FShape.LINE|FShape.Z)){
275
                                geometry=ShapeFactory.createPolyline3D(new GeneralPathX(geometry.getInternalShape()),((IGeometry3D)geometry).getZs());
276
                        }else if (type==(FShape.LINE|FShape.M)){ //MCoord
277
                                geometry=ShapeMFactory.createPolyline2DM(new GeneralPathX(geometry.getInternalShape()),((IGeometryM)geometry).getMs()); //MCoord
278
                        }
279
                }
280
                //MCoord
281
                if ((type == (FShape.LINE|FShape.M)) || (type == (FShape.POINT|FShape.M))){
282
                        sqlBuf.append(" GeometryFromText( '"
283
                                        + ((FShapeM)geometry.getInternalShape()).toText() + "', "
284
                                        + DefaultJDBCDriver.removePrefix(dbLayerDef.getSRID_EPSG()) + ")");
285
                }else{
286
                        sqlBuf.append(" GeometryFromText( '"
287
                                + geometry.toJTSGeometry().toText() + "', "
288
                                + DefaultJDBCDriver.removePrefix(dbLayerDef.getSRID_EPSG()) + ")");
289
                }
290

    
291
                // sqlBuf.deleteCharAt(sqlBuf.lastIndexOf(","));
292
                sqlBuf.append(" ) ");
293
                sql = sqlBuf.toString();
294
                return sql;
295
        }
296

    
297
        public String getSqlCreateIndex(DBLayerDefinition lyrDef) {
298
                String indexName = lyrDef.getTableName() + "_"
299
                                + lyrDef.getFieldGeometry() + "_gist";
300
                String sql = "CREATE INDEX \"" + indexName + "\" ON \""
301
                                + lyrDef.getComposedTableName() + "\" USING GIST (\""
302
                                + lyrDef.getFieldGeometry() + "\" GIST_GEOMETRY_OPS)";
303

    
304
                return sql;
305
        }
306

    
307
        public String getSqlModifyFeature(DBLayerDefinition dbLayerDef, IFeature feat) {
308
                /*
309
                         UPDATE weather
310
                         SET temp_hi = temp_hi - 2,  temp_lo = temp_lo - 2
311
                         WHERE date > '1994-11-28';
312
                 */
313
                StringBuffer sqlBuf = new StringBuffer("UPDATE "
314
                                + dbLayerDef.getComposedTableName() + " SET");
315
                String sql = null;
316
                int numAlphanumericFields = dbLayerDef.getFieldsDesc().length;
317

    
318
                for (int i = 0; i < numAlphanumericFields; i++) {
319
                        FieldDescription fldDesc = dbLayerDef.getFieldsDesc()[i];
320
                        if (fldDesc != null)
321
                        {
322
                                String name = fldDesc.getFieldName();
323
                                // El campo gid no lo actualizamos.
324
                                if (name.equalsIgnoreCase(dbLayerDef.getFieldID()))
325
                                        continue;
326
                                Value val = feat.getAttribute(i);
327
                                if (val != null)
328
                                {
329
                                        String strAux = val.getStringValue(ValueWriter.internalValueWriter);
330
                                        sqlBuf.append(" " + name + " = " + strAux + " ,");
331
                                }
332
                        }
333
                }
334
                //If pos > 0 there is at least one field..
335
                int pos = sqlBuf.lastIndexOf(",");
336
                if (pos > -1){
337
                        sqlBuf.deleteCharAt(pos);
338
                }
339
                if (feat.getGeometry() != null)
340
                {                
341
                        if (pos > -1){
342
                                sqlBuf.append(",");
343
                        }
344
                        sqlBuf.append(" " + dbLayerDef.getFieldGeometry());
345
                        sqlBuf.append(" = ");
346
                        //MCoord
347
                        int type = feat.getGeometry().getGeometryType();
348
                        if ((type == (FShape.LINE|FShape.M)) || (type == (FShape.POINT|FShape.M))){
349
                                sqlBuf.append(" GeometryFromText( '"
350
                                                + ((FShapeM)feat.getGeometry().getInternalShape()).toText() + "', "
351
                                                + DefaultJDBCDriver.removePrefix(dbLayerDef.getSRID_EPSG()) + ")");
352
                        }else{
353
                                sqlBuf.append(" GeometryFromText( '"
354
                                + feat.getGeometry().toJTSGeometry().toText() + "', "
355
                                + DefaultJDBCDriver.removePrefix(dbLayerDef.getSRID_EPSG()) + ")");
356
                        }
357
                }
358
                sqlBuf.append(" WHERE ");
359
                sqlBuf.append(dbLayerDef.getFieldID() + " = " + feat.getID());
360
                sql = sqlBuf.toString();
361
                return sql;
362

    
363
        }
364

    
365
        /**
366
         * TODO: NECESITAMOS OTRO M?TODO PARA BORRAR CORRECTAMENTE.
367
         *         Esto provocar? errores, ya que getID que viene en un row no
368
         *         nos sirve dentro de un writer para modificar y/o borrar entidades
369
         *         Por ahora, cojo el ID del campo que me indica el dbLayerDef
370
         * @param dbLayerDef
371
         * @param row
372
         * @return
373
         */
374
        public String getSqlDeleteFeature(DBLayerDefinition dbLayerDef, IRow row) {
375
                // DELETE FROM weather WHERE city = 'Hayward';
376
                // TODO: NECESITAMOS OTRO M?TODO PARA BORRAR CORRECTAMENTE.
377
                // Esto provocar? errores, ya que getID que viene en un row no
378
                // nos sirve dentro de un writer para modificar y/o borrar entidades
379
                // Por ahora, cojo el ID del campo que me indica el dbLayerDev
380
                StringBuffer sqlBuf = new StringBuffer("DELETE FROM "
381
                                + dbLayerDef.getComposedTableName() + " WHERE ");
382
                String sql = null;
383
                int indexFieldId = dbLayerDef.getIdFieldID();
384
                sqlBuf.append(dbLayerDef.getFieldID() + " = " + row.getAttribute(indexFieldId));
385
                sql = sqlBuf.toString();
386

    
387
                return sql;
388
        }
389

    
390
        public String getEncoding() {
391
                return toEncode;
392
        }
393
        public void setEncoding(String toEncode){
394
                if (toEncode.compareToIgnoreCase("SQL_ASCII") == 0){
395
                   this.toEncode = "ASCII";
396
                  } else {
397
                          this.toEncode = toEncode;
398
                  }
399
        }
400

    
401
}