Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / org.gvsig.oracle / src / org / gvsig / fmap / dal / store / oracle / OracleHelper.java @ 38076

History | View | Annotate | Download (32.3 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
                StringBuilder strb = new StringBuilder();
201
                strb.append("SELECT * FROM "
202
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW);
203
                strb.append(" WHERE "
204
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_TABLE_NAME
205
                                + " = '" + storeParams.getTable() + "'");
206
                strb.append(" AND "
207
                                + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_COLUMN_NAME
208
                                + " = '" + geometryAttrName + "'");
209
                String sql = strb.toString();
210

    
211
                ResultSet rs = null;
212
                Statement st = null;
213
                String schema = null;
214
                Connection conn = null;
215

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

    
230
                        // DIMINFO (ARRAY)
231
                        ARRAY dim_info_array = (ARRAY) rs.getObject("DIMINFO");
232

    
233
                        Datum[] da = dim_info_array.getOracleArray();
234
                        int dim = da.length;
235

    
236
                        STRUCT sx = (STRUCT) da[0];
237
                        STRUCT sy = (STRUCT) da[1];
238
                        double minx = Double.parseDouble(sx.getAttributes()[1].toString());
239
                        double maxx = Double.parseDouble(sx.getAttributes()[2].toString());
240
                        double miny = Double.parseDouble(sy.getAttributes()[1].toString());
241
                        double maxy = Double.parseDouble(sy.getAttributes()[2].toString());
242
                        if (minx > maxx) {
243
                                double aux = minx;
244
                                minx = maxx;
245
                                maxx = aux;
246
                        }
247

    
248
                        if (miny > maxy) {
249
                                double aux = miny;
250
                                miny = maxy;
251
                                maxy = aux;
252
                        }
253

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

    
265
                                Point minPto = new Point2DZ(minx, miny, minz);
266
                                Point maxPto = new Point2DZ(maxx, maxy, maxz);
267

    
268
                                fullEnvelope = new Envelope3D(minPto, maxPto);
269
                        }
270

    
271
                        return fullEnvelope;
272

    
273
                } catch (Exception e) {
274
                        return null;
275
                }
276

    
277
                finally {
278
                        try {
279
                                rs.close();
280
                        } catch (Exception e) {
281
                        }
282

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

    
288
                        /*
289
                        try {
290
                                conn.close();
291
                        } catch (Exception e) {
292
                        }
293
                        */
294

    
295
                        finally {
296
                                rs = null;
297
                                st = null;
298
                                conn = null;
299
                        }
300
                }
301
        }
302

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

    
316
        /**
317
         * 
318
         */
319
        public Geometry getGeometry(byte[] buffer) throws BaseException {
320
                // TODO BLOB format in Oracle?
321
                logger.error("Unsupported: binary Geometry format");
322
                return null;
323
        }
324

    
325
        /**
326
         * get geometry column name "SDO_GEOMETRY"
327
         * 
328
         * @param attr
329
         * @return
330
         */
331
        public String getSqlColumnTypeDescription(FeatureAttributeDescriptor attr) {
332

    
333
                switch (attr.getDataType().getType()) {
334

    
335
                case DataTypes.GEOMETRY:
336
                        return "\"MDSYS\".\"SDO_GEOMETRY\"";
337

    
338
                case DataTypes.STRING:
339
                        return "NVARCHAR2(" + attr.getSize() + ")";
340

    
341
                case DataTypes.BOOLEAN:
342
                        return "NUMBER(1, 0)";
343

    
344
                case DataTypes.BYTE:
345
                        return "NUMBER";
346

    
347
                case DataTypes.DATE:
348
                        return "DATE";
349

    
350
                case DataTypes.TIMESTAMP:
351
                        return "TIMESTAMP";
352

    
353
                case DataTypes.TIME:
354
                        return "TIMESTAMP";
355

    
356
                case DataTypes.BYTEARRAY:
357

    
358
                case DataTypes.DOUBLE:
359
                        return "FLOAT";
360

    
361
                case DataTypes.FLOAT:
362
                        return "FLOAT";
363

    
364
                case DataTypes.INT:
365
                        return "NUMBER(12, 0)";
366

    
367
                case DataTypes.LONG:
368
                        return "NUMBER(38, 0)";
369

    
370
                default:
371
                        String typeName = (String) attr.getAdditionalInfo("SQLTypeName");
372
                        if (typeName != null) {
373
                                return typeName;
374
                        }
375
                        throw new UnsupportedDataTypeException(attr.getDataTypeName(), attr
376
                                        .getDataType().getType());
377
                }
378

    
379
        }
380

    
381
        /**
382
         * Get oracle geometry dimension
383
         * 
384
         * @param geometrySubType
385
         * @return
386
         */
387
        public int getOraGeomDimensions(int geometrySubType) {
388

    
389
                switch (geometrySubType) {
390
                case Geometry.SUBTYPES.GEOM2D:
391
                        return 2;
392
                case Geometry.SUBTYPES.GEOM2DM:
393
                case Geometry.SUBTYPES.GEOM3D:
394
                        return 3;
395
                case Geometry.SUBTYPES.GEOM3DM:
396
                        return 4;
397
                default:
398
                        throw new UnsupportedDataTypeException(
399
                                        "GEOMETRY field",
400
                                        DataTypes.GEOMETRY);
401
                }
402
        }
