Statistics
| Revision:

root / trunk / org.gvsig.postgresql / org.gvsig.postgresql.provider / src / main / java / org / gvsig / fmap / dal / store / postgresql / PostgreSQLHelper.java @ 58

History | View | Annotate | Download (28.4 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
*
3
* Copyright (C) 2007-2008 Infrastructures and Transports Department
4
* of the Valencian Government (CIT)
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
*
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
* GNU General Public License for more details.
15
*
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
* MA  02110-1301, USA.
20
*
21
*/
22

    
23
/*
24
* AUTHORS (In addition to CIT):
25
* 2009 IVER T.I   {{Task}}
26
*/
27

    
28
/**
29
 *
30
 */
31
package org.gvsig.fmap.dal.store.postgresql;
32

    
33
import java.io.File;
34
import java.io.InputStream;
35
import java.net.URL;
36
import java.sql.Connection;
37
import java.sql.PreparedStatement;
38
import java.sql.ResultSet;
39
import java.sql.ResultSetMetaData;
40
import java.sql.SQLException;
41
import java.sql.Statement;
42
import java.util.ArrayList;
43
import java.util.Comparator;
44
import java.util.Iterator;
45
import java.util.List;
46
import java.util.Map;
47
import java.util.Properties;
48
import java.util.TreeMap;
49
import java.util.TreeSet;
50

    
51
import org.cresques.cts.IProjection;
52
import org.postgresql.PGResultSetMetaData;
53
import org.slf4j.Logger;
54
import org.slf4j.LoggerFactory;
55

    
56
import org.gvsig.fmap.crs.CRSFactory;
57
import org.gvsig.fmap.dal.DALLocator;
58
import org.gvsig.fmap.dal.DataTypes;
59
import org.gvsig.fmap.dal.NewDataStoreParameters;
60
import org.gvsig.fmap.dal.exception.DataException;
61
import org.gvsig.fmap.dal.exception.InitializeException;
62
import org.gvsig.fmap.dal.exception.ReadException;
63
import org.gvsig.fmap.dal.exception.WriteException;
64
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
65
import org.gvsig.fmap.dal.feature.EditableFeatureType;
66
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
67
import org.gvsig.fmap.dal.feature.FeatureType;
68
import org.gvsig.fmap.dal.feature.exception.CreateGeometryException;
69
import org.gvsig.fmap.dal.feature.exception.UnsupportedDataTypeException;
70
import org.gvsig.fmap.dal.feature.exception.UnsupportedGeometryException;
71
import org.gvsig.fmap.dal.resource.ResourceAction;
72
import org.gvsig.fmap.dal.resource.spi.ResourceManagerProviderServices;
73
import org.gvsig.fmap.dal.store.jdbc.ConnectionAction;
74
import org.gvsig.fmap.dal.store.jdbc.JDBCHelper;
75
import org.gvsig.fmap.dal.store.jdbc.JDBCHelperUser;
76
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
77
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
78
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecutePreparedSQLException;
79
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
80
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCPreparingSQLException;
81
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
82
import org.gvsig.fmap.geom.Geometry;
83
import org.gvsig.fmap.geom.GeometryLocator;
84
import org.gvsig.fmap.geom.GeometryManager;
85
import org.gvsig.fmap.geom.operation.GeometryOperationException;
86
import org.gvsig.fmap.geom.operation.GeometryOperationNotSupportedException;
87
import org.gvsig.fmap.geom.operation.fromwkb.FromWKB;
88
import org.gvsig.fmap.geom.operation.fromwkb.FromWKBGeometryOperationContext;
89
import org.gvsig.fmap.geom.primitive.Envelope;
90
import org.gvsig.tools.ToolsLocator;
91
import org.gvsig.tools.exception.BaseException;
92

    
93
/**
94
 * @author jmvivo
95
 *
96
 */
97
public class PostgreSQLHelper extends JDBCHelper {
98

    
99
        private static Logger logger = LoggerFactory
100
                        .getLogger(PostgreSQLHelper.class);
101

    
102
        private Map pgSR2SRSID = new TreeMap();
103
        private Map srsID2pgSR = new TreeMap();
104
        
105
        private static Properties beforePostgis13 = null;
106
    private int[] postGISVersion = { 0,0,0 };
107
    private boolean versionSet = false;
108

    
109
        PostgreSQLHelper(JDBCHelperUser consumer,
110
                        PostgreSQLConnectionParameters params)
111
                        throws InitializeException {
112

    
113
                super(consumer, params);
114
        }
115

    
116
        protected void initializeResource() throws InitializeException {
117
                ResourceManagerProviderServices manager = (ResourceManagerProviderServices) DALLocator
118
                .getResourceManager();
119
                PostgreSQLResource resource = (PostgreSQLResource) manager
120
                .createAddResource(
121
                                PostgreSQLResource.NAME, new Object[] {
122
                                                params.getUrl(), params.getHost(),
123
                                                params.getPort(), params.getDBName(), params.getUser(),
124
                                                params.getPassword(),
125
                                                params.getJDBCDriverClassName(),
126
                                                ((PostgreSQLConnectionParameters) params).getUseSSL() });
127
                this.setResource(resource);
128
        }
129

    
130

    
131
        protected String getDefaultSchema(Connection conn)
132
                        throws JDBCException {
133
                if (defaultSchema == null) {
134
                        String sql = "Select current_schema()";
135
                        ResultSet rs = null;
136
                        Statement st = null;
137
                        String schema = null;
138
                        try {
139
                                st = conn.createStatement();
140
                                try {
141
                                        rs = st.executeQuery(sql);
142
                                } catch (java.sql.SQLException e) {
143
                                        throw new JDBCExecuteSQLException(sql, e);
144
                                }
145
                                rs.next();
146
                                schema = rs.getString(1);
147
                        } catch (java.sql.SQLException e) {
148
                                throw new JDBCSQLException(e);
149
                        } finally {
150
                                try {rs.close();} catch (Exception e) {logger.error("Exception clossing resulset", e);};
151
                                try {st.close();} catch (Exception e) {logger.error("Exception clossing statement", e);};
152
                                rs = null;
153
                                st = null;
154
                        }
155
                        defaultSchema = schema;
156
                }
157

    
158
                return defaultSchema;
159
        }
160

    
161
        public Envelope getFullEnvelopeOfField(
162
                        JDBCStoreParameters storeParams,
163
                        String geometryAttrName, Envelope limit)
164
                        throws DataException {
165

    
166
                StringBuilder strb = new StringBuilder();
167
                strb.append("Select " + getFunctionName("ST_AsBinary") + "(" +
168
                getFunctionName("ST_Extent") + "(");
169
                strb.append(escapeFieldName(geometryAttrName));
170
                strb.append(")) from ");
171

    
172
                if (storeParams.getSQL() != null
173
                                && storeParams.getSQL().trim().length() > 0) {
174
                        strb.append('(');
175
                        strb.append(storeParams.getSQL());
176
                        strb.append(") as _subquery_alias_ ");
177
                } else {
178
                        strb.append(storeParams.tableID());
179
                }
180

    
181
                if (limit != null || (storeParams.getBaseFilter() != null 
182
                                && storeParams.getBaseFilter().trim().length() > 0)){
183
                        strb.append(" where  ");
184

    
185
                        if (limit != null) { 
186
                                strb.append(" ( " + getFunctionName("ST_Intersects") + "("
187
                                        + getFunctionName("ST_GeomFromText") + "('");
188
                                String workAreaWkt = null;
189
                                try {
190
                                        workAreaWkt = limit.getGeometry().convertToWKT();
191
                                } catch (Exception e) {
192
                                        throw new CreateGeometryException(e);
193
                                }
194
                                strb.append(workAreaWkt);
195
                                strb.append("', ");
196

    
197
                                IProjection proj = storeParams.getCRS();
198
                                int sridInt = this.getProviderSRID(proj); 
199
                                if (sridInt == -1) {
200
                                        throw new CreateGeometryException(
201
                                                new Exception("CRS is null or unknown."));
202
                                } else {
203
                                        strb.append(Integer.toString(sridInt));
204
                                }
205
                                strb.append("), " + getFunctionName("ST_Envelope") + "(");
206
                                strb.append(escapeFieldName(geometryAttrName));
207
                                strb.append(")) ) ");
208

    
209
                        }
210
                        if (storeParams.getBaseFilter() != null && storeParams.getBaseFilter().trim().length() > 0) {
211
                                if (limit != null) { 
212
                                        strb.append(" and ");
213
                                }
214
                                strb.append(" ( ");
215
                                strb.append(storeParams.getBaseFilter());
216
                                strb.append(" ) ");
217
                        }
218

    
219
                }
220

    
221
                final String sql = strb.toString();
222

    
223
                this.open();
224

    
225
                return (Envelope) getResource().execute(new ResourceAction() {
226
                        public Object run() throws Exception {
227
                                ResultSet rs = null;
228
                                Statement st = null;
229
                                Connection conn = null;
230
                                Envelope fullEnvelope = null;
231
                                
232
                                Envelope emptyEnv =
233
                                                geomManager.createEnvelope(Geometry.SUBTYPES.GEOM2D);
234
                                
235
                                try {
236

    
237
                                        conn = getConnection();
238
                                        st = conn.createStatement();
239
                                        try {
240
                                                rs = st.executeQuery(sql);
241
                                        } catch (java.sql.SQLException e) {
242
                                                throw new JDBCExecuteSQLException(sql, e);
243
                                        }
244
                                        if (!rs.next()) {
245
                                                return emptyEnv;
246
                                        }
247

    
248
                                        byte[] data = rs.getBytes(1);
249
                                        if (data == null) {
250
                                                return emptyEnv;
251
                                        }
252

    
253
                                        Geometry geom = geomManager.createFrom(data);
254

    
255
                                        fullEnvelope = geom.getEnvelope();
256

    
257
                                        return fullEnvelope;
258
                                } catch (java.sql.SQLException e) {
259
                                        throw new JDBCSQLException(e);
260
                                } catch (BaseException e) {
261
                                        throw new ReadException(user.getProviderName(), e);
262
                                } finally {
263
                                        try {
264
                                                rs.close();
265
                                        } catch (Exception e) {
266
                                        }
267
                                        try {
268
                                                st.close();
269
                                        } catch (Exception e) {
270
                                        }
271
                                        try {
272
                                                conn.close();
273
                                        } catch (Exception e) {
274
                                        }
275
                                        rs = null;
276
                                        st = null;
277
                                        conn = null;
278
                                }
279
                        }
280
                });
281
        }
282

    
283
        @Override
284
        protected boolean supportsGeometry() {
285
                return true;
286
        }
287

    
288
        /**
289
         * Fill <code>featureType</code> geometry attributes with SRS and ShapeType
290
         * information stored in the table GEOMETRY_COLUMNS
291
         *
292
         * @param conn
293
         * @param rsMetadata
294
         * @param featureType
295
         * @throws ReadException
296
         */
297
        protected void loadSRS_and_shapeType(Connection conn,
298
                        ResultSetMetaData rsMetadata, EditableFeatureType featureType,
299
                        String baseSchema, String baseTable)
300
                        throws JDBCException {
301

    
302
                Statement st = null;
303
                ResultSet rs = null;
304
                try {
305
                        // Sacamos la lista de los attributos geometricos
306
                        EditableFeatureAttributeDescriptor attr;
307
                        List geoAttrs = new ArrayList();
308

    
309
                        Iterator iter = featureType.iterator();
310
                        while (iter.hasNext()) {
311
                                attr = (EditableFeatureAttributeDescriptor) iter.next();
312
                                if (attr.getType() == DataTypes.GEOMETRY) {
313
                                        geoAttrs.add(attr);
314
                                }
315
                        }
316
                        if (geoAttrs.size() < 1) {
317
                                return;
318
                        }
319

    
320

    
321
                        // preparamos un set con las lista de tablas de origen
322
                        // de los campos
323
                        class TableId {
324
                                public String schema=null;
325
                                public String table=null;
326
                                public String field = null;
327

    
328
                                public void appendToSQL(StringBuilder strb) {
329
                                        if (schema == null || schema.length() == 0) {
330
                                                strb
331
                                                                .append("( F_TABLE_SCHEMA = current_schema() AND F_TABLE_NAME = '");
332
                                        } else {
333
                                                strb.append("( F_TABLE_SCHEMA = '");
334
                                                strb.append(schema);
335
                                                strb.append("' AND F_TABLE_NAME = '");
336
                                        }
337
                                        strb.append(table);
338
                                        strb.append("' AND F_GEOMETRY_COLUMN = '");
339
                                        strb.append(field);
340
                                        strb.append("' )");
341
                                }
342

    
343
                        }
344
                        Comparator cmp = new Comparator(){
345
                                public int compare(Object arg0, Object arg1) {
346
                                        TableId a0 = (TableId) arg0;
347
                                        TableId a1 = (TableId) arg1;
348

    
349
                                        int aux = a0.field.compareTo(a1.field);
350
                                        if (aux != 0) {
351
                                            return aux;
352
                                        }
353

    
354
                                        aux = a0.table.compareTo(a1.table);
355
                    if (aux != 0) {
356
                        return aux;
357
                    }
358
                                        
359
                    if (a0.schema == null) {
360
                        if (a1.schema == null) {
361
                            aux = 0;
362
                        } else {
363
                            aux = -1;
364
                        }
365
                    } else {
366
                        if (a1.schema == null) {
367
                            aux = -1;
368
                        } else {
369
                            aux = a0.schema.compareTo(a1.schema);
370
                        }
371
                    }
372
                                        return aux;
373
                                }
374
                        };
375
                        TreeSet set = new TreeSet(cmp);
376
                        TableId tableId;
377
                        iter = geoAttrs.iterator();
378
                        int rsIndex;
379
                        while (iter.hasNext()) {
380
                                attr = (EditableFeatureAttributeDescriptor) iter.next();
381
                                tableId = new TableId();
382
                                rsIndex = attr.getIndex() + 1;
383

    
384
                                if (baseSchema == null && baseTable == null) {
385
                                        if (rsMetadata instanceof PGResultSetMetaData) {
386
                                                tableId.schema = ((PGResultSetMetaData) rsMetadata)
387
                                                                .getBaseSchemaName(rsIndex);
388
                                                tableId.table = ((PGResultSetMetaData) rsMetadata)
389
                                                                .getBaseTableName(rsIndex);
390
                                                tableId.field = ((PGResultSetMetaData) rsMetadata)
391
                                                                .getBaseColumnName(rsIndex);
392

    
393
                                        } else {
394
                                                tableId.schema = rsMetadata.getSchemaName(rsIndex);
395
                                                tableId.table = rsMetadata.getTableName(rsIndex);
396
                                                tableId.field = rsMetadata.getColumnName(rsIndex);
397
                                        }
398
                                } else {
399
                                        tableId.schema = baseSchema;
400
                                        tableId.table = baseTable;
401
                                        tableId.field = rsMetadata.getColumnName(rsIndex);
402
                                }
403
                                if (tableId.table == null || tableId.table.length() == 0) {
404
                                        // Si no tiene tabla origen (viene de algun calculo por ej.)
405
                                        // lo saltamos ya que no estara en la tabla GEOMETRY_COLUMNS
406
                                        continue;
407
                                }
408
                                set.add(tableId);
409
                        }
410

    
411
                        if (set.size() == 0) {
412
                                return;
413
                        }
414

    
415
                        // Preparamos una sql para que nos saque el resultado
416
                        StringBuilder strb = new StringBuilder();
417
                        strb.append("Select geometry_columns.*,auth_name || ':' || auth_srid as SRSID ");
418
                        strb.append("from geometry_columns left join spatial_ref_sys on ");
419
                        strb.append("geometry_columns.srid = spatial_ref_sys.srid WHERE ");
420
                        iter = set.iterator();
421
                        for (int i=0;i<set.size()-1;i++) {
422
                                tableId = (TableId) iter.next();
423
                                tableId.appendToSQL(strb);
424
                                strb.append(" OR ");
425
                        }
426
                        tableId = (TableId) iter.next();
427
                        tableId.appendToSQL(strb);
428
                        String sql = strb.toString();
429

    
430

    
431
                        st = conn.createStatement();
432
                        try {
433
                                rs = st.executeQuery(sql);
434
                        } catch (SQLException e) {
435
                                throw new JDBCExecuteSQLException(sql, e);
436
                        }
437
                        String srsID;
438
                        int pgSrid;
439
                        int geometryType;
440
                        int geometrySubtype;
441
                        String geomTypeStr;
442
                        int dimensions;
443
                        IProjection srs;
444

    
445
                        while (rs.next()){
446
                                srsID = rs.getString("SRSID");
447
                                pgSrid = rs.getInt("SRID");
448
                                geomTypeStr = rs.getString("TYPE").toUpperCase();
449
                                geometryType = Geometry.TYPES.GEOMETRY;
450
                                if (geomTypeStr.startsWith("POINT")) {
451
                                        geometryType = Geometry.TYPES.POINT;
452
                                } else if (geomTypeStr.startsWith("LINESTRING")) {
453
                                        geometryType = Geometry.TYPES.CURVE;
454
                                } else if (geomTypeStr.startsWith("POLYGON")) {
455
                                        geometryType = Geometry.TYPES.SURFACE;
456
                                } else if (geomTypeStr.startsWith("MULTIPOINT")) {
457
                                        geometryType = Geometry.TYPES.MULTIPOINT;
458
                                } else if (geomTypeStr.startsWith("MULTILINESTRING")) {
459
                                        geometryType = Geometry.TYPES.MULTICURVE;
460
                                } else if (geomTypeStr.startsWith("MULTIPOLYGON")) {
461
                                        geometryType = Geometry.TYPES.MULTISURFACE;
462
                                }
463
                                dimensions = rs.getInt("coord_dimension");
464
                                geometrySubtype = Geometry.SUBTYPES.GEOM2D;
465
                                if (dimensions > 2) {
466
                                        if (dimensions == 3) {
467
                                                if (geomTypeStr.endsWith("M")) {
468
                                                        geometrySubtype = Geometry.SUBTYPES.GEOM2DM;
469
                                                } else {
470
                                                        geometrySubtype = Geometry.SUBTYPES.GEOM3D;
471
                                                }
472

    
473
                                        } else {
474
                                                geometrySubtype = Geometry.SUBTYPES.GEOM3DM;
475
                                        }
476
                                }
477
                                addToPgSRToSRSID(pgSrid, srsID);
478

    
479

    
480
                                iter = geoAttrs.iterator();
481
                                while (iter.hasNext()) {
482
                                        attr = (EditableFeatureAttributeDescriptor) iter.next();
483
                                        rsIndex = attr.getIndex() + 1;
484
                                        if (!rsMetadata.getColumnName(rsIndex).equals(
485
                                                        rs.getString("f_geometry_column"))) {
486
                                                continue;
487
                                        }
488

    
489
                                        if (baseSchema == null && baseTable == null) {
490

    
491
                                                if (rsMetadata instanceof PGResultSetMetaData) {
492
                                                        if (!((PGResultSetMetaData) rsMetadata)
493
                                                                        .getBaseTableName(rsIndex).equals(
494
                                                                                        rs.getString("f_table_name"))) {
495
                                                                continue;
496
                                                        }
497
                                                        String curSchema = rs.getString("f_table_schema");
498
                                                        String metaSchema = ((PGResultSetMetaData) rsMetadata)
499
                                                                        .getBaseSchemaName(rsIndex);
500
                                                        if (!metaSchema.equals(curSchema)) {
501
                                                                if (metaSchema.length() == 0
502
                                                                                && metaSchema == getDefaultSchema(conn)) {
503
                                                                } else {
504
                                                                        continue;
505
                                                                }
506
                                                        }
507

    
508
                                                } else {
509

    
510
                                                        if (!rsMetadata.getTableName(rsIndex).equals(
511
                                                                        rs.getString("f_table_name"))) {
512
                                                                continue;
513
                                                        }
514
                                                        String curSchema = rs.getString("f_table_schema");
515
                                                        String metaSchema = rsMetadata
516
                                                                        .getSchemaName(rsIndex);
517
                                                        if (!metaSchema.equals(curSchema)) {
518
                                                                if (metaSchema.length() == 0
519
                                                                                && metaSchema == getDefaultSchema(conn)) {
520
                                                                } else {
521
                                                                        continue;
522
                                                                }
523
                                                        }
524
                                                }
525
                                        }
526
                                        attr.setGeometryType(geometryType);
527
                                        attr.setGeometrySubType(geometrySubtype);
528
                                        if (srsID != null && srsID.length() > 0) {
529
                                                attr.setSRS(CRSFactory.getCRS(srsID));
530
                                        }
531
                                        iter.remove();
532
                                }
533
                                iter = geoAttrs.iterator();
534
                                while (iter.hasNext()) {
535
                                        attr = (EditableFeatureAttributeDescriptor) iter.next();
536
                                        attr.setSRS(null);
537
                                        attr.setGeometryType(Geometry.TYPES.GEOMETRY);
538

    
539
                                }
540
                        }
541

    
542
                } catch (java.sql.SQLException e) {
543
                        throw new JDBCSQLException(e);
544
                } finally {
545
                        try {rs.close();} catch (Exception e) {        };
546
                        try {st.close();} catch (Exception e) {        };
547
                }
548

    
549
        }
550

    
551

    
552
        public String getSqlColumnTypeDescription(FeatureAttributeDescriptor attr) {
553
                if (attr.getType() == DataTypes.GEOMETRY) {
554
                        return "geometry";
555
                }
556
                return super.getSqlColumnTypeDescription(attr);
557
        }
558

    
559

    
560
        public int getPostgisGeomDimensions(int geometrySubType) {
561
                switch (geometrySubType) {
562
                case Geometry.SUBTYPES.GEOM2D:
563
                        return 2;
564
                case Geometry.SUBTYPES.GEOM2DM:
565
                case Geometry.SUBTYPES.GEOM3D:
566
                        return 3;
567

    
568
                case Geometry.SUBTYPES.GEOM3DM:
569
                        return 4;
570
                default:
571
                        throw new UnsupportedDataTypeException(
572
                                        ToolsLocator.getDataTypesManager().getTypeName(DataTypes.GEOMETRY),
573
                                        DataTypes.GEOMETRY);
574
                }
575
        }
576

    
577
        public String getPostgisGeomType(int geometryType, int geometrySubType) {
578
                String pgGeomType;
579
                switch (geometryType) {
580
                case Geometry.TYPES.GEOMETRY:
581
                        pgGeomType = "GEOMETRY";
582
                        break;
583
                case Geometry.TYPES.POINT:
584
                        pgGeomType = "POINT";
585
                        break;
586
                case Geometry.TYPES.CURVE:
587
                        pgGeomType = "LINESTRING";
588
                        break;
589
                case Geometry.TYPES.SURFACE:
590
                        pgGeomType = "POLYGON";
591
                        break;
592
                case Geometry.TYPES.MULTIPOINT:
593
                        pgGeomType = "MULTIPOINT";
594
                        break;
595
                case Geometry.TYPES.MULTICURVE:
596
                        pgGeomType = "MULTILINESTRING";
597
                        break;
598
                case Geometry.TYPES.MULTISURFACE:
599
                        pgGeomType = "MULTIPOLYGON";
600
                        break;
601
                default:
602
                    logger.warn("Can't determine PostGIS geometry type, use GEOMETRY.");
603
                    pgGeomType = "GEOMETRY";
604
                }
605
                if (geometrySubType == Geometry.SUBTYPES.GEOM2DM
606
                                || geometrySubType == Geometry.SUBTYPES.GEOM3DM) {
607
                        pgGeomType = pgGeomType + "M";
608
                } /* else  if (geometrySubType == Geometry.SUBTYPES.GEOM3D) {
609
                        throw new UnsupportedGeometryException(geometryType,
610
                                        geometrySubType);
611
                   /
612
                } */
613
                return pgGeomType;
614
        }
615

    
616
        public int getProviderSRID(String srs) {
617
                if (srs != null) {
618
                        Integer pgSRID = (Integer) srsID2pgSR.get(srs);
619
                        if (pgSRID != null) {
620
                                return pgSRID.intValue();
621
                        }
622

    
623
                        return searchpgSRID(srs);
624

    
625
                }
626
                return -1;
627
        }
628

    
629

    
630
        public int getProviderSRID(IProjection srs) {
631
                if (srs != null) {
632
                        Integer pgSRID = (Integer) srsID2pgSR.get(srs.getAbrev());
633
                        if (pgSRID != null) {
634
                                return pgSRID.intValue();
635
                        }
636

    
637
                        return searchpgSRID(srs);
638

    
639
                }
640
                return -1;
641
        }
642

    
643
        private int searchpgSRID(final IProjection srs) {
644
                if (srs == null) {
645
                        return -1;
646
                }
647
                return searchpgSRID(srs.getAbrev());
648
        }
649

    
650
        private int searchpgSRID(final String srsID) {
651
                if (srsID == null) {
652
                        return -1;
653
                }
654

    
655
                ConnectionAction action = new ConnectionAction(){
656

    
657
                        public Object action(Connection conn) throws DataException {
658

    
659
                                String[] abrev = srsID.split(":");
660
                                StringBuilder sqlb = new StringBuilder();
661
                                sqlb.append("select srid from spatial_ref_sys where ");
662
                                if (abrev.length > 1) {
663
                                        sqlb.append("auth_name = ? and ");
664
                                }
665
                                sqlb.append("auth_srid = ?");
666

    
667
                                String sql = sqlb.toString();
668
                                PreparedStatement st;
669
                                try {
670
                                        st = conn.prepareStatement(sql);
671
                                } catch (SQLException e){
672
                                        throw new JDBCPreparingSQLException(sql,e);
673
                                }
674
                                ResultSet rs = null;
675
                                try{
676
                                        int i=0;
677
                                        if (abrev.length > 1){
678
                                                st.setString(i+1, abrev[i]);
679
                                                i++;
680
                                        }
681
                                        st.setInt(i + 1, Integer.parseInt(abrev[i]));
682

    
683
                                        try{
684
                                                rs = st.executeQuery();
685
                                        } catch (SQLException e){
686
                                                throw new JDBCExecutePreparedSQLException(sql, abrev, e);
687
                                        }
688

    
689
                                        if (!rs.next()) {
690
                                                return null;
691
                                        }
692

    
693
                                        return new Integer(rs.getInt(1));
694

    
695
                                } catch (SQLException e){
696
                                        throw new JDBCSQLException(e);
697
                                } finally{
698
                                        try {rs.close(); } catch (Exception e) {};
699
                                        try {st.close(); } catch (Exception e) {};
700
                                }
701

    
702
                        }
703

    
704
                };
705

    
706
                Integer pgSRSID = null;
707
                try {
708
                        pgSRSID = (Integer) doConnectionAction(action);
709
                } catch (Exception e) {
710
                        logger.error("Excetion searching pgSRS", e);
711
                        return -1;
712
                }
713

    
714
                if (pgSRSID != null) {
715
                        addToPgSRToSRSID(pgSRSID.intValue(), srsID);
716
                        return pgSRSID.intValue();
717
                }
718
                return -1;
719

    
720
        }
721

    
722
        private void addToPgSRToSRSID(int pgSRID, String srsId) {
723
                if (pgSRID < 0 || srsId == null || srsId.length() == 0) {
724
                        return;
725
                }
726
                Integer pgSRIDInteger = new Integer(pgSRID);
727
                pgSR2SRSID.put(pgSRIDInteger, srsId);
728
                srsID2pgSR.put(srsId, pgSRIDInteger);
729
        }
730

    
731
        public List<String> getSqlGeometyFieldAdd(FeatureAttributeDescriptor attr,
732
                        String table, String schema) {
733
                // SELECT AddGeometryColumn({schema}, {table}, {field}, {srid}(int),
734
                // {geomType}(Str), {dimensions}(int))
735

    
736
                // gemoType:
737
                /*
738
                 * POINT, LINESTRING, POLYGON, MULTIPOINT, MULTILINESTRING,
739
                 * MULTIPOLYGON, GEOMETRYCOLLECTION POINTM, LINESTRINGM, POLYGONM,
740
                 * MULTIPOINTM, MULTILINESTRINGM, MULTIPOLYGONM, GEOMETRYCOLLECTIONM
741
                 */
742

    
743
                List<String> sqls = new ArrayList<String>();
744

    
745
                StringBuilder strb = new StringBuilder();
746
                strb.append("SELECT AddGeometryColumn('");
747
                if (schema != null && schema.length() > 0) {
748
                        strb.append(schema);
749
                        strb.append("', '");
750
                }
751
                strb.append(table);
752
                strb.append("', '");
753
                strb.append(attr.getName().toLowerCase());
754
                strb.append("', ");
755
                // strb.append("-1");
756
                strb.append(getProviderSRID(attr.getSRS()));
757
                strb.append(", '");
758
                
759
                // ===========================================================================
760
            // TODO Improve this. Keep in mind that MULTIPOLYGON will not accept POLYGON
761
//        strb.append("GEOMETRY");
762
            
763
                strb.append( getPostgisGeomType(
764
                        attr.getGeometryType(), 
765
                        attr
766
                        .getGeometrySubType()
767
                )
768
        );
769
        // ===========================================================================
770
                strb.append("', ");
771
                strb.append(getPostgisGeomDimensions(attr.getGeometrySubType()));
772
                strb.append(")");
773

    
774

    
775
                sqls.add(strb.toString());
776

    
777
                /*ALTER TABLE muni10000_peq_test DROP CONSTRAINT enforce_srid_the_geom;*/
778
                /*
779
                strb = new StringBuilder();
780
                strb.append("Alter table ");
781
                if (schema != null && schema.length() > 0) {
782
                        strb.append(schema);
783
                        strb.append(".");
784
                }
785
                strb.append("f_table_name = '");
786
                strb.append(table);
787
                strb.append("' AND f_geometry_column = '");
788
                strb.append(attr.getName());
789
                strb.append("' AND srid = -1");
790

791

792
                sqls.add(strb.toString());
793
                */
794
                return sqls;
795
        }
796

    
797
        public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
798
                if (attribute.getType() == DataTypes.GEOMETRY) {
799
                        return getFunctionName("ST_AsBinary") + "("
800
                            + super.getSqlFieldName(attribute) + ")";
801
                }
802
                return super.getSqlFieldName(attribute);
803
        }
804

    
805
        protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
806
                        EditableFeatureType type, Connection conn,
807
                        ResultSetMetaData rsMetadata, int colIndex) throws SQLException {
808
                if (rsMetadata.getColumnType(colIndex) == java.sql.Types.OTHER) {
809
                        if (rsMetadata.getColumnTypeName(colIndex).equalsIgnoreCase(
810
                                        "geometry")) {
811
                                EditableFeatureAttributeDescriptor attr = type.add(rsMetadata.getColumnName(colIndex),
812
                                                DataTypes.GEOMETRY);
813
                                // Set default values for geometry type
814
                                attr.setGeometryType(Geometry.TYPES.GEOMETRY);
815
                                attr.setGeometrySubType(Geometry.SUBTYPES.GEOM2D);
816
                                return attr;
817

    
818
                        }
819
                }
820

    
821
                return super.createAttributeFromJDBC(type, conn, rsMetadata, colIndex);
822
        }
