Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / org.gvsig.oracle / src / org / gvsig / fmap / dal / store / oracle / OracleHelper.java @ 38077

History | View | Annotate | Download (32.5 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 Prodevelop S.L. main development
26
 */
27

    
28
package org.gvsig.fmap.dal.store.oracle;
29

    
30
import java.awt.geom.Rectangle2D;
31
import java.sql.Connection;
32
import java.sql.ResultSet;
33
import java.sql.ResultSetMetaData;
34
import java.sql.SQLException;
35
import java.sql.Statement;
36
import java.util.ArrayList;
37
import java.util.Iterator;
38
import java.util.List;
39

    
40
import oracle.sql.ARRAY;
41
import oracle.sql.Datum;
42
import oracle.sql.STRUCT;
43

    
44
import org.cresques.cts.IProjection;
45
import org.gvsig.fmap.crs.CRSFactory;
46
import org.gvsig.fmap.dal.DALLocator;
47
import org.gvsig.fmap.dal.DataTypes;
48
import org.gvsig.fmap.dal.exception.DataException;
49
import org.gvsig.fmap.dal.exception.InitializeException;
50
import org.gvsig.fmap.dal.exception.ReadException;
51
import org.gvsig.fmap.dal.feature.EditableFeatureAttributeDescriptor;
52
import org.gvsig.fmap.dal.feature.EditableFeatureType;
53
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
54
import org.gvsig.fmap.dal.feature.exception.UnsupportedDataTypeException;
55
import org.gvsig.fmap.dal.feature.exception.UnsupportedGeometryException;
56
import org.gvsig.fmap.dal.feature.impl.DefaultEditableFeatureAttributeDescriptor;
57
import org.gvsig.fmap.dal.feature.impl.DefaultEditableFeatureType;
58
import org.gvsig.fmap.dal.resource.ResourceAction;
59
import org.gvsig.fmap.dal.resource.spi.ResourceManagerProviderServices;
60
import org.gvsig.fmap.dal.store.jdbc.ConnectionAction;
61
import org.gvsig.fmap.dal.store.jdbc.JDBCHelper;
62
import org.gvsig.fmap.dal.store.jdbc.JDBCHelperUser;
63
import org.gvsig.fmap.dal.store.jdbc.JDBCStoreParameters;
64
import org.gvsig.fmap.dal.store.jdbc.TransactionalAction;
65
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCException;
66
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCExecuteSQLException;
67
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCSQLException;
68
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCTransactionCommitException;
69
import org.gvsig.fmap.dal.store.jdbc.exception.JDBCTransactionRollbackException;
70
import org.gvsig.fmap.geom.Geometry;
71
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
72
import org.gvsig.fmap.geom.Geometry.TYPES;
73
import org.gvsig.fmap.geom.primitive.Envelope;
74
import org.gvsig.fmap.geom.primitive.Point;
75
import org.gvsig.fmap.geom.primitive.impl.Envelope2D;
76
import org.gvsig.fmap.geom.primitive.impl.Envelope3D;
77
import org.gvsig.fmap.geom.primitive.impl.Point2DZ;
78
import org.gvsig.tools.exception.BaseException;
79
import org.slf4j.Logger;
80
import org.slf4j.LoggerFactory;
81

    
82
/**
83
 * Oracle helper
84
 * 
85
 * @author vsanjaime
86
 * 
87
 */
88
public class OracleHelper extends JDBCHelper {
89

    
90

    
91
        private static final double ORACLE_SPATIAL_DEFAULT_TOLERANCE = 0.0005;
92

    
93
        private static final String IDENTIFIER_QUOTE_STRING = "\"";
94

    
95
        private static Logger logger = LoggerFactory.getLogger(OracleHelper.class);
96

    
97
        // private boolean tableHasSrid = true;
98
        // private String oracleSRID;
99
        private IProjection viewProjection = null;
100

    
101

    
102

    
103
        /**
104
         * Constructor
105
         * 
106
         * @param consumer
107
         * @param params
108
         * @throws InitializeException
109
         */
110
        public OracleHelper(JDBCHelperUser consumer,
111
                        OracleConnectionParameters params) throws InitializeException {
112

    
113
                super(consumer, params);
114
        }
115

    
116
        /**
117
         * Initialize resource
118
         * 
119
         * @throws InitializeException
120
         */
121
        protected void initializeResource() throws InitializeException {
122
                ResourceManagerProviderServices manager = (ResourceManagerProviderServices) DALLocator
123
                                .getResourceManager();
124
                OracleResource resource = (OracleResource) manager.createResource(
125
                                OracleResource.NAME, new Object[] {
126
                                                params.getUrl(),
127
                                                params.getHost(),
128
                                                params.getPort(),
129
                                                params.getDBName(),
130
                                                params.getUser(),
131
                                                params.getPassword(),
132
                                                params.getJDBCDriverClassName(),
133
                                                ((OracleConnectionParameters) params).getUseSSL(),
134
                                                ((OracleConnectionParameters) params)
135
                                                                .getOraDriverType() });
136
                this.setResource(resource);
137
        }
138

    
139
        /**
140
         * Get default schema name
141
         * 
142
         * @param conn
143
         * @return
144
         */
145
        protected String getDefaultSchema(Connection conn) throws JDBCException {
146
                if (defaultSchema == null) {
147
                        String sql = "SELECT sys_context('USERENV', 'CURRENT_SCHEMA') FROM dual";
148
                        ResultSet rs = null;
149
                        Statement st = null;
150
                        String schema = null;
151
                        try {
152
                                st = conn.createStatement();
153
                                try {
154
                                        rs = st.executeQuery(sql);
155
                                } catch (java.sql.SQLException e) {
156
                                        throw new JDBCExecuteSQLException(sql, e);
157
                                }
158
                                rs.next();
159
                                schema = rs.getString(1);
160
                        } catch (java.sql.SQLException e) {
161
                                throw new JDBCSQLException(e);
162
                        } finally {
163
                                try {
164
                                        rs.close();
165
                                } catch (Exception e) {
166
                                        logger.error("Exception clossing resulset", e);
167
                                }
168
                                ;
169
                                try {
170
                                        st.close();
171
                                } catch (Exception e) {
172
                                        logger.error("Exception clossing statement", e);
173
                                }
174
                                ;
175
                                rs = null;
176
                                st = null;
177
                        }
178
                        defaultSchema = schema;
179
                }
180

    
181
                return defaultSchema;
182
        }
183

    
184
        /**
185
         * get full envelope of geometry field
186
         */
187
        public Envelope getFullEnvelopeOfField(JDBCStoreParameters storeParams,
188
                        String geometryAttrName, Envelope limit) throws DataException {
189
                
190
                Object filterobj = storeParams.getDynValue("filterarea");
191
                if (filterobj != null && filterobj instanceof Geometry) {
192
                        Geometry filtergeom = (Geometry) filterobj;
193
                        return filtergeom.getEnvelope();
194
                }
195
                
196
                if (limit != null) {
197
                        return limit; 
198
                }
199

    
200
                String _schema = (String) ((OracleStoreParameters) storeParams).getDynValue("schema");
201
                
202
                StringBuilder strb = new StringBuilder();
203
                strb.append("SELECT * FROM "
204
                                + OracleValues.ALL_ORACLE_GEOMETADATA_VIEW);
205
                strb.append(" WHERE "
206
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_TABLE_NAME
207
                                + " = '" + storeParams.getTable() + "'");
208
                strb.append(" AND "
209
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_COLUMN_NAME
210
                                + " = '" + geometryAttrName + "'");
211
                strb.append(" AND "
212
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_OWNER
213
                                + " = '" + _schema + "'");
214
                String sql = strb.toString();
215

    
216
                ResultSet rs = null;
217
                Statement st = null;
218
                // String schema = null;
219
                Connection conn = null;
220

    
221
                Envelope fullEnvelope = null;
222
                this.open();
223
                try {
224
                        conn = getConnection();
225
                        st = conn.createStatement();
226
                        try {
227
                                rs = st.executeQuery(sql);
228
                        } catch (java.sql.SQLException e) {
229
                                throw new JDBCExecuteSQLException(sql, e);
230
                        }
231
                        if (!rs.next()) {
232
                                return null;
233
                        }
234

    
235
                        // DIMINFO (ARRAY)
236
                        ARRAY dim_info_array = (ARRAY) rs.getObject("DIMINFO");
237

    
238
                        Datum[] da = dim_info_array.getOracleArray();
239
                        int dim = da.length;
240

    
241
                        STRUCT sx = (STRUCT) da[0];
242
                        STRUCT sy = (STRUCT) da[1];
243
                        double minx = Double.parseDouble(sx.getAttributes()[1].toString());
244
                        double maxx = Double.parseDouble(sx.getAttributes()[2].toString());
245
                        double miny = Double.parseDouble(sy.getAttributes()[1].toString());
246
                        double maxy = Double.parseDouble(sy.getAttributes()[2].toString());
247
                        if (minx > maxx) {
248
                                double aux = minx;
249
                                minx = maxx;
250
                                maxx = aux;
251
                        }
252

    
253
                        if (miny > maxy) {
254
                                double aux = miny;
255
                                miny = maxy;
256
                                maxy = aux;
257
                        }
258

    
259
                        // dim 3
260
                        STRUCT sz = null;
261
                        double minz = 0;
262
                        double maxz = 0;
263
                        if (dim == 2) {
264
                                fullEnvelope = new Envelope2D(minx, miny, maxx, maxy);
265
                        } else if (dim == 3) {
266
                                sz = (STRUCT) da[2];
267
                                minz = Double.parseDouble(sz.getAttributes()[1].toString());
268
                                maxz = Double.parseDouble(sz.getAttributes()[2].toString());
269

    
270
                                Point minPto = new Point2DZ(minx, miny, minz);
271
                                Point maxPto = new Point2DZ(maxx, maxy, maxz);
272

    
273
                                fullEnvelope = new Envelope3D(minPto, maxPto);
274
                        }
275

    
276
                        return fullEnvelope;
277

    
278
                } catch (Exception e) {
279
                        return null;
280
                }
281

    
282
                finally {
283
                        try {
284
                                rs.close();
285
                        } catch (Exception e) {
286
                        }
287

    
288
                        try {
289
                                st.close();
290
                        } catch (Exception e) {
291
                        }
292

    
293
                        /*
294
                        try {
295
                                conn.close();
296
                        } catch (Exception e) {
297
                        }
298
                        */
299

    
300
                        finally {
301
                                rs = null;
302
                                st = null;
303
                                conn = null;
304
                        }
305
                }
306
        }
307

    
308
        /**
309
         * 
310
         */
311
//        protected void initializeFromWKBOperation() throws BaseException {
312
//                // TODO
313
//                if (fromWKB == null) {
314
//                        fromWKB = (FromWKB) GeometryLocator.getGeometryManager()
315
//                                        .getGeometryOperation(FromWKB.CODE,
316
//                                                        Geometry.TYPES.GEOMETRY, Geometry.SUBTYPES.GEOM2D);
317
//                        fromWKBContext = new FromWKBGeometryOperationContext();
318
//                }
319
//        }
320

    
321
        /**
322
         * 
323
         */
324
        public Geometry getGeometry(byte[] buffer) throws BaseException {
325
                // TODO BLOB format in Oracle?
326
                logger.error("Unsupported: binary Geometry format");
327
                return null;
328
        }
329

    
330
        /**
331
         * get geometry column name "SDO_GEOMETRY"
332
         * 
333
         * @param attr
334
         * @return
335
         */
336
        public String getSqlColumnTypeDescription(FeatureAttributeDescriptor attr) {
337

    
338
                switch (attr.getDataType().getType()) {
339

    
340
                case DataTypes.GEOMETRY:
341
                        return "\"MDSYS\".\"SDO_GEOMETRY\"";
342

    
343
                case DataTypes.STRING:
344
                        return "NVARCHAR2(" + attr.getSize() + ")";
345

    
346
                case DataTypes.BOOLEAN:
347
                        return "NUMBER(1, 0)";
348

    
349
                case DataTypes.BYTE:
350
                        return "NUMBER";
351

    
352
                case DataTypes.DATE:
353
                        return "DATE";
354

    
355
                case DataTypes.TIMESTAMP:
356
                        return "TIMESTAMP";
357

    
358
                case DataTypes.TIME:
359
                        return "TIMESTAMP";
360

    
361
                case DataTypes.BYTEARRAY:
362

    
363
                case DataTypes.DOUBLE:
364
                        return "FLOAT";
365

    
366
                case DataTypes.FLOAT:
367
                        return "FLOAT";
368

    
369
                case DataTypes.INT:
370
                        return "NUMBER(12, 0)";
371

    
372
                case DataTypes.LONG:
373
                        return "NUMBER(38, 0)";
374

    
375
                default:
376
                        String typeName = (String) attr.getAdditionalInfo("SQLTypeName");
377
                        if (typeName != null) {
378
                                return typeName;
379
                        }
380
                        throw new UnsupportedDataTypeException(attr.getDataTypeName(), attr
381
                                        .getDataType().getType());
382
                }
383

    
384
        }
385

    
386
        /**
387
         * Get oracle geometry dimension
388
         * 
389
         * @param geometrySubType
390
         * @return
391
         */
392
        public int getOraGeomDimensions(int geometrySubType) {
393

    
394
                switch (geometrySubType) {
395
                case Geometry.SUBTYPES.GEOM2D:
396
                        return 2;
397
                case Geometry.SUBTYPES.GEOM2DM:
398
                case Geometry.SUBTYPES.GEOM3D:
399
                        return 3;
400
                case Geometry.SUBTYPES.GEOM3DM:
401
                        return 4;
402
                default:
403
                        throw new UnsupportedDataTypeException(
404
                                        "GEOMETRY field",
405
                                        DataTypes.GEOMETRY);
406
                }
407
        }
408

    
409
        /**
410
         * Get Oracle geometry type
411
         * 
412
         * @param geometryType
413
         * @param geometrySubType
414
         * @return
415
         */
416
        public String getOraGeomType(int geometryType, int geometrySubType) {
417
                String oraGeomType;
418
                switch (geometryType) {
419
                case Geometry.TYPES.GEOMETRY:
420
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
421
                        break;
422
                case Geometry.TYPES.POINT:
423
                        oraGeomType = OracleValues.OraGeometry_GTYPE_POINT;
424
                        break;
425
                case Geometry.TYPES.CURVE:
426
                        oraGeomType = OracleValues.OraGeometry_GTYPE_CURVE;
427
                        break;
428
                /*
429
                case Geometry.TYPES..TEXT:
430
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
431
                        break;
432
                */
433
                case Geometry.TYPES.SOLID:
434
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
435
                        break;
436
                case Geometry.TYPES.AGGREGATE:
437
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
438
                        break;
439
                case Geometry.TYPES.SURFACE:
440
                        oraGeomType = OracleValues.OraGeometry_GTYPE_POLYGON;
441
                        break;
442
                case Geometry.TYPES.MULTIPOINT:
443
                        oraGeomType = OracleValues.OraGeometry_GTYPE_MULTIPOINT;
444
                        break;
445
                case Geometry.TYPES.MULTICURVE:
446
                        oraGeomType = OracleValues.OraGeometry_GTYPE_MULTICURVE;
447
                        break;
448
                case Geometry.TYPES.MULTISURFACE:
449
                        oraGeomType = OracleValues.OraGeometry_GTYPE_MULTIPOLYGON;
450
                        break;
451
                case Geometry.TYPES.MULTISOLID:
452
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
453
                        break;
454
                case Geometry.TYPES.CIRCLE:
455
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
456
                        break;
457
                case Geometry.TYPES.ARC:
458
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
459
                        break;
460
                case Geometry.TYPES.ELLIPSE:
461
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
462
                        break;
463
                case Geometry.TYPES.SPLINE:
464
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
465
                        break;
466
                case Geometry.TYPES.ELLIPTICARC:
467
                        oraGeomType = OracleValues.OraGeometry_GTYPE_GEOMETRY;
468
                        break;
469
                default:
470
                        throw new UnsupportedGeometryException(geometryType,
471
                                        geometrySubType);
472
                }
473
                return oraGeomType;
474
        }
475

    
476
        /**
477
         * 
478
         */
479
        public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
480
                /*
481
                if (attribute.getDataType() == DataTypes.GEOMETRY) {
482
                        return "asBinary(" + super.getSqlFieldName(attribute) + ")";
483
                }
484
                */
485
                return super.getSqlFieldName(attribute);
486
        }
487
        
488
        protected String getIdentifierQuoteString() {
489
                return IDENTIFIER_QUOTE_STRING;
490
        }
491

    
492
        /**
493
         * 
494
         */
495
        protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
496
                        EditableFeatureType fType, Connection conn,
497
                        ResultSetMetaData rsMetadata, int colIndex) throws SQLException {
498
                
499
                String rstypename = rsMetadata.getColumnTypeName(colIndex);
500
                if (rstypename
501
                                .equalsIgnoreCase(OracleValues.OraGeometry_GTYPE_GEOMETRY)) {
502

    
503
                        return fType.add(rsMetadata.getColumnName(colIndex),
504
                                        DataTypes.GEOMETRY);
505
                }
506

    
507
                EditableFeatureAttributeDescriptor column;
508
                switch (rsMetadata.getColumnType(colIndex)) {
509
                case java.sql.Types.INTEGER:
510
                        column = fType.add(rsMetadata.getColumnName(colIndex),
511
                                        DataTypes.INT);
512
                        break;
513
                case java.sql.Types.BIGINT:
514
                        column = fType.add(rsMetadata.getColumnName(colIndex),
515
                                        DataTypes.LONG);
516
                        break;
517
                case java.sql.Types.REAL:
518
                        column = fType.add(rsMetadata.getColumnName(colIndex),
519
                                        DataTypes.DOUBLE);
520
                        break;
521
                case java.sql.Types.DOUBLE:
522
                        column = fType.add(rsMetadata.getColumnName(colIndex),
523
                                        DataTypes.DOUBLE);
524
                        break;
525
                case java.sql.Types.CHAR:
526
                        column = fType.add(rsMetadata.getColumnName(colIndex),
527
                                        DataTypes.STRING);
528
                        break;
529
                case java.sql.Types.VARCHAR:
530
                case java.sql.Types.LONGVARCHAR:
531
                        column = fType.add(rsMetadata.getColumnName(colIndex),
532
                                        DataTypes.STRING);
533
                        break;
534
                case java.sql.Types.FLOAT:
535
                        column = fType.add(rsMetadata.getColumnName(colIndex),
536
                                        DataTypes.FLOAT);
537
                        break;
538
                case java.sql.Types.DECIMAL:
539
                        column = fType.add(rsMetadata.getColumnName(colIndex),
540
                                        DataTypes.FLOAT);
541
                        break;
542
                case java.sql.Types.DATE:
543
                        column = fType.add(rsMetadata.getColumnName(colIndex),
544
                                        DataTypes.DATE);
545
                        break;
546
                case java.sql.Types.TIME:
547
                        column = fType.add(rsMetadata.getColumnName(colIndex),
548
                                        DataTypes.TIME);
549
                        break;
550
                case java.sql.Types.TIMESTAMP:
551
                        column = fType.add(rsMetadata.getColumnName(colIndex),
552
                                        DataTypes.TIMESTAMP);
553
                        break;
554
                case java.sql.Types.BOOLEAN:
555
                        column = fType.add(rsMetadata.getColumnName(colIndex),
556
                                        DataTypes.BOOLEAN);
557
                        break;
558
                case java.sql.Types.BLOB:
559
                case java.sql.Types.BINARY:
560
                case java.sql.Types.LONGVARBINARY:
561
                        column = fType.add(rsMetadata.getColumnName(colIndex),
562
                                        DataTypes.BYTEARRAY);
563
                        break;
564

    
565
                case java.sql.Types.NUMERIC:
566
                        
567
                        // decimal positions to the right of point
568
                        int scale = rsMetadata.getScale(colIndex);
569
                        // decimal positions to the right of point
570
                        // int leftdigits = rsMetadata.getPrecision(colIndex);
571
                        
572
                        if (scale == 0) { 
573
                                column = fType.add(rsMetadata.getColumnName(colIndex),
574
                                                DataTypes.LONG);
575
                        } else {
576
                                column = fType.add(rsMetadata.getColumnName(colIndex),
577
                                                DataTypes.DOUBLE);
578
                        }
579
                        
580
                        break;
581

    
582
                default:
583
                        column = fType.add(rsMetadata.getColumnName(colIndex),
584
                                        DataTypes.OBJECT);
585
                        column.setAdditionalInfo("SQLType", new Integer(rsMetadata
586
                                        .getColumnType(colIndex)));
587
                        column.setAdditionalInfo("SQLTypeName", rsMetadata
588
                                        .getColumnTypeName(colIndex));
589

    
590
                        break;
591
                }
592

    
593
                return column;
594

    
595

    
596
                // return super.createAttributeFromJDBC(type, conn, rsMetadata, colIndex);
597
        }