403

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

    
471
        /**
472
         * 
473
         */
474
        public String getSqlFieldName(FeatureAttributeDescriptor attribute) {
475
                /*
476
                if (attribute.getDataType() == DataTypes.GEOMETRY) {
477
                        return "asBinary(" + super.getSqlFieldName(attribute) + ")";
478
                }
479
                */
480
                return super.getSqlFieldName(attribute);
481
        }
482
        
483
        protected String getIdentifierQuoteString() {
484
                return IDENTIFIER_QUOTE_STRING;
485
        }
486

    
487
        /**
488
         * 
489
         */
490
        protected EditableFeatureAttributeDescriptor createAttributeFromJDBC(
491
                        EditableFeatureType fType, Connection conn,
492
                        ResultSetMetaData rsMetadata, int colIndex) throws SQLException {
493
                
494
                String rstypename = rsMetadata.getColumnTypeName(colIndex);
495
                if (rstypename
496
                                .equalsIgnoreCase(OracleValues.OraGeometry_GTYPE_GEOMETRY)) {
497

    
498
                        return fType.add(rsMetadata.getColumnName(colIndex),
499
                                        DataTypes.GEOMETRY);
500
                }
501

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

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

    
577
                default:
578
                        column = fType.add(rsMetadata.getColumnName(colIndex),
579
                                        DataTypes.OBJECT);
580
                        column.setAdditionalInfo("SQLType", new Integer(rsMetadata
581
                                        .getColumnType(colIndex)));
582
                        column.setAdditionalInfo("SQLTypeName", rsMetadata
583
                                        .getColumnTypeName(colIndex));
584

    
585
                        break;
586
                }
587

    
588
                return column;
589

    
590

    
591
                // return super.createAttributeFromJDBC(type, conn, rsMetadata, colIndex);
592
        }
593

    
594
        /**
595
         * 
596
         */
597
        public boolean allowAutomaticValues() {
598
                return Boolean.TRUE;
599
        }
600

    
601
        /**
602
         * 
603
         */
604
        public boolean supportOffset() {
605
                return true;
606
        }
607

    
608
        /**
609
         * 
610
         */
611
        public boolean supportsUnion() {
612
                return true;
613
        }
614

    
615
        /**
616
         * get sql with fields description
617
         * 
618
         * @param attr
619
         * @return
620
         */
621
        public String getSqlFieldDescription(FeatureAttributeDescriptor attr)
622
                        throws DataException {
623

    
624
                StringBuilder strb = new StringBuilder();
625
                // name
626
                strb.append("\"" + attr.getName() + "\" ");
627

    
628
                // Type
629
                strb.append(this.getSqlColumnTypeDescription(attr));
630

    
631
                // Primary key
632
                if (attr.isPrimaryKey()) {
633
                        strb.append(" PRIMARY KEY");
634
                }
635

    
636
                return strb.toString();
637
        }
638

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

    
658
                String[] dim_name = new String[dim];
659
                // double tolerance = ORACLE_SPATIAL_DEFAULT_TOLERANCE;
660

    
661
                String _ora_srid = ora_srid;
662
                if (_ora_srid == null)
663
                        _ora_srid = "NULL";
664

    
665
                if (_ora_srid.compareTo(OracleValues.GEODETIC_SRID) == 0) {
666
                        dim_name[0] = "LONGITUDE";
667
                        dim_name[1] = "LATITUDE";
668
                } else {
669
                        dim_name[0] = "X";
670
                        dim_name[1] = "Y";
671

    
672
                        if (dim > 2) {
673
                                dim_name[2] = "Z";
674

    
675
                                if (dim > 3) {
676
                                        dim_name[3] = "T";
677
                                }
678
                        }
679
                }
680

    
681
                double minx = bbox.getMinX();
682
                double miny = bbox.getMinY();
683
                double maxx = bbox.getMaxX();
684
                double maxy = bbox.getMaxY();
685

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

    
696
                if (dim > 2) {
697
                        resp = resp.substring(0, resp.length() - 1) + ",";
698
                        resp = resp + "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[2]
699
                                        + "', 0.0, 100.0, " + ORACLE_SPATIAL_DEFAULT_TOLERANCE + " ))";
700

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

    
708
                if (withsrid) {
709
                        resp = resp + ", " + _ora_srid + " )";
710
                } else {
711
                        resp = resp + ", NULL )";
712
                }
713

    
714
                return resp;
715
        }
716

    
717

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

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

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

    
761
                Statement st = null;
762
                ResultSet rs = null;
763
                String reserved_geocolname = null;
764
                