823

    
824
        public List getAdditionalSqlToCreate(NewDataStoreParameters ndsp,
825
                        FeatureType fType) {
826
                FeatureAttributeDescriptor attr;
827
                Iterator iter = fType.iterator();
828
                List result = new ArrayList();
829
                PostgreSQLNewStoreParameters pgNdsp = (PostgreSQLNewStoreParameters) ndsp;
830
                while (iter.hasNext()){
831
                        attr = (FeatureAttributeDescriptor) iter.next();
832
                        if (attr.getType() == DataTypes.GEOMETRY){
833
                                result.addAll(getSqlGeometyFieldAdd(attr, pgNdsp.getTable(),
834
                                                pgNdsp
835
                                                .getSchema()));
836
                        }
837
                }
838

    
839
                return result;
840
        }
841

    
842
        public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
843
                        throws DataException {
844
                if (attr.getType() == DataTypes.GEOMETRY){
845
                        return null;
846
                }
847
                return super.getSqlFieldDescription(attr);
848
        }
849

    
850

    
851
        public boolean allowAutomaticValues() {
852
                return Boolean.TRUE;
853
        }
854

    
855
        public boolean supportOffset() {
856
                return true;
857
        }
858

    
859
        public boolean supportsUnion() {
860
                return true;
861
        }