598

    
599
        /**
600
         * 
601
         */
602
        public boolean allowAutomaticValues() {
603
                return Boolean.TRUE;
604
        }
605

    
606
        /**
607
         * 
608
         */
609
        public boolean supportOffset() {
610
                return true;
611
        }
612

    
613
        /**
614
         * 
615
         */
616
        public boolean supportsUnion() {
617
                return true;
618
        }
619

    
620
        /**
621
         * get sql with fields description
622
         * 
623
         * @param attr
624
         * @return
625
         */
626
        public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
627
                        throws DataException {
628

    
629
                StringBuilder strb = new StringBuilder();
630
                // name
631
                strb.append("\"" + attr.getName() + "\" ");
632

    
633
                // Type
634
                strb.append(this.getSqlColumnTypeDescription(attr));
635

    
636
                // Primary key
637
                if (attr.isPrimaryKey()) {
638
                        strb.append(" PRIMARY KEY");
639
                }
640

    
641
                return strb.toString();
642
        }
643

    
644
        /**
645
         * UTility method to get the SQL sentence needed to update the geographic
646
         * metadata table with a new bounding box and SRS
647
         * 
648
         * @param tName
649
         *            table name
650
         * @param ora_srid
651
         *            new SRS
652
         * @param bbox
653
         *            new bounding box
654
         * @param dim
655
         *            geometries dimension
656
         * @param withsrid
657
         *            False if the SRS is set to NULL. True otherwise.
658
         * @return the SQL sentence to perform the update
659
         */