765
                try {
766
                        // Sacamos la lista de los attributos geometricos
767

    
768
                        EditableFeatureAttributeDescriptor attr;
769
                        ArrayList geoAttrs = new ArrayList();
770

    
771
                        Iterator iter = featureType.iterator();
772
                        while (iter.hasNext()) {
773
                                attr = (EditableFeatureAttributeDescriptor) iter.next();
774
                                if (attr.getDataType().getType() == DataTypes.GEOMETRY) {
775
                                        geoAttrs.add(attr);
776
                                }
777
                        }
778
                        if (geoAttrs.size() < 1) {
779
                                return;
780
                        }
781

    
782
                        // Preparamos una sql para que nos saque el resultado
783
                        StringBuilder strb = new StringBuilder();
784
                        strb.append("SELECT * FROM "
785
                                        + OracleValues.USER_ORACLE_GEOMETADATA_VIEW + " WHERE "
786
                                        + OracleValues.USER_ORACLE_GEOMETADATA_VIEW_TABLE_NAME
787
                                        + " = '" + baseTable + "'");
788
                        String sql = strb.toString();
789

    
790
                        st = conn.createStatement();
791
                        try {
792
                                rs = st.executeQuery(sql);
793
                        } catch (SQLException e) {
794
                                throw new JDBCExecuteSQLException(sql, e);
795
                        }
796
                        
797
                        String srID;
798

    
799
                        EditableFeatureAttributeDescriptor auxdesc;
800
                        
801

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

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

    
866
            if (shptypes.size() > 0) {
867
                    guess_type = OracleUtils.getShapeTypeFromArray(shptypes);
868
            } else {
869
                    logger.warn("Did not find geometries to sample. Assumed TYPE = GEOMETRY, SUBTYPE = 2D");
870
            }
871

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

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

    
901
        /**
902
         * Add oracle geometry field and add spatial index
903
         * 
904
         * @param attr
905
         * @param table
906
         * @param schema
907
         * @return
908
         */
909
        public List<String> getSqlGeometryFieldAdd(FeatureAttributeDescriptor attr,
910
                        String table, String schema) {
911

    
912
                List<String> sqls = new ArrayList<String>();
913

    
914
                StringBuilder strb1 = new StringBuilder();
915
                strb1.append("Alter table ");
916
                if (schema != null && schema.length() > 0) {
917
                        strb1.append(schema);
918
                        strb1.append(".");
919
                }
920
                strb1.append(table);
921
                strb1.append(" add (");
922
                strb1.append(attr.getName());
923
                strb1.append(" SDO_GEOMETRY)");
924

    
925
                sqls.add(strb1.toString());
926

    
927
                String sqlindex = "CREATE INDEX "
928
                                + OracleUtils.getDerivedName(table, "SX") + " ON " + table
929
                                + " (\"" + attr.getName()
930
                                + "\") INDEXTYPE IS \"MDSYS\".\"SPATIAL_INDEX\" ";
931

    
932
                sqls.add(sqlindex);
933

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

    
982
                                        result = action.action(conn);
983

    
984
                                        if (beginTrans) {
985
                                                try {
986
                                                        conn.commit();
987
                                                } catch (SQLException e) {
988
                                                        throw new JDBCTransactionCommitException(e);
989
                                                }
990
                                        }
991

    
992
                                        return result;
993

    
994
                                } catch (Exception e) {
995

    
996
                                        if (beginTrans) {
997
                                                try {
998
                                                        conn.rollback();
999
                                                } catch (Exception e1) {
1000
                                                        throw new JDBCTransactionRollbackException(e1, e);
1001
                                                }
1002
                                        }
1003
                                        throw e;
1004

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

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

    
1075
                ResultSet rs = null;
1076
                Statement st = null;
1077
                Connection conn = null;
1078
                String srid_str = "";
1079

    
1080
                try {
1081
                        this.open();
1082
                        
1083
                        conn = getConnection();
1084
                        st = conn.createStatement();
1085
                        try {
1086
                                rs = st.executeQuery(sql);
1087
                        } catch (java.sql.SQLException e) {
1088
                                throw new JDBCExecuteSQLException(sql, e);
1089
                        }
1090
                        if (!rs.next()) {
1091
                                return null;
1092
                        }
1093

    
1094
                        Object srid_obj = rs.getObject(1);
1095
                        if (srid_obj == null) {
1096
                                srid_str = null;
1097
                        } else {
1098
                                if (srid_obj instanceof Integer) {
1099
                                        srid_str = ((Integer) srid_obj).toString();
1100
                                } else {
1101
                                        srid_str = srid_obj.toString();
1102
                                }
1103
                        }
1104

    
1105
                } catch (Exception e) {
1106
                        logger.error("While getting SRID from Oracle view: " + e.getMessage());
1107
                        return null;
1108
                } finally {
1109
                        try {
1110
                                rs.close();
1111
                        } catch (Exception e) {
1112
                        }
1113

    
1114
                        try {
1115
                                st.close();
1116
                        } catch (Exception e) {
1117
                        }
1118

    
1119
                        rs = null;
1120
                        st = null;
1121
                        conn = null;
1122
                }
1123
                
1124
                return srid_str;
1125
                
1126
                
1127
        }
1128
        
1129
        
1130
        public IProjection getViewProjection() {
1131
                return viewProjection;
1132
        }
1133

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

    
1208

    
1209
}