862
        
863
        public String escapeFieldName(String field) {
864
                /*
865
                if (!reservedWord(field) && 
866
                                field.matches("[a-z][a-z0-9_]*")) {
867
                        return field;
868
                }
869
                */
870
                String quote = getIdentifierQuoteString();
871
                return quote + field + quote;
872
        }
873
        
874
    protected EditableFeatureAttributeDescriptor createAttributeFromJDBCNativeType(
875
        EditableFeatureType fType, ResultSetMetaData rsMetadata, int colIndex)
876
        throws SQLException {
877

    
878
        EditableFeatureAttributeDescriptor column;
879

    
880
        String nativeType = rsMetadata.getColumnTypeName(colIndex);
881

    
882
        if (nativeType.startsWith("int")) {
883
            column = fType.add(rsMetadata.getColumnName(colIndex),
884
                DataTypes.INT);
885
            column.setAdditionalInfo("SQLType", new Integer(rsMetadata
886
                .getColumnType(colIndex)));
887
            column.setAdditionalInfo("SQLTypeName", rsMetadata
888
                .getColumnTypeName(colIndex));
889
            return column;
890
        }
891
        return super.createAttributeFromJDBCNativeType(fType, rsMetadata, colIndex);
892
    }
893

    
894
    public Object dalValueToJDBC(
895
        FeatureAttributeDescriptor attributeDescriptor, Object object)