660
        public String getSqlUpdateMetadata(OracleStoreParameters params,
661
                        String ora_srid, Rectangle2D bbox, int dim, boolean withsrid) {
662

    
663
                String[] dim_name = new String[dim];
664
                // double tolerance = ORACLE_SPATIAL_DEFAULT_TOLERANCE;
665

    
666
                String _ora_srid = ora_srid;
667
                if (_ora_srid == null)
668
                        _ora_srid = "NULL";
669

    
670
                if (_ora_srid.compareTo(OracleValues.GEODETIC_SRID) == 0) {
671
                        dim_name[0] = "LONGITUDE";
672
                        dim_name[1] = "LATITUDE";
673
                } else {
674
                        dim_name[0] = "X";
675
                        dim_name[1] = "Y";
676

    
677
                        if (dim > 2) {
678
                                dim_name[2] = "Z";
679

    
680
                                if (dim > 3) {
681
                                        dim_name[3] = "T";
682
                                }
683
                        }
684
                }
685

    
686
                double minx = bbox.getMinX();
687
                double miny = bbox.getMinY();
688
                double maxx = bbox.getMaxX();
689
                double maxy = bbox.getMaxY();
690

    
691
                String resp = "INSERT INTO "
692
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW + " "
693
                                + " ( TABLE_NAME, COLUMN_NAME, DIMINFO, SRID ) " + " VALUES ("
694
                                + "'" + params.getTable() + "', " + "'"
695
                                + OracleValues.DEFAULT_GEO_FIELD + "', "
696
                                + "MDSYS.SDO_DIM_ARRAY( " + "MDSYS.SDO_DIM_ELEMENT ('"
697
                                + dim_name[0] + "', " + minx + ", " + maxx + ", " + ORACLE_SPATIAL_DEFAULT_TOLERANCE
698
                                + " ), " + "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[1] + "', "
699
                                + miny + ", " + maxy + ", " + ORACLE_SPATIAL_DEFAULT_TOLERANCE + " ))";
700

    
701
                if (dim > 2) {
702
                        resp = resp.substring(0, resp.length() - 1) + ",";
703
                        resp = resp + "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[2]
704
                                        + "', 0.0, 100.0, " + ORACLE_SPATIAL_DEFAULT_TOLERANCE + " ))";
705

    
706
                        if (dim > 3) {
707
                                resp = resp.substring(0, resp.length() - 1) + ",";
708
                                resp = resp + "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[3]
709
                                                + "', 0.0, 100.0, " + ORACLE_SPATIAL_DEFAULT_TOLERANCE + " ))";
710
                        }
711
                }
712

    
713
                if (withsrid) {
714
                        resp = resp + ", " + _ora_srid + " )";
715
                } else {
716
                        resp = resp + ", NULL )";
717
                }
718

    
719
                return resp;
720
        }
721

    
722

    
723
        
724
        
725
        /**
726
         * 
727
         */
728
        public void loadFeatureType(EditableFeatureType featureType,
729
                        JDBCStoreParameters storeParams) throws DataException {
730
                
731
                if ((storeParams.getDefaultGeometryField() == null) && (storeParams instanceof OracleNewStoreParameters)) {
732
                        OracleNewStoreParameters osp = (OracleNewStoreParameters) storeParams;
733
                        String geoname = osp.getDefaultFeatureType().getDefaultGeometryAttributeName();
734
                        storeParams.setDefaultGeometryField(geoname);
735
                }
736

    
737
                String sqlstr = storeParams.getSQL();
738
                
739
                if (sqlstr != null && sqlstr.trim().length() > 0) {
740
                        // loadFeatureType(featureType, storeParams, sqlstr);
741
                } else {
742
                        sqlstr = "SELECT * FROM " + storeParams.tableID() + " WHERE ROWID = NULL";
743
                        storeParams.setSQL(sqlstr);
744
                }
745
                
746
                loadFeatureType(featureType, storeParams, sqlstr, storeParams
747
                                .getSchema(), storeParams.getTable());
748
                
749
                storeParams.setSQL(null);
750
                // super.loadFeatureType(featureType, storeParams);
751
        }