896
        throws WriteException {
897
           if ("int2".equals(attributeDescriptor.getAdditionalInfo("SQLTypeName"))) {
898
                return new Short(String.valueOf(object));
899
            }
900

    
901
        return super.dalValueToJDBC(attributeDescriptor, object);
902
    }
903
    
904
    // =======================================
905
    
906

    
907
    public String getFunctionName(String newFuncName) {
908
        
909
        if (!versionSet) {
910
            postGISVersion = getPostgisVersion();
911
            versionSet = true;
912
        }
913
        return getFunctionNameForVersion(newFuncName, postGISVersion);
914
    }
915

    
916
    private String getFunctionNameForVersion(String newFuncName, int[] pv) {
917
        
918
        if (newFuncName == null || pv == null) {
919
            return newFuncName;
920
        }
921
        
922
        if (pv.length < 2) {
923
            // cannot compare
924
            return newFuncName;
925
        }
926
        
927
        if (pv[0] > 1) {
928
            return newFuncName;
929
        }
930
        
931
        if (pv[0] == 1 && pv[1] >= 3) {
932
            return newFuncName;
933
        }
934
        
935
        Properties pp = this.getBeforePostgis13Properties();
936
        String k = newFuncName.toLowerCase();
937
        String v = pp.getProperty(k);
938
        if (v == null) {
939
            return newFuncName;
940
        } else {
941
            return v;
942
        }
943
    }