752

    
753
        /**
754
         * Fill <code>featureType</code> geometry attributes with ShapeType
755
         * information stored in the table USER_SDO_GEOMETRY_METADATA
756
         * 
757
         * @param conn
758
         * @param rsMetadata
759
         * @param featureType
760
         * @throws ReadException
761
         */
762
        protected void loadSRS_and_shapeType(Connection conn,
763
                        ResultSetMetaData rs_Metadata, EditableFeatureType featureType,
764
                        String baseSchema, String baseTable) throws JDBCException {
765

    
766
                Statement st = null;
767
                ResultSet rs = null;
768
                String reserved_geocolname = null;
769
                
770
                try {
771
                        // Sacamos la lista de los attributos geometricos
772

    
773
                        EditableFeatureAttributeDescriptor attr;
774
                        ArrayList geoAttrs = new ArrayList();
775

    
776
                        Iterator iter = featureType.iterator();
777
                        while (iter.hasNext()) {
778
                                attr = (EditableFeatureAttributeDescriptor) iter.next();
779
                                if (attr.getDataType().getType() == DataTypes.GEOMETRY) {
780
                                        geoAttrs.add(attr);
781
                                }
782
                        }
783
                        if (geoAttrs.size() < 1) {
784
                                return;
785
                        }
786

    
787
                        // Preparamos una sql para que nos saque el resultado
788
                        StringBuilder strb = new StringBuilder();
789
                        strb.append("SELECT * FROM "
790
                                        + OracleValues.USER_ORACLE_GEOMETADATA_VIEW + " WHERE "
791
                                        + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_TABLE_NAME
792
                                        + " = '" + baseTable + "'");
793
                        String sql = strb.toString();
794

    
795
                        st = conn.createStatement();
796
                        try {
797
                                rs = st.executeQuery(sql);
798
                        } catch (SQLException e) {
799
                                throw new JDBCExecuteSQLException(sql, e);
800
                        }
801
                        
802
                        String srID;
803

    
804
                        EditableFeatureAttributeDescriptor auxdesc;
805
                        
806

    
807
                                while (rs.next()) {
808
                                        String rsName =
809
                                                rs.getString(OracleValues.USER_ORACLE_GEOMETADATA_VIEW_COLUMN_NAME);
810
                                        reserved_geocolname = rsName;
811
                                        auxdesc = getAttrDescForCol(geoAttrs, rsName);
812
                                        if (auxdesc != null) {
813
                                                Object sridobj = rs.getObject("SRID");
814
                                                if (sridobj == null) {
815
                                                        if (getViewProjection() != null) {
816
                                                                // ora table has no srid, use SRS of the view
817
                                                                auxdesc.setSRS(getViewProjection());
818
                                                        }
819
                                                } else {
820
                                                        srID = sridobj.toString();
821
                                                        int epsg = OracleUtils.oracleSridToEpsg(srID);
822
                                                        String sepsg = "EPSG:" + Integer.toString(epsg);
823
                                                        auxdesc.setSRS(CRSFactory.getCRS(sepsg));
824
                                                }
825
                                        }
826
                                        if (featureType.getDefaultGeometryAttribute() == null) {
827
                                                ((DefaultEditableFeatureType) featureType).setDefaultGeometryAttributeName(reserved_geocolname);
828
                                        }
829
                                        
830
                        }
831
                } catch (java.sql.SQLException e) {
832
                        throw new JDBCSQLException(e);
833
                } finally {
834
                        try { rs.close(); } catch (Exception e) { };
835
                        try { st.close(); } catch (Exception e) { };
836
                }
837
                
838
                // guess shape type
839
                String geoColName = featureType.getDefaultGeometryAttributeName();
840
                if (geoColName == null) {
841
                        geoColName = reserved_geocolname; 
842
                }
843
                
844
                try {
845
                        String str_geo = "SELECT " + geoColName + " FROM " +  
846
                        ((baseSchema != null) ? (baseSchema + "." + baseTable) : baseTable) +
847
                        " WHERE (" + geoColName + " IS NOT NULL) AND " + OracleUtils.EXPONENTIAL_INDICES_CONDITION; 
848

    
849
                        st = conn.createStatement();
850
                        try {
851
                                rs = st.executeQuery(str_geo);
852
                        } catch (SQLException e) {
853
                                throw new JDBCExecuteSQLException(str_geo, e);
854
                        }
855
                        
856
            int aux = 0;
857
            int guess_type = TYPES.GEOMETRY;
858
            int guess_subtype = SUBTYPES.GEOM2D;
859
            
860
            STRUCT sample_geo;
861
            ArrayList shptypes = new ArrayList();
862
            int[] ty_subty;
863
            while (rs.next()) {
864
                sample_geo = (STRUCT) rs.getObject(1);
865
                ty_subty = OracleUtils.getGeoTypeSubTypeOfStruct(sample_geo); 
866
                aux = ty_subty[0];
867
                guess_subtype = ty_subty[1];
868
                shptypes.add(new Integer(aux));
869
            }
870

    
871
            if (shptypes.size() > 0) {
872
                    guess_type = OracleUtils.getShapeTypeFromArray(shptypes);
873
            } else {
874
                    logger.warn("Did not find geometries to sample. Assumed TYPE = GEOMETRY, SUBTYPE = 2D");
875
            }
876

    
877
            DefaultEditableFeatureAttributeDescriptor dfad = null;
878
            try {
879
                dfad = (DefaultEditableFeatureAttributeDescriptor) featureType.getDefaultGeometryAttribute();
880
                dfad.setGeometryType(guess_type);
881
                dfad.setGeometrySubType(guess_subtype);
882
            } catch (ClassCastException cce) {
883
                    logger.error("Unexpected non editable feature type. Did not set geo types.");
884
            }
885
                } catch (java.sql.SQLException e) {
886
                        throw new JDBCSQLException(e);
887
                } finally {
888
                        try {rs.close();} catch (Exception e) {        };
889
                        try {st.close();} catch (Exception e) { };
890
                }
891
        }
892

    
893
        private EditableFeatureAttributeDescriptor getAttrDescForCol(ArrayList list, String name) {
894
                
895
                int sz = list.size();
896
                for (int i=0; i<sz; i++) {
897
                        EditableFeatureAttributeDescriptor aux = (EditableFeatureAttributeDescriptor) list.get(i);
898
                        if (aux.getName().compareToIgnoreCase(name) == 0) {
899
                                return aux;
900
                        }
901
                }
902
                // not found
903
                return null;
904
        }
905

    
906
        /**
907
         * Add oracle geometry field and add spatial index
908
         * 
909
         * @param attr
910
         * @param table
911
         * @param schema
912
         * @return
913
         */
914
        public List<String> getSqlGeometryFieldAdd(FeatureAttributeDescriptor attr,
915
                        String table, String schema) {
916

    
917
                List<String> sqls = new ArrayList<String>();
918

    
919
                StringBuilder strb1 = new StringBuilder();
920
                strb1.append("Alter table ");
921
                if (schema != null && schema.length() > 0) {
922
                        strb1.append(schema);
923
                        strb1.append(".");
924
                }
925
                strb1.append(table);
926
                strb1.append(" add (");
927
                strb1.append(attr.getName());
928
                strb1.append(" SDO_GEOMETRY)");
929

    
930
                sqls.add(strb1.toString());
931

    
932
                String sqlindex = "CREATE INDEX "
933
                                + OracleUtils.getDerivedName(table, "SX") + " ON " + table
934
                                + " (\"" + attr.getName()
935
                                + "\") INDEXTYPE IS \"MDSYS\".\"SPATIAL_INDEX\" ";
936

    
937
                sqls.add(sqlindex);
938

    
939
                return sqls;
940
        }