944

    
945

    
946
    private int[] getPostgisVersion() {
947

    
948
        String sql = "SELECT PostGIS_Lib_Version()";
949
        ResultSet rs = null;
950
        Statement st = null;
951
        String v = null;
952
        Connection conn = null;
953
        try {
954
            conn = this.getConnection();
955
            st = conn.createStatement();
956
            rs = st.executeQuery(sql);
957
            rs.next();
958
            v = rs.getString(1);
959
            if (v == null) {
960
                throw new Exception("Returned version is NULL");
961
            }
962
        } catch (Exception exc) {
963
            logger.error("Unable to get Postgis version: " + exc.getMessage(), exc);
964
            return null;
965
        } finally {
966
            try { rs.close(); } catch (Exception e) {};
967
            try { st.close(); } catch (Exception e) {};
968
            try { conn.close(); } catch (Exception e) {};
969
        }
970

    
971
        String[] vv = v.split("\\.");
972
        int[] resp = new int[3];
973
        try {
974
            for (int i=0; i<3; i++) {
975
                resp[i] = Integer.parseInt(vv[i]);
976
            }
977
        } catch (Exception exc) {
978
            logger.error("Unable to parse version: " + v, exc);
979
            return null;
980
        }
981
        return resp;
982
    }
983
    
984
    
985
    
986
    protected Properties getBeforePostgis13Properties() {
987
        if (beforePostgis13 == null) {
988
            
989
            beforePostgis13 = new Properties();
990
            // Left side MUST be in lower case
991
            // Right side will be used if Postgis version < 1.3
992
            beforePostgis13.setProperty("st_intersects", "Intersects");
993
            beforePostgis13.setProperty("st_extent", "Extent");
994
            beforePostgis13.setProperty("st_envelope", "Envelope");
995
            beforePostgis13.setProperty("st_asbinary", "AsBinary");
996
            beforePostgis13.setProperty("st_geomfromtext", "GeomFromText");
997
            beforePostgis13.setProperty("st_geomfromwkb", "GeomFromWKB");
998
        }
999
        return beforePostgis13;
1000
    }
1001
    
1002

    
1003

    
1004
}