941
        
942
        
943
        /**
944
         * Executes an atomic action that uses an DB Connection.<br>
945
         *
946
         * This methos prepares a connection and close it at the end of execution of
947
         * action.<br>
948
         *
949
         * if <code>action</code> is an instance of {@link TransactionalAction} the
950
         * action will be execute inside of a DB transaction.
951
         *
952
         *
953
         * @param action
954
         * @throws Exception
955
         */
956
        public Object doConnectionAction(final ConnectionAction action)
957
                        throws Exception {
958
                this.open();
959
//                this.begin();
960
                return getResource().execute(new ResourceAction() {
961
                        public Object run() throws Exception {
962
                                Object result = null;
963
                                Connection conn = null;
964
                                boolean beginTrans = false;
965
                                try {
966
                                        conn = getConnection();
967
                                        if (action instanceof TransactionalAction) {
968
                                                /*
969
                                                // XXX OJO esta condicion NO ES FIABLE
970
                                                if (!conn.getAutoCommit()) {
971
                                                        if (!((TransactionalAction) action)
972
                                                                        .continueTransactionAllowed()) {
973
                                                                // FIXME exception
974
                                                                throw new Exception();
975
                                                        }
976
                                                }
977
                                                */
978
                                                try {
979
                                                        conn.setAutoCommit(false);
980
                                                } catch (SQLException e) {
981
                                                        logger.warn("Unable to set auto commit = false when starting update in Oracle layer.");
982
                                                        // throw new JDBCSQLException(e);
983
                                                }
984
                                                beginTrans = true;
985
                                        }
986

    
987
                                        result = action.action(conn);
988

    
989
                                        if (beginTrans) {
990
                                                try {
991
                                                        conn.commit();
992
                                                } catch (SQLException e) {
993
                                                        throw new JDBCTransactionCommitException(e);
994
                                                }
995
                                        }
996

    
997
                                        return result;
998

    
999
                                } catch (Exception e) {
1000

    
1001
                                        if (beginTrans) {
1002
                                                try {
1003
                                                        conn.rollback();
1004
                                                } catch (Exception e1) {
1005
                                                        throw new JDBCTransactionRollbackException(e1, e);
1006
                                                }
1007
                                        }
1008
                                        throw e;
1009

    
1010
                                /*
1011
                                } finally {
1012
                                        try {
1013
                                                conn.close();
1014
                                        } catch (Exception e1) {
1015
                                                logger.error("Exception on close connection", e1);
1016
                                        }
1017
                                */
1018
                                }
1019
                        }
1020
                });
1021
        }
1022
        
1023
        public void loadFeatureType(final EditableFeatureType featureType,
1024
                        final JDBCStoreParameters storeParams, final String sql,
1025
                        final String schema, final String table) throws DataException {
1026
                this.open();
1027
                
1028
                if (storeParams.getCRS() != null) {
1029
                        this.setViewProjection(storeParams.getCRS());
1030
                }
1031
//                this.begin();
1032
                getResource().execute(new ResourceAction() {
1033
                        public Object run() throws Exception {
1034
                                Connection conn = null;
1035
                                // try {
1036
                                        conn = getConnection();
1037
                                        
1038
                                        String[] pks = storeParams.getPkFields();
1039
                                        if (pks == null || pks.length < 1) {
1040
                                                if (storeParams.getTable() != null
1041
                                                                && storeParams.getTable().trim().length() > 0) {
1042
                                                        pks = getPksFrom(conn, storeParams);
1043
                                                        
1044
                                                }
1045
                                        }
1046
                                        
1047
                                        loadFeatureType(conn, featureType, sql, pks, storeParams
1048
                                                        .getDefaultGeometryField(), schema, table);                                        
1049
                                        
1050
                                /*
1051
                                } finally {
1052
                                        try {
1053
                                                conn.close();
1054
                                        } catch (Exception e) {
1055
                                        }
1056
                                */
1057
                                // }
1058
                                return null;
1059
                        }
1060
                });
1061
        }
1062

    
1063
        public String getOraTableSrid(OracleStoreParameters params,
1064
                        String geo_field) {
1065
                
1066
                StringBuilder strb = new StringBuilder();
1067
                strb.append("SELECT SRID FROM "
1068
                                + OracleValues.ALL_ORACLE_GEOMETADATA_VIEW);
1069
                strb.append(" WHERE "
1070
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_TABLE_NAME
1071
                                + " = '" + params.getTable() + "'");
1072
                strb.append(" AND "
1073
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_COLUMN_NAME
1074
                                + " = '" + geo_field + "'");
1075
                strb.append(" AND "
1076
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_OWNER
1077
                                + " = '" + params.getSchema() + "'");
1078
                String sql = strb.toString();
1079

    
1080
                ResultSet rs = null;
1081
                Statement st = null;
1082
                Connection conn = null;
1083
                String srid_str = "";
1084

    
1085
                try {
1086
                        this.open();
1087
                        
1088
                        conn = getConnection();
1089
                        st = conn.createStatement();
1090
                        try {
1091
                                rs = st.executeQuery(sql);
1092
                        } catch (java.sql.SQLException e) {
1093
                                throw new JDBCExecuteSQLException(sql, e);
1094
                        }
1095
                        if (!rs.next()) {
1096
                                return null;
1097
                        }
1098

    
1099
                        Object srid_obj = rs.getObject(1);
1100
                        if (srid_obj == null) {
1101
                                srid_str = null;
1102
                        } else {
1103
                                if (srid_obj instanceof Integer) {
1104
                                        srid_str = ((Integer) srid_obj).toString();
1105
                                } else {
1106
                                        srid_str = srid_obj.toString();
1107
                                }
1108
                        }
1109

    
1110
                } catch (Exception e) {
1111
                        logger.error("While getting SRID from Oracle view: " + e.getMessage());
1112
                        return null;
1113
                } finally {
1114
                        try {
1115
                                rs.close();
1116
                        } catch (Exception e) {
1117
                        }
1118

    
1119
                        try {
1120
                                st.close();
1121
                        } catch (Exception e) {
1122
                        }
1123

    
1124
                        rs = null;
1125
                        st = null;
1126
                        conn = null;
1127
                }
1128
                
1129
                return srid_str;
1130
                
1131
                
1132
        }
1133
        
1134
        
1135
        public IProjection getViewProjection() {
1136
                return viewProjection;
1137
        }
1138

    
1139
        public void setViewProjection(IProjection p) {
1140
                this.viewProjection = p;
1141
        }
1142
        
1143
        
1144
//        protected void loadFeatureType(Connection conn,
1145
//                        EditableFeatureType featureType, String sql, String[] pks,
1146
//                        String defGeomName, String schema, String table)
1147
//                        throws DataException {
1148
//
1149
//                Statement stAux = null;
1150
//                ResultSet rs = null;
1151
//                try {
1152
//
1153
//                        stAux = conn.createStatement();
1154
//                        stAux.setFetchSize(1);
1155
//
1156
//                        try {
1157
//                                rs = stAux.executeQuery(sql);
1158
//                        } catch (SQLException e) {
1159
//                                throw new JDBCExecuteSQLException(sql, e);
1160
//                        }
1161
//                        ResultSetMetaData rsMetadata = rs.getMetaData();
1162
//
1163
//                        List pksList = null;
1164
//                        if (pks != null) {
1165
//                                pksList = Arrays.asList(pks);
1166
//                        }
1167
//
1168
//                        int i;
1169
//                        int geometriesColumns = 0;
1170
//                        String lastGeometry = null;
1171
//
1172
//                        EditableFeatureAttributeDescriptor attr;
1173
//                        for (i = 1; i <= rsMetadata.getColumnCount(); i++) {
1174
//                                attr = getAttributeFromJDBC(featureType, conn, rsMetadata, i);
1175
//                                if (pksList != null && pksList.contains(attr.getName())) {
1176
//                                        attr.setIsPrimaryKey(true);
1177
//                                }
1178
//                                if (attr.getDataType() == DataTypes.GEOMETRY) {
1179
//                                        geometriesColumns++;
1180
//                                        lastGeometry = attr.getName();
1181
//                                        if (lastGeometry.equals(defGeomName)) {
1182
//                                                featureType.setDefaultGeometryAttributeName(defGeomName);
1183
//                                        }
1184
//                                }
1185
//                        }
1186
//
1187
//                        if (geometriesColumns > 0) {
1188
//                                loadSRS_and_shapeType(conn, rsMetadata, featureType, schema,
1189
//                                                table);
1190
//                        }
1191
//
1192
//                        if (defGeomName == null && geometriesColumns == 1) {
1193
//                                featureType.setDefaultGeometryAttributeName(lastGeometry);
1194
//                                defGeomName = lastGeometry;
1195
//                        }
1196
//
1197
//                } catch (java.sql.SQLException e) {
1198
//                        throw new JDBCSQLException(e); // FIXME exception
1199
//                } finally {
1200
//                        try {
1201
//                                rs.close();
1202
//                        } catch (Exception e) {
1203
//                        }
1204
//                        try {
1205
//                                stAux.close();
1206
//                        } catch (Exception e) {
1207
//                        }
1208
//
1209
//                }
1210
//
1211
//        }
1212

    
1213

    
1214
}