Statistics
| Revision:

root / branches / v10 / extensions / extOracleSpatial / src / es / prodevelop / cit / gvsig / fmap / drivers / jdbc / oracle / OracleSpatialDriver.java @ 13995

History | View | Annotate | Download (128 KB)

1 13991 jldominguez@prodevelop.es
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
 *
3
 * Copyright (C) 2006 Prodevelop and Generalitat Valenciana.
4
 *
5
 * This program is free software; you can redistribute it and/or
6
 * modify it under the terms of the GNU General Public License
7
 * as published by the Free Software Foundation; either version 2
8
 * of the License, or (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
 *
19
 * For more information, contact:
20
 *
21
 *   Generalitat Valenciana
22
 *   Conselleria d'Infraestructures i Transport
23
 *   Av. Blasco Ib??ez, 50
24
 *   46010 VALENCIA
25
 *   SPAIN
26
 *
27
 *   +34 963862235
28
 *   gvsig@gva.es
29
 *   www.gvsig.gva.es
30
 *
31
 *    or
32
 *
33
 *   Prodevelop Integraci?n de Tecnolog?as SL
34
 *   Conde Salvatierra de ?lava , 34-10
35
 *   46004 Valencia
36
 *   Spain
37
 *
38
 *   +34 963 510 612
39
 *   +34 963 510 968
40
 *   gis@prodevelop.es
41
 *   http://www.prodevelop.es
42
 */
43
package es.prodevelop.cit.gvsig.fmap.drivers.jdbc.oracle;
44
45
import com.hardcode.driverManager.IDelayedDriver;
46
47
import com.hardcode.gdbms.engine.data.DataSource;
48
import com.hardcode.gdbms.engine.data.DataSourceFactory;
49
import com.hardcode.gdbms.engine.data.SourceInfo;
50
import com.hardcode.gdbms.engine.data.edition.DataWare;
51
import com.hardcode.gdbms.engine.data.file.FileSourceInfo;
52
import com.hardcode.gdbms.engine.spatial.fmap.FShapeGeneralPathX;
53
import com.hardcode.gdbms.engine.values.DoubleValue;
54
import com.hardcode.gdbms.engine.values.Value;
55
import com.hardcode.gdbms.engine.values.ValueFactory;
56
57
import com.iver.cit.gvsig.fmap.DriverException;
58
import com.iver.cit.gvsig.fmap.core.DefaultFeature;
59
import com.iver.cit.gvsig.fmap.core.FGeometryCollection;
60
import com.iver.cit.gvsig.fmap.core.FMultiPoint2D;
61
import com.iver.cit.gvsig.fmap.core.FNullGeometry;
62
import com.iver.cit.gvsig.fmap.core.FPoint2D;
63
import com.iver.cit.gvsig.fmap.core.FPolygon2D;
64
import com.iver.cit.gvsig.fmap.core.FPolyline2D;
65
import com.iver.cit.gvsig.fmap.core.FShape;
66
import com.iver.cit.gvsig.fmap.core.GeneralPathX;
67
import com.iver.cit.gvsig.fmap.core.ICanReproject;
68
import com.iver.cit.gvsig.fmap.core.IFeature;
69
import com.iver.cit.gvsig.fmap.core.IGeometry;
70
import com.iver.cit.gvsig.fmap.core.ShapeFactory;
71
import com.iver.cit.gvsig.fmap.core.v02.FConverter;
72
import com.iver.cit.gvsig.fmap.crs.CRSFactory;
73
import com.iver.cit.gvsig.fmap.drivers.DBLayerDefinition;
74
import com.iver.cit.gvsig.fmap.drivers.DefaultDBDriver;
75
import com.iver.cit.gvsig.fmap.drivers.DriverAttributes;
76
import com.iver.cit.gvsig.fmap.drivers.FieldDescription;
77
import com.iver.cit.gvsig.fmap.drivers.IFeatureIterator;
78
import com.iver.cit.gvsig.fmap.drivers.dbf.DBFDriver;
79
import com.iver.cit.gvsig.fmap.edition.EditableAdapter;
80
import com.iver.cit.gvsig.fmap.edition.EditionException;
81
import com.iver.cit.gvsig.fmap.edition.IWriteable;
82
import com.iver.cit.gvsig.fmap.edition.IWriter;
83
import com.iver.cit.gvsig.fmap.layers.LayerFactory;
84
import com.iver.cit.gvsig.fmap.layers.SelectableDataSource;
85
import com.iver.cit.gvsig.project.documents.table.ProjectTable;
86
import com.iver.cit.gvsig.project.documents.table.ProjectTableFactory;
87
import com.iver.utiles.NumberUtilities;
88
89
import com.vividsolutions.jts.algorithm.CGAlgorithms;
90
import com.vividsolutions.jts.geom.Coordinate;
91
import com.vividsolutions.jts.geom.Geometry;
92
import com.vividsolutions.jts.geom.GeometryFactory;
93
import com.vividsolutions.jts.geom.LineString;
94
import com.vividsolutions.jts.geom.LinearRing;
95
import com.vividsolutions.jts.geom.MultiPolygon;
96
import com.vividsolutions.jts.geom.Polygon;
97
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
98
99
import oracle.jdbc.OracleConnection;
100
101
import oracle.spatial.geometry.JGeometry;
102
103
import oracle.sql.ARRAY;
104
import oracle.sql.Datum;
105
import oracle.sql.NUMBER;
106
import oracle.sql.ROWID;
107
import oracle.sql.STRUCT;
108
import oracle.sql.StructDescriptor;
109
110
import org.apache.log4j.Logger;
111
import org.cresques.cts.ICoordTrans;
112
import org.cresques.cts.IProjection;
113
114
//import org.geotools.data.oracle.sdo.GeometryConverter;
115
116
import java.awt.Shape;
117
import java.awt.geom.Point2D;
118
import java.awt.geom.Rectangle2D;
119
120
import java.io.File;
121
import java.io.IOException;
122 13995 jldominguez@prodevelop.es
import java.math.BigDecimal;
123 13991 jldominguez@prodevelop.es
124
import java.sql.Connection;
125
import java.sql.DatabaseMetaData;
126
import java.sql.PreparedStatement;
127
import java.sql.ResultSet;
128
import java.sql.ResultSetMetaData;
129
import java.sql.SQLException;
130
import java.sql.Statement;
131
import java.sql.Types;
132
133
import java.text.ParseException;
134
135
import java.util.ArrayList;
136
import java.util.HashMap;
137
import java.util.Hashtable;
138
import java.util.Iterator;
139
import java.util.Random;
140
import java.util.TreeMap;
141
142
143
/**
144
 * Vectorial driver to access Oracle databases geometries.
145
 * Should work on Oracle Locator.
146
 *
147
 * It contains switches to test different modules to perform the
148
 * translation oracle structs --> gvsig geometries:
149
 *
150
 * - Parsing the structs directly.
151
 * - Using Oracle's JGeometry static methods
152
 * - Using Geotools utilities
153
 *
154
 *  (currently, the driver parses the structs directly)
155
 *
156
 * @author jldominguez
157
 *
158
 */
159
public class OracleSpatialDriver extends DefaultDBDriver
160
    implements IDelayedDriver, ICanReproject, IWriteable {
161
    private static Logger logger = Logger.getLogger(OracleSpatialDriver.class.getName());
162
    private static int FETCH_SIZE = 15000;
163
164
    // constants
165
    public static final int GEODETIC_FULLEXTENT_SAMPLE_SIZE = 50;
166
    public static final String GEODETIC_SRID = "8307";
167
    public static final String ASSUMED_ORACLE_SRID = "8307";
168
169
    // ------------------------------------------------
170
    public static final String NAME = "Oracle Spatial Database Driver";
171
    public static final int ID_COLUMN_INDEX = 1;
172 13993 fran.penarrubia@iver.es
    public static final String ORACLE_GEOMETADATA_VIEW = "ALL_SDO_GEOM_METADATA";
173 13991 jldominguez@prodevelop.es
    public static final String ORACLE_EPSG_TABLE_NAME = "ORA_EPSG";
174
    public static final String ORACLE_EPSG_FILE_NAME = "ora_epsg.dbf";
175
    public static final String DEFAULT_GEO_FIELD = "GEOMETRY";
176
    public static final String ORACLE_ID_FIELD = "ROWID";
177
    public static final String DEFAULT_ID_FIELD = "GID";
178
    public static final String ORACLE_GEO_SCHEMA = "MDSYS";
179
    public static final String CONN_STR_BEGIN = "jdbc:oracle:thin:";
180
    public static final int VARCHAR2_STANDARD_SIZE = 80;
181
    public static final int VARCHAR2_LONG_SIZE = 256;
182
    public static final int MAX_ID_LENGTH = 30;
183
    private final static GeometryFactory geomFactory = new GeometryFactory();
184
    public static final double IRRELEVANT_DISTANCE = 0.00000001;
185
        private static final String EXTENSION_DIR_NAME = "com.iver.cit.gvsig.jdbc_spatial";
186
187
    static {
188
        try {
189
            Class.forName("oracle.jdbc.driver.OracleDriver");
190
        }
191
        catch (ClassNotFoundException e) {
192
            throw new RuntimeException(e);
193
        }
194
        createOracleEpsgTable();
195
    }
196
197
    private OracleSpatialWriter writer = null;
198
199
    // utility object to convert geometries.
200
//    private GeometryConverter geotools_conv;
201
202
    // switch variable
203
    private boolean use_geotools = false;
204
    private boolean tableHasSrid = true;
205
206
    // ------------------------------------------------
207
    private boolean isNotAvailableYet = true;
208
    private IGeometry nullGeom = new FNullGeometry();
209
    private Value nullVal = ValueFactory.createNullValue();
210
    private IdLoaderThread idLoader;
211
    private DriverAttributes drvAtts;
212
    private int[] pkOneBasedIndexes;
213
    private String[] fieldNames;
214
    private String not_restricted_sql = "";
215
216
    private Rectangle2D workingAreaInViewsCS = null;
217
    private Rectangle2D workingAreaInTablesCS = null;
218
    private STRUCT workingAreaInTablesCSStruct = null;
219
220
    private String idFieldNames;
221
    private int oneBasedGeoColInd = 0;
222
    private int shapeType = -1;
223
    private boolean needsCollectionLayer = true;
224
225
    // ----------------------------------------------
226
    // one feature is cached to avoid querying for each attribute request:
227
    private IFeature singleCachedFeature = null;
228
    private long singleCachedFeatureRowNum = -1;
229
230
    // ----------------------------------------------
231
    private boolean cancelIDLoad = false;
232
233
    // ----------------------------------------------
234
    private String geoColName = "";
235
    private String oracleSRID;
236
    private String epsgSRID;
237
    private String destProj = "";
238
    private Rectangle2D full_Extent = null;
239
    private boolean emptyWhereClause = true;
240
    private boolean isGeogCS = false;
241
    private boolean hasRealiableExtent = true;
242
243
    // new hash map to perform queries by row number:
244
    private HashMap rowToId = new HashMap();
245
    private String standardSelectExpressionFalse = null;
246
        private String destProjOracle;
247
        private boolean isDestGeogCS = false;
248
249
    public OracleSpatialDriver() {
250
        drvAtts = new DriverAttributes();
251
        drvAtts.setLoadedInMemory(false);
252
    }
253
254
    /**
255
     * This method is called when the user creates a new oracle
256
     * table from a vectorial layer
257
     *
258
     * @param params this array simply contains the parameters <tt>Connection</tt> and
259
     * <tt>DBLayerDefinition</tt>
260
     */
261
    public void setData(Object[] params) {
262
        createOracleEpsgTable();
263
        setData((Connection) params[0], (DBLayerDefinition) params[1]);
264
    }
265
266
    private void adjustLyrDef() throws SQLException {
267
        DBLayerDefinition ldef = getLyrDef();
268
        int cnt = metaData.getColumnCount();
269
270
        FieldDescription[] _new = new FieldDescription[cnt];
271
272
        for (int i = 0; i < cnt; i++) {
273
            _new[i] = new FieldDescription();
274
            _new[i].setFieldName(metaData.getColumnName(i + 1));
275
            _new[i].setDefaultValue(ValueFactory.createNullValue());
276
            _new[i].setFieldAlias(_new[i].getFieldName());
277
            _new[i].setFieldLength(getFieldWidth(i));
278
279
            int _type = metaData.getColumnType(i + 1);
280
            _new[i].setFieldType(_type);
281
282
            if ((_type == Types.FLOAT) || (_type == Types.DOUBLE) ||
283
                    (_type == Types.DECIMAL) || (_type == Types.REAL)) {
284
                _new[i].setFieldDecimalCount(6);
285
            }
286
            else {
287
                _new[i].setFieldDecimalCount(0);
288
            }
289
        }
290
291
        ldef.setFieldsDesc(_new);
292
        setLyrDef(ldef);
293
    }
294
295
    /**
296
     * Standard initializing method.
297
     */
298
    public void setData(Connection _conn, DBLayerDefinition lyrDef) {
299
        createOracleEpsgTable();
300
301
        conn = _conn;
302
303
//        geotools_conv = new GeometryConverter((OracleConnection) conn);
304
        lyrDef.setConnection(conn);
305
306
        setLyrDef(lyrDef);
307
308
        geoColName = lyrDef.getFieldGeometry();
309
        not_restricted_sql = "select " + getStandardSelectExpression() +
310
            " from " + getTableName() + " c ";
311
312
        // various metadata settings
313
        // getMetaDataInThisThread();
314
        cleanWhereClause();
315
        loadSdoMetadata();
316
        oneRowMetadata();
317
318 13992 jldominguez@prodevelop.es
        setDestProjection(lyrDef.getSRID_EPSG());
319
320 13991 jldominguez@prodevelop.es
        IProjection viewProj = CRSFactory.getCRS("EPSG:" + destProj);
321
        IProjection tableProj = CRSFactory.getCRS("EPSG:" + epsgSRID);
322
        ICoordTrans reprojecter = viewProj.getCT(tableProj);
323
324
        workingAreaInViewsCS = lyrDef.getWorkingArea();
325
        if (workingAreaInViewsCS != null) {
326
                workingAreaInTablesCS = reprojecter.convert(workingAreaInViewsCS);
327
        }
328
        workingAreaInTablesCSStruct = shapeToStruct(workingAreaInTablesCS,
329
                FShape.NULL, tableHasSrid, false, true);
330
331
        cancelIDLoad = false;
332
        idLoader = new IdLoaderThread(this);
333
        idLoader.start();
334
    }
335
336
        /**
337
     * Utility method to load IDs in a different thred, so that gvsig's gui
338
     * does not get blocked.
339
     *
340
     */
341
    public void getMetaDataInThisThread() {
342
        getMetadata();
343
    }
344
345
    private void getMetadata() {
346
        setIdRowTable();
347
348
        if (!hasRealiableExtent) {
349
                full_Extent = getEstimatedGeodeticExtent(
350
                                getTableName(), geoColName, conn, 20, 1.5);
351
        }
352
353
354
        if (cancelIDLoad) {
355
            return;
356
        }
357
    }
358
359
    private boolean needsCollectionLayer() {
360
        try {
361
            // SELECT DISTINCT(C.GEOM.SDO_GTYPE) FROM COMUICV C
362
            // String qry = "select distinct(c."  + geoColName + ".SDO_GTYPE) from " + getTableName() + " c";
363
            String qry = "select c." + geoColName + ".SDO_ELEM_INFO from " +
364
                getTableName() + " c";
365
366
            // SDO_ELEM_INFO
367
            Statement _st = conn.createStatement();
368
            ResultSet _rs = _st.executeQuery(qry);
369
370
            ArrayList types = new ArrayList();
371
            int aux = 0;
372
373
            ARRAY info_aux;
374
            int[] info_aux_int;
375
            int size;
376
377
            while (_rs.next()) {
378
                // aux = _rs.getInt(1);
379
                info_aux = (ARRAY) _rs.getObject(1);
380
                info_aux_int = info_aux.getIntArray();
381
                size = info_aux_int.length / 3;
382
383
                for (int i = 0; i < size; i++) {
384
                    aux = info_aux_int[(3 * i) + 1];
385
                }
386
387
                types.add(new Integer(aux % 1000));
388
389
                if ((aux % 1000) != 3) {
390
                    System.err.println("x");
391
                }
392
            }
393
394
            _rs.close();
395
            _st.close();
396
397
            boolean resp = hasSeveralGeometryTypes(types, false);
398
399
            return resp;
400
        }
401
        catch (Exception se) {
402
            System.err.println("Error while getting SDO metadata: " +
403
                se.getMessage());
404
        }
405
406
        return false;
407
    }
408
409
    private boolean hasSeveralGeometryTypes(ArrayList tt, boolean are_dims) {
410
        if (tt.size() == 0) {
411
            return false;
412
        }
413
414
        HashMap m = new HashMap();
415
416
        for (int i = 0; i < tt.size(); i++) {
417
            Integer integ = (Integer) tt.get(i);
418
            int val = integ.intValue();
419
420
            if ((val == 4) && (!are_dims)) {
421
                return true;
422
            }
423
424
            m.put("" + (val % 4), "a type");
425
        }
426
427
        Iterator iter = m.keySet().iterator();
428
        iter.next();
429
430
        return iter.hasNext();
431
    }
432
433
    private String getOracleSridFromCurrentRecord(ResultSet _rs)
434
        throws SQLException {
435
        Object obj = _rs.getObject("SRID");
436
437
        if (obj == null) {
438
            logger.warn("No SRID found for this table.");
439
            tableHasSrid = false;
440
441
            return ASSUMED_ORACLE_SRID;
442
        }
443
444
        return obj.toString();
445
    }
446
447
    private Rectangle2D getFullExtentFromCurrentRecord(ResultSet _rs)
448
        throws SQLException {
449
        ARRAY dim_info_array = (ARRAY) _rs.getObject("DIMINFO");
450
451
        if (dim_info_array == null) {
452
            // no full extent found:
453
            return null;
454
        }
455
        else {
456
            Datum[] da = dim_info_array.getOracleArray();
457
458
            STRUCT sx = (STRUCT) da[0];
459
            STRUCT sy = (STRUCT) da[1];
460
461
            try {
462
                double minx = Double.parseDouble(sx.getAttributes()[1].toString());
463
                double maxx = Double.parseDouble(sx.getAttributes()[2].toString());
464
                double miny = Double.parseDouble(sy.getAttributes()[1].toString());
465
                double maxy = Double.parseDouble(sy.getAttributes()[2].toString());
466
467
                if (minx > maxx) {
468
                    double aux = minx;
469
                    minx = maxx;
470
                    maxx = aux;
471
                }
472
473
                if (miny > maxy) {
474
                    double aux = miny;
475
                    miny = maxy;
476
                    maxy = aux;
477
                }
478
479
                return getRectangle(minx, maxx, miny, maxy);
480
481
                // fullExtentJTS = shapeToGeometry(fullExtent);
482
            }
483
            catch (Exception ex) {
484
                System.err.println(
485
                    "Error while getting full extent from metadata table.");
486
487
                return null;
488
489
                // fullExtentJTS = null;
490
            }
491
        }
492
    }
493
494
    private void loadSdoMetadata() {
495
        try {
496
            Statement _st = conn.createStatement();
497 13994 fran.penarrubia@iver.es
            String[] tokens = getTableName().split("\\u002E", 2);
498
            String qry;
499
            if (tokens.length > 1)
500
            {
501
                    qry = "select * from " + ORACLE_GEOMETADATA_VIEW +
502
                " where OWNER = '" + tokens[0] + "' AND TABLE_NAME = '" +
503
                tokens[1] + "'";
504
            }
505
            else
506
            {
507
                    qry = "select * from " + ORACLE_GEOMETADATA_VIEW +
508 13991 jldominguez@prodevelop.es
                " where TABLE_NAME = " + "'" + getTableName() + "'";
509 13994 fran.penarrubia@iver.es
510
            }
511
//            String qry = "select * from " + ORACLE_GEOMETADATA_VIEW +
512
//                " where TABLE_NAME = " + "'" + getTableName() + "'";
513 13991 jldominguez@prodevelop.es
            ResultSet _rs = _st.executeQuery(qry);
514
515
            if (_rs.next()) {
516
                oracleSRID = getOracleSridFromCurrentRecord(_rs);
517
518
                isGeogCS = getIsGCS(oracleSRID, tableHasSrid);
519
520
                try {
521
                                        epsgSRID = oracleSridToEpsgSrid(oracleSRID);
522
                                } catch (Exception e) {
523
                                        logger.error("Unknown oracle SRID: " + oracleSRID);
524
                                        tableHasSrid = false;
525
                                }
526
                full_Extent = getFullExtentFromCurrentRecord(_rs);
527
528
                hasRealiableExtent = realiableExtent(full_Extent, isGeogCS);
529
530
                if (!hasRealiableExtent) {
531
                        full_Extent = getFastEstimatedGeodeticExtent(
532
                                        getTableName(), geoColName, conn, 20, 10);
533
                }
534
535
                _rs.close();
536
                _st.close();
537
            }
538
            else {
539
                throw new SQLException("Empty resultset from this query: " +
540
                    qry);
541
            }
542
        }
543
        catch (SQLException se) {
544
            System.err.println("Error while getting SDO metadata: " +
545
                se.getMessage());
546
        }
547
    }
548
549
    /**
550
     * Utility method to find out if a coordinate system is geodetic or not.
551
     *
552
     * @param oracleSRID2 the coordinate system's oracle code
553
     * @param thas whether the table has a coordinate system set.
554
     * if not, the method returns false.
555
     * @return whether the coordinate system is geodetic or not.
556
     */
557
    public static boolean getIsGCS(String oracleSRID2, boolean thas) {
558
559
        if (!thas) return false;
560
        int ora_cs = 0;
561
562
        try {
563
            ora_cs = Integer.parseInt(oracleSRID2);
564
        }
565
        catch (Exception ex) {
566
            return false;
567
        }
568
569
        if (((ora_cs >= 8000) && (ora_cs <= 8999)) || (ora_cs == 524288)) {
570
            return true;
571
        } else {
572
                return false;
573
        }
574
    }
575
576
    private Rectangle2D getRectangle(double minx, double maxx, double miny,
577
        double maxy) {
578
        Rectangle2D resp = new Rectangle2D.Double(minx, miny, maxx - minx,
579
                maxy - miny);
580
581
        return resp;
582
    }
583
584
    private void oneRowMetadata() {
585
        try {
586
            String _sql = "select " + getStandardSelectExpression() + ", c." +
587
                geoColName + " from " + getTableName() + " c ";
588
589
            st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
590
                    ResultSet.CONCUR_READ_ONLY);
591
592
            ResultSet _rs = st.executeQuery(_sql + " where (rownum = 1)");
593
594
            if (_rs.next()) {
595
                STRUCT sample_geo = (STRUCT) _rs.getObject(geoColName);
596
                shapeType = getShapeTypeOfStruct(sample_geo);
597
            }
598
            else {
599
                shapeType = FShape.MULTI;
600
            }
601
602
            // -----------------------
603
            _rs = st.executeQuery(not_restricted_sql + " where (rownum = 1)");
604
            metaData = _rs.getMetaData();
605 13995 jldominguez@prodevelop.es
            userName = conn.getMetaData().getUserName();
606
607 13991 jldominguez@prodevelop.es
608
            // geoColInd = _rs.findColumn(geoColName);
609
            oneBasedGeoColInd = metaData.getColumnCount() + 1;
610
611
            DatabaseMetaData dbmd = conn.getMetaData();
612
            pkOneBasedIndexes = getPKIndexes(dbmd, _rs);
613
614
            int cnt = metaData.getColumnCount();
615
            fieldNames = new String[cnt];
616
617
            for (int i = 0; i < cnt; i++) {
618
                fieldNames[i] = metaData.getColumnName(i + 1);
619
            }
620
621
            getIdFieldNames();
622
623
            adjustLyrDef();
624
625
            _rs.close(); // st no debe cerrarse ya que las llamadas a metadata lo encesitan
626
        }
627
        catch (SQLException se) {
628
            logger.error("While getting metadata. " + se.getMessage());
629
        }
630
    }
631
632
    private int getShapeTypeOfStruct(STRUCT sample) throws SQLException {
633
        int code = ((NUMBER) sample.getOracleAttributes()[0]).intValue() % 10;
634
635
        switch (code) {
636
        case 1:
637
            return FShape.POINT;
638
639
        case 2:
640
            return FShape.LINE;
641
642
        case 3:
643
            return FShape.POLYGON;
644
645
        case 5:
646
            return FShape.MULTIPOINT;
647
648
        case 6:
649
            return FShape.LINE;
650
651
        case 7:
652
            return FShape.POLYGON;
653
        }
654
655
        logger.error("Unknown geometry type: " + code);
656
657
        return FShape.NULL;
658
    }
659
660
    private String getIdFieldNames() {
661
        try {
662
            idFieldNames = "";
663
664
            for (int i = 0; i < pkOneBasedIndexes.length; i++) {
665
                idFieldNames = idFieldNames +
666
                    metaData.getColumnName(pkOneBasedIndexes[i]) + ", ";
667
            }
668
        }
669
        catch (SQLException se) {
670
        }
671
672
        idFieldNames = idFieldNames.substring(0, idFieldNames.length() - 2);
673
674
        return idFieldNames;
675
    }
676
677
    private int[] getPKIndexes(DatabaseMetaData metaData, ResultSet table_rs) {
678
        int[] _res = new int[1];
679
        _res[0] = 1;
680
681
        return _res;
682
    }
683
684
    public String getSqlTotal() {
685
        // TODO Auto-generated method stub
686
        return "";
687
    }
688
689
    public String getCompleteWhere() {
690
        // TODO Auto-generated method stub
691
        return "";
692
    }
693
694
    /**
695
     * Gets the feature iterator for a given SQL sentence (ignores previous filters
696
     * and uses directly that sentence to query the table).
697
     */
698
    public IFeatureIterator getFeatureIterator(String sql)
699
        throws DriverException {
700
        if (isNotAvailableYet) {
701
            return null;
702
        }
703
704
        singleCachedFeatureRowNum = -1;
705
706
        Object[] rs_st = getViewResultSet(null, sql, tableHasSrid);
707
708
        ResultSet localrs = (ResultSet) rs_st[0];
709
        Statement _st = (Statement) rs_st[1];
710
711
        return new OracleSpatialFeatureIterator(this, localrs, _st,
712
            oneBasedGeoColInd, use_geotools);
713
    }
714
715
    /**
716
     * Gets Oracle particular connection string beginning: "jdbc:oracle:thin:"
717
     */
718
    public String getConnectionStringBeginning() {
719
        // oracle
720
        return CONN_STR_BEGIN;
721
    }
722
723
    public void open() throws DriverException {
724
    }
725
726
    /**
727
     * Gets Oracle's default port: 1521
728
     */
729
    public int getDefaultPort() {
730
        // oracle port
731
        return 1521;
732
    }
733
734
    /**
735
     * Gets the feature iterator for a given rectangle (the view's bounding box)
736
     * and a SRS.
737
     */
738
    public IFeatureIterator getFeatureIterator(Rectangle2D r, String strEPSG)
739
        throws DriverException {
740
        if (isNotAvailableYet) {
741
            return null;
742
        }
743
744
        singleCachedFeatureRowNum = -1;
745
746
        STRUCT local_st = shapeToStruct(r, FShape.NULL, true, false, true);
747
748
        Object[] rs_st = getViewResultSet(local_st, null, tableHasSrid);
749
750
        ResultSet localrs = (ResultSet) rs_st[0];
751
        Statement _st = (Statement) rs_st[1];
752
753
        return new OracleSpatialFeatureIterator(this, localrs, _st,
754
            oneBasedGeoColInd, use_geotools);
755
    }
756
757
    private Rectangle2D intersectWithWorkingArea(Rectangle2D r) {
758
        if (workingAreaInTablesCS == null) return r;
759
        return doIntersect(r, workingAreaInTablesCS);
760
    }
761
762
    /**
763
     * This method reverts to the one without the fields specification.
764
     * The fields have been selected from the start.
765
     */
766
    public IFeatureIterator getFeatureIterator(Rectangle2D r, String strEPSG,
767
        String[] alphaNumericFieldsNeeded) throws DriverException {
768
        if (isNotAvailableYet) {
769
            return null;
770
771
            // return emptyIt;
772
        }
773
774
        singleCachedFeatureRowNum = -1;
775
776
        return getFeatureIterator(r, strEPSG);
777
    }
778
779
    public String getGeometryField(String fieldName) {
780
        return fieldName;
781
782
        // return "ASBINARY(" + fieldName + ")";
783
    }
784
785
    public DriverAttributes getDriverAttributes() {
786
        return drvAtts;
787
    }
788
789
    /**
790
     * Gets the requested geometry. Always performs a new query in this case.
791
     * This should be a rare way to get the geometries. The standard way is by using
792
     * the iterators.
793
     */
794
    public IGeometry getShape(int _ind) throws IOException {
795
        if (isNotAvailableYet) {
796
            return nullGeom;
797
        }
798
799
        ROWID r_id = (ROWID) rowToId.get(new Integer(_ind));
800
801
        String _sql = "select " + geoColName + " from " + getTableName() +
802
            " where rowid = ?";
803
804
        try {
805
            java.sql.PreparedStatement ps = conn.prepareStatement(_sql);
806
            ps.setObject(1, r_id);
807
808
            // Statement stmnt = conn.createStatement();
809
            ps.execute();
810
811
            ResultSet _res = ps.getResultSet();
812
813
            if (_res.next()) {
814
                STRUCT _st = (oracle.sql.STRUCT) _res.getObject(1); // geocolind);
815
                IGeometry theGeom = getGeometryUsing(_st, use_geotools);
816
                _res.close();
817
                ps.close();
818
819
                return theGeom;
820
            }
821
            else {
822
                logger.error("Unable to get shape: " + _ind +
823
                    " (probably due to edition)");
824
825
                return nullGeom;
826
            }
827
        }
828
        catch (SQLException se) {
829
            throw new IOException("SQLException: " + se.getMessage());
830
        }
831
    }
832
833
    public boolean isWritable() {
834
        return true;
835
    }
836
837
    public String getName() {
838
        return NAME;
839
    }
840
841
    public int[] getPrimaryKeys()
842
        throws com.hardcode.gdbms.engine.data.driver.DriverException {
843
        return pkOneBasedIndexes;
844
    }
845
846
    public void write(DataWare dataWare)
847
        throws com.hardcode.gdbms.engine.data.driver.DriverException {
848
    }
849
850
    private void setIdRowTable() {
851
        hashRelate = new Hashtable();
852
853
        java.sql.PreparedStatement ps = null;
854
855
        try {
856
            String _sql = getIdAndElemInfoFullResulltSetQuery();
857
858
            logger.debug("SQL para leer ids: " + _sql);
859
            Statement st = null;
860
861
862
            st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
863
                        ResultSet.CONCUR_READ_ONLY);
864
865
            st.setFetchSize(FETCH_SIZE);
866
            logger.info("FETCH_SIZE = " + FETCH_SIZE);
867
868
            ResultSet _r = null;
869
            _r = st.executeQuery(_sql);
870
871
            ROWID ri = null;
872
873
            int row = 0;
874
            String gid;
875
            Value aux = null;
876
877
            // ----------------------------------- types init
878
            ArrayList types = new ArrayList();
879
            int types_aux = 0;
880
881
            ARRAY info_aux;
882
            int[] info_aux_int;
883
            int size;
884
885
            // ----------------------------------- types init
886
            logger.debug("Beginning of result set:");
887
888
            while (_r.next()) {
889
                // ---------------------------------------
890
                ri = (ROWID) _r.getObject(1);
891
                gid = ri.stringValue();
892
                aux = ValueFactory.createValue(gid);
893
894
                Integer intobj = new Integer(row);
895
                hashRelate.put(aux, intobj);
896
                rowToId.put(intobj, ri);
897
898
                if ((row % 5000) == 0) {
899
                    // ------------------------------------------- cancel load
900
                    if (cancelIDLoad) {
901
                        hashRelate.clear();
902
                        rowToId.clear();
903
904
                        return;
905
                    }
906
907
                    // -------------------------------------------
908
                    String fmt = OracleSpatialUtils.getFormattedInteger(row);
909
                    logger.info("IDs read: " + fmt);
910
                }
911
912
                row++;
913
914
                // --------------------------------------- types
915
                info_aux = (ARRAY) _r.getObject(2);
916
917
                if (info_aux == null) {
918
                    // logger.debug("NULL info array found in record: " + row);
919
                }
920
                else {
921
                    info_aux_int = info_aux.getIntArray();
922
                    size = info_aux_int.length / 3;
923
924
                    for (int i = 0; i < size; i++) {
925
                        types_aux = info_aux_int[(3 * i) + 1];
926
                        types.add(new Integer(types_aux % 1000));
927
                    }
928
                }
929
930
                // --------------------------------------- types end
931
            }
932
933
            _r.close();
934
//            ps.close();
935
            st.close();
936
            numReg = row;
937
938
            needsCollectionLayer = hasSeveralGeometryTypes(types, false);
939
940
            if (needsCollectionLayer) {
941
                shapeType = FShape.MULTI;
942
            }
943
        }
944
        catch (SQLException e) {
945
            System.err.println("While setting id-row hashmap: " +
946
                e.getMessage());
947
        }
948
    }
949
950
    public int getFieldCount()
951
        throws com.hardcode.gdbms.engine.data.driver.DriverException {
952
        try {
953
            return metaData.getColumnCount();
954
        }
955
        catch (SQLException e) {
956
            System.err.println("While getting field count: " + e.getMessage());
957
            throw new com.hardcode.gdbms.engine.data.driver.DriverException(e.getMessage());
958
        }
959
    }
960
961
    public String[] getFieldNames() {
962
        return fieldNames;
963
    }
964
965
    public String getTotalFields() {
966
        String strAux = "";
967
968
        for (int i = 0; i < fieldNames.length; i++) {
969
            if (i == 0) {
970
                strAux = fieldNames[i];
971
            }
972
            else {
973
                strAux = strAux + ", " + fieldNames[i];
974
            }
975
        }
976
977
        return strAux;
978
    }
979
980
    public int getFieldType(int idField)
981
        throws com.hardcode.gdbms.engine.data.driver.DriverException {
982
        int i = 0;
983
984
        try {
985
            i = idField + 1; // idField viene basado en 0
986
987
            int __type = metaData.getColumnType(i);
988
989
            // we must add this entry because we did not remove the 'geometry' column
990
            if (__type == Types.STRUCT) {
991
                return Types.VARCHAR; // .STRUCT;
992
                                      // ----------------------------------------------------------------------
993
            }
994
995
            if (__type == Types.VARCHAR) {
996
                return Types.VARCHAR;
997
            }
998
999
            if (__type == Types.FLOAT) {
1000
                return Types.FLOAT;
1001
            }
1002
1003
            if (__type == Types.DOUBLE) {
1004
                return Types.DOUBLE;
1005
            }
1006
1007
            if (__type == Types.INTEGER) {
1008
                return Types.INTEGER;
1009
            }
1010
1011
            if (__type == Types.SMALLINT) {
1012
                return Types.SMALLINT;
1013
            }
1014
1015
            if (__type == Types.TINYINT) {
1016
                return Types.TINYINT;
1017
            }
1018
1019
            if (__type == Types.BIGINT) {
1020
                return Types.BIGINT;
1021
            }
1022
1023
            if (__type == Types.BIT) {
1024
                return Types.BIT;
1025
            }
1026
1027
            if (__type == Types.DATE) {
1028
                return Types.DATE;
1029
            }
1030
1031
            if (__type == Types.DECIMAL) {
1032
                return Types.DOUBLE;
1033
            }
1034
1035
            if (__type == Types.NUMERIC) {
1036
                return Types.DOUBLE;
1037
            }
1038
1039
            if (__type == Types.DATE) {
1040
                return Types.DATE;
1041
            }
1042
1043
            if (__type == Types.TIME) {
1044
                return Types.TIME;
1045
            }
1046
1047
            if (__type == Types.TIMESTAMP) {
1048
                return Types.TIMESTAMP;
1049
            }
1050
        }
1051
        catch (SQLException e) {
1052
            System.err.println("i = " + i);
1053
            throw new com.hardcode.gdbms.engine.data.driver.DriverException(e);
1054
        }
1055
1056
        return -1;
1057
    }
1058
1059
    public Value[] getAttributes(ResultSet rs) {
1060
        Value[] res = null;
1061
1062
        try {
1063
            int fcount = rs.getMetaData().getColumnCount();
1064
            res = new Value[fcount];
1065
1066
            for (int i = 0; i < fcount; i++) {
1067
                Object obj = rs.getObject(i + 1);
1068
                String objToString = null;
1069
                int _type = -1;
1070
1071
                if (obj instanceof String) {
1072
                    objToString = (String) obj;
1073
                    _type = Types.VARCHAR;
1074
                }
1075
                else {
1076
                    if (obj instanceof ROWID) {
1077
                        objToString = ((ROWID) obj).stringValue();
1078
                        _type = Types.VARCHAR;
1079
                    }
1080
                    else {
1081
                        if (obj instanceof STRUCT) {
1082
                            objToString = "STRUCT";
1083
                            _type = Types.VARCHAR;
1084
                        }
1085
                        else {
1086
                            objToString = (obj == null) ? "NULL" : obj.toString();
1087
                            _type = getFieldType(i);
1088
                        }
1089
                    }
1090
                }
1091
1092
                // /*
1093
                if (_type == -1) {
1094
                    obj = null;
1095
                }
1096
1097
                // */
1098
                if (obj == null) {
1099
                    res[i] = ValueFactory.createNullValue();
1100
                }
1101
                else {
1102
                    if (_type == Types.DATE) {
1103
                        objToString = objToString.replace('-', '/');
1104
                    }
1105
1106
                    res[i] = ValueFactory.createValueByType(objToString, _type);
1107
                }
1108
            }
1109
        }
1110
        catch (SQLException se) {
1111
            System.err.println("Error while getting attributes: " +
1112
                se.getMessage());
1113
1114
            return null;
1115
        }
1116
        catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
1117
            System.err.println("Error while getting attributes: " +
1118
                e.getMessage());
1119
1120
            return null;
1121
        }
1122
        catch (ParseException e) {
1123
            System.err.println("Error while getting attributes: " +
1124
                e.getMessage());
1125
1126
            return null;
1127
        }
1128
1129
        return res;
1130
    }
1131
1132
    public Value[] getAttributesUsingMainMetadata(ResultSet rs) {
1133
        Value[] res = null;
1134
1135
        try {
1136
            int fcount = metaData.getColumnCount();
1137
            res = new Value[fcount];
1138
1139
            for (int i = 0; i < fcount; i++) {
1140
                Object obj = rs.getObject(i + 1);
1141
                String objToString = null;
1142
                int _type = -1;
1143
1144
                if (obj instanceof String) {
1145
                    objToString = (String) obj;
1146
                    _type = Types.VARCHAR;
1147
                }
1148
                else {
1149
                    if (obj instanceof ROWID) {
1150
                        objToString = ((ROWID) obj).stringValue();
1151
                        _type = Types.VARCHAR;
1152
                    }
1153
                    else {
1154
                        if (obj instanceof STRUCT) {
1155
                            objToString = "STRUCT";
1156
                            _type = Types.VARCHAR;
1157
                        }
1158
                        else {
1159
                            objToString = (obj == null) ? "NULL" : obj.toString();
1160
                            _type = getFieldType(i);
1161
                        }
1162
                    }
1163
                }
1164
1165
                // /*
1166
                if (_type == -1) {
1167
                    obj = null;
1168
                }
1169
1170
                // */
1171
                if (obj == null) {
1172
                    res[i] = ValueFactory.createNullValue();
1173
                }
1174
                else {
1175
                    if (_type == Types.DATE) {
1176
                        objToString = objToString.replace('-', '/');
1177
                    }
1178
1179
                    res[i] = ValueFactory.createValueByType(objToString, _type);
1180
                }
1181
            }
1182
        }
1183
        catch (SQLException se) {
1184
            System.err.println("Error while getting attributes: " +
1185
                se.getMessage());
1186
1187
            return null;
1188
        }
1189
        catch (com.hardcode.gdbms.engine.data.driver.DriverException e) {
1190
            System.err.println("Error while getting attributes: " +
1191
                e.getMessage());
1192
1193
            return null;
1194
        }
1195
        catch (ParseException e) {
1196
            System.err.println("Error while getting attributes: " +
1197
                e.getMessage());
1198
1199
            return null;
1200
        }
1201
1202
        return res;
1203
    }
1204
1205
1206
    public String getFieldName(int fieldId)
1207
        throws com.hardcode.gdbms.engine.data.driver.DriverException {
1208
        return fieldNames[fieldId];
1209
    }
1210
1211
    public int getFieldWidth(int fieldId) {
1212
        int i = -1;
1213
1214
        try {
1215
            int aux = fieldId + 1; // fieldId viene basado en 0
1216
            i = metaData.getColumnDisplaySize(aux);
1217
        }
1218
        catch (SQLException e) {
1219
            System.err.println("While getting field width: " + e.getMessage());
1220
        }
1221
1222
        if (i < 0) {
1223
            i = 255;
1224
        }
1225
1226
        return i;
1227
    }
1228
1229
    public Value getFieldValue(long rowIndex, int field_Id)
1230
        throws com.hardcode.gdbms.engine.data.driver.DriverException {
1231
        if (isNotAvailableYet) {
1232
            return nullVal;
1233
        }
1234
1235
        if ((singleCachedFeature != null) &&
1236
                (rowIndex == singleCachedFeatureRowNum)) {
1237
            return singleCachedFeature.getAttributes()[field_Id];
1238
        }
1239
1240
        // return ValueFactory.createNullValue();
1241
        ResultSet _r = null;
1242
        java.sql.PreparedStatement ps = null;
1243
1244
        try {
1245
            String rnq = getSearchId();
1246
            ROWID _id = (ROWID) rowToId.get(new Integer((int) rowIndex));
1247
1248
            ps = conn.prepareStatement(rnq);
1249
            ps.setObject(1, _id);
1250
1251
            ps.execute();
1252
            _r = ps.getResultSet();
1253
            _r.next();
1254
        }
1255
        catch (SQLException se) {
1256
            throw new com.hardcode.gdbms.engine.data.driver.DriverException(se.getMessage());
1257
        }
1258
1259
        IFeature ife = null;
1260
        Value[] atts = null;
1261
1262
        try {
1263
            ROWID ri = (ROWID) _r.getObject(1);
1264
            atts = getAttributesUsingMainMetadata(_r);
1265
1266
            String gid = ri.stringValue();
1267
            STRUCT _st = (oracle.sql.STRUCT) _r.getObject(oneBasedGeoColInd);
1268
            IGeometry theGeom = getGeometryUsing(_st, use_geotools);
1269
            ife = new DefaultFeature(theGeom, atts, gid);
1270
            _r.close();
1271
            ps.close();
1272
        }
1273
        catch (SQLException se) {
1274
            logger.error("Error while doing next(): " + se.getMessage(), se);
1275
        }
1276
1277
        // -------------------------------
1278
        singleCachedFeature = ife;
1279
        singleCachedFeatureRowNum = rowIndex;
1280
1281
        // -------------------------------
1282
        if (atts == null) {
1283
            return ValueFactory.createNullValue();
1284
        }
1285
        else {
1286
            return atts[field_Id];
1287
        }
1288
    }
1289
1290
    public static void showMemory() {
1291
        Runtime r = Runtime.getRuntime();
1292
        long mem = r.totalMemory() - r.freeMemory();
1293
        System.err.println("Memoria total: " + mem);
1294
    }
1295
1296
    public Rectangle2D getFullExtent() {
1297
            return full_Extent;
1298
    }
1299
1300
    /**
1301
     * Utility method to get a geometry from a struct.
1302
     *
1303
     * @param theStruct the struct to be converted
1304
     * @param use_gtools switch to use geotools classes or not
1305
     * @return the geometry
1306
     * @throws SQLException
1307
     */
1308
    public IGeometry getGeometryUsing(STRUCT theStruct, boolean use_gtools)
1309
        throws SQLException {
1310
        IGeometry _igeom = null;
1311
1312
        if (theStruct == null) {
1313
            return nullGeom;
1314
        }
1315
1316
        if (use_gtools) { // geotools
1317
//            _igeom = getGeotoolsIGeometry(theStruct);
1318
        }
1319
        else { // jgeometry
1320
            _igeom = getFMapGeometry(theStruct, false);
1321
        }
1322
1323
        return _igeom;
1324
    }
1325
1326
    private IGeometry getFMapGeometry(JGeometry jg, boolean force_not_collection) {
1327
        int jgtype = jg.getType();
1328
        int dim = jg.getDimensions();
1329
        IGeometry ig = null;
1330
1331
        if ((jgtype != JGeometry.GTYPE_COLLECTION) &&
1332
                (isActuallyACollection(jg))) {
1333
            jgtype = JGeometry.GTYPE_COLLECTION;
1334
        }
1335
1336
        switch (jgtype) {
1337
        case JGeometry.GTYPE_COLLECTION:
1338
1339
            int srid = jg.getSRID();
1340
            ig = getFMapGeometryCollection(jg, dim, srid);
1341
1342
            break;
1343
1344
        case JGeometry.GTYPE_POINT:
1345
        case JGeometry.GTYPE_MULTIPOINT:
1346
            ig = getFMapGeometryPoint(jg, dim);
1347
1348
            break;
1349
1350
        case JGeometry.GTYPE_CURVE:
1351
        case JGeometry.GTYPE_MULTICURVE:
1352
            ig = getFMapGeometryMultiLineString(jg, dim);
1353
1354
            break;
1355
1356
        case JGeometry.GTYPE_POLYGON:
1357
        case JGeometry.GTYPE_MULTIPOLYGON:
1358
            ig = getFMapGeometryMultipolygon(jg, dim);
1359
1360
            break;
1361
        }
1362
1363
        return ig;
1364
    }
1365
1366
    private IGeometry getFMapGeometryCollection(Datum[] the_data, int dim,
1367
        int __srid) {
1368
        NUMBER main_type = new NUMBER((dim * 1000) +
1369
                OracleSpatialUtils.getStructType(the_data));
1370
        NUMBER _srid = new NUMBER(__srid);
1371
1372
        Datum[] all_info_array = null;
1373
        Object[] elems_info_aray = null;
1374
        Datum[] all_ords = null;
1375
1376
        try {
1377
            all_info_array = ((ARRAY) the_data[3]).getOracleArray();
1378
            elems_info_aray = groupByElement(all_info_array);
1379
            all_ords = ((ARRAY) the_data[4]).getOracleArray();
1380
        }
1381
        catch (SQLException e) {
1382
            logger.error("Unexpected error: " + e.getMessage());
1383
        }
1384
1385
        Object[] ords_of_groups = getOrdOfGroups(all_ords, elems_info_aray);
1386
        Object[] _elems_info_aray = new Object[elems_info_aray.length];
1387
1388
        for (int i = 0; i < elems_info_aray.length; i++) {
1389
            _elems_info_aray[i] = updateIndexes((Datum[]) elems_info_aray[i]);
1390
        }
1391
1392
        // _elems_info_aray, ords_of_groups
1393
        int no_of_elems = ords_of_groups.length;
1394
        IGeometry[] geoms = new IGeometry[no_of_elems];
1395
1396
        for (int i = 0; i < no_of_elems; i++) {
1397
            Datum[] item_info_array = null;
1398
            Datum[] item_ords = null;
1399
            NUMBER gtype = null;
1400
1401
            try {
1402
                item_info_array = (Datum[]) _elems_info_aray[i];
1403
                item_ords = (Datum[]) ords_of_groups[i];
1404
1405
                gtype = new NUMBER((dim * 1000) +
1406
                        (item_info_array[1].intValue() % 1000));
1407
            }
1408
            catch (SQLException se) {
1409
                logger.error("Unexpected error: " + se.getMessage());
1410
            }
1411
1412
            // if it's the first geometry, the type is the collection's main type (no?)
1413
            if (i == 0) {
1414
                gtype = main_type;
1415
            }
1416
1417
            STRUCT itemst = null;
1418
1419
            if (tableHasSrid) {
1420
                itemst = OracleSpatialUtils.createStruct(gtype, _srid,
1421
                        item_info_array, item_ords, conn);
1422
            }
1423
            else {
1424
                itemst = OracleSpatialUtils.createStruct(gtype, null,
1425
                        item_info_array, item_ords, conn);
1426
            }
1427
1428
            geoms[i] = getFMapGeometry(itemst, true);
1429
        }
1430
1431
        return new FGeometryCollection(geoms);
1432
    }
1433
1434
    /**
1435
     * Utility method to transform a struct into a IGeometry.
1436
     *
1437
     * @param st the struct to be converted
1438
     * @param force_not_collection t5his parameter is currently ignored
1439
     * @return the IGeometry
1440
     */
1441
    public IGeometry getFMapGeometry(STRUCT st, boolean force_not_collection) {
1442
        Datum[] the_data = null;
1443
1444
        try {
1445
            the_data = st.getOracleAttributes();
1446
1447
            int jgtype = ((NUMBER) the_data[0]).intValue() % 1000;
1448
            jgtype = OracleSpatialUtils.oracleGTypeToFShapeType(jgtype);
1449
1450
            int dim = ((NUMBER) the_data[0]).intValue() / 1000;
1451
1452
            if (dim < 2) {
1453
                dim = 2;
1454
            }
1455
1456
            IGeometry ig = null;
1457
1458
            if (isActuallyACollection(the_data)) {
1459
                jgtype = FShape.MULTI;
1460
            }
1461
1462
            switch (jgtype) {
1463
            case FShape.MULTI:
1464
1465
                int srid = ((NUMBER) the_data[1]).intValue();
1466
                ig = getFMapGeometryCollection(the_data, dim, srid);
1467
1468
                break;
1469
1470
            case FShape.POINT:
1471
                ig = getFMapGeometryPoint(the_data, dim);
1472
1473
                break;
1474
1475
            case FShape.LINE:
1476
                ig = getFMapGeometryMultiLineString(the_data, dim);
1477
1478
                break;
1479
1480
            case FShape.POLYGON:
1481
                ig = getFMapGeometryMultipolygon(the_data, dim);
1482
1483
                break;
1484
            }
1485
1486
            return ig;
1487
        }
1488
        catch (SQLException e) {
1489
            logger.error(e);
1490
        }
1491
1492
        return null;
1493
    }
1494
1495
    private double[] getIndDoublesModule(double[] input, int ind, int n) {
1496
        int size = input.length / n;
1497
        double[] resp = new double[size];
1498
1499
        for (int i = 0; i < size; i++) {
1500
            resp[i] = input[(i * n) + ind];
1501
        }
1502
1503
        return resp;
1504
    }
1505
1506
    private double[] getIndBigDecimalModule(double[] input, int ind, int n) {
1507
        int size = input.length / n;
1508
        double[] resp = new double[size];
1509
1510
        for (int i = 0; i < size; i++) {
1511
            resp[i] = input[(i * n) + ind];
1512
        }
1513
1514
        return resp;
1515
    }
1516
1517
    private IGeometry getFMapGeometryMultipolygon(JGeometry jg, int dim) {
1518
        IGeometry ig = null;
1519
1520
        if (jg.isCircle()) {
1521
            ig = getCircleFromJGeometry(jg);
1522
        }
1523
        else {
1524
            Shape shape = jg.createShape();
1525
            GeneralPathX gpx = new GeneralPathX(shape);
1526
1527
            if (dim == 2) {
1528
                ig = ShapeFactory.createPolygon2D(gpx);
1529
            }
1530
            else {
1531
                double[] z = getIndDoublesModule(jg.getOrdinatesArray(), 2, dim);
1532
                ig = ShapeFactory.createPolygon3D(gpx, z);
1533
            }
1534
        }
1535
1536
        return ig;
1537
    }
1538
1539
    private IGeometry getFMapGeometryMultipolygon(Datum[] the_data, int dim) {
1540
        IGeometry ig = null;
1541
1542
        if (OracleSpatialUtils.isCircle(the_data)) {
1543
            ig = getCircleFromStruct(the_data);
1544
        }
1545
        else {
1546
            GeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
1547
1548
            if (dim == 2) {
1549
                ig = ShapeFactory.createPolygon2D(gpx);
1550
            }
1551
            else {
1552
                double[] ords = null;
1553
1554
                try {
1555
                    ords = ((ARRAY) the_data[4]).getDoubleArray();
1556
                }
1557
                catch (SQLException se) {
1558
                    logger.error("While getting ordinates: " + se.getMessage(),
1559
                        se);
1560
                }
1561
1562
                double[] z = getIndBigDecimalModule(ords, 2, dim);
1563
                ig = ShapeFactory.createPolygon3D(gpx, z);
1564
            }
1565
        }
1566
1567
        return ig;
1568
    }
1569
1570
    private IGeometry getCircleFromJGeometry(JGeometry jg) {
1571
        double[] threep = jg.getOrdinatesArray();
1572
        Point2D[] three = new Point2D.Double[3];
1573
        three[0] = new Point2D.Double(threep[0], threep[1]);
1574
        three[1] = new Point2D.Double(threep[2], threep[3]);
1575
        three[2] = new Point2D.Double(threep[4], threep[5]);
1576
1577
        Object[] cent_rad = OracleSpatialUtils.getCenterAndRadiousOfCirc(three);
1578
1579
        Point2D cent = (Point2D) cent_rad[0];
1580
        double radius = ((Double) cent_rad[1]).doubleValue();
1581
1582
        IGeometry circ = ShapeFactory.createCircle(cent, radius);
1583
1584
        return circ;
1585
    }
1586
1587
    private IGeometry getCircleFromStruct(Datum[] the_data) {
1588
        double[] threep = null;
1589
1590
        try {
1591
            threep = ((ARRAY) the_data[4]).getDoubleArray();
1592
        }
1593
        catch (SQLException se) {
1594
            logger.error("While getting ords from struct: " + se.getMessage(),
1595
                se);
1596
1597
            return new FNullGeometry();
1598
        }
1599
1600
        Point2D[] three = new Point2D.Double[3];
1601
        three[0] = new Point2D.Double(threep[0], threep[1]);
1602
        three[1] = new Point2D.Double(threep[2], threep[3]);
1603
        three[2] = new Point2D.Double(threep[4], threep[5]);
1604
1605
        Object[] cent_rad = OracleSpatialUtils.getCenterAndRadiousOfCirc(three);
1606
1607
        Point2D cent = (Point2D) cent_rad[0];
1608
        double radius = ((Double) cent_rad[1]).doubleValue();
1609
1610
        IGeometry circ = ShapeFactory.createCircle(cent, radius);
1611
1612
        return circ;
1613
    }
1614
1615
    private IGeometry getFMapGeometryMultiLineString(JGeometry jg, int dim) {
1616
        Shape shape = jg.createShape();
1617
        GeneralPathX gpx = new GeneralPathX(shape);
1618
        IGeometry ig = null;
1619
1620
        if (dim == 2) {
1621
            ig = ShapeFactory.createPolyline2D(gpx);
1622
        }
1623
        else {
1624
            double[] z = getIndDoublesModule(jg.getOrdinatesArray(), 2, dim);
1625
            ig = ShapeFactory.createPolyline3D(gpx, z);
1626
        }
1627
1628
        return ig;
1629
    }
1630
1631
    private IGeometry getFMapGeometryMultiLineString(Datum[] the_data, int dim) {
1632
        GeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
1633
        IGeometry ig = null;
1634
        double[] ords = null;
1635
1636
        if (dim == 2) {
1637
            ig = ShapeFactory.createPolyline2D(gpx);
1638
        }
1639
        else {
1640
            ords = OracleSpatialUtils.getOrds(the_data);
1641
1642
            double[] z = getIndBigDecimalModule(ords, 2, dim);
1643
            ig = ShapeFactory.createPolyline3D(gpx, z);
1644
        }
1645
1646
        return ig;
1647
    }
1648
1649
    private IGeometry getFMapGeometryPoint(JGeometry jg_point, int dim) {
1650
        if (jg_point.getOrdinatesArray() == null) { // sdo_point
1651
1652
            return getFMapGeometrySdoPoint(jg_point, dim);
1653
        }
1654
1655
        IGeometry ig = null;
1656
        int total_size = jg_point.getOrdinatesArray().length;
1657
        int no_po = total_size / dim;
1658
        double[] x = new double[no_po];
1659
        double[] y = new double[no_po];
1660
        double[] z = new double[no_po];
1661
1662
        for (int i = 0; i < no_po; i++) {
1663
            x[i] = jg_point.getOrdinatesArray()[i * dim]; // pp[i].getX();
1664
            y[i] = jg_point.getOrdinatesArray()[(i * dim) + 1];
1665
1666
            if (dim >= 3) {
1667
                z[i] = jg_point.getOrdinatesArray()[(i * dim) + 2];
1668
            }
1669
        }
1670
1671
        if (dim == 2) {
1672
            if (no_po == 1) {
1673
                ig = ShapeFactory.createPoint2D(x[0], y[0]);
1674
            }
1675
            else {
1676
                ig = ShapeFactory.createMultipoint2D(x, y);
1677
            }
1678
        }
1679
        else {
1680
            if (no_po == 1) {
1681
                ig = ShapeFactory.createPoint3D(x[0], y[0], z[0]);
1682
            }
1683
            else {
1684
                ig = ShapeFactory.createMultipoint3D(x, y, z);
1685
            }
1686
        }
1687
1688
        return ig;
1689
    }
1690
1691
    private IGeometry getFMapGeometryPoint(Datum[] the_data, int dim) {
1692
        double[] ords = OracleSpatialUtils.getOrds(the_data);
1693
1694
        if (ords == null) { // sdo_point
1695
1696
            return getFMapGeometrySdoPoint(the_data, dim);
1697
        }
1698
1699
        IGeometry ig = null;
1700
        int total_size = ords.length;
1701
        int no_po = total_size / dim;
1702
        double[] x = new double[no_po];
1703
        double[] y = new double[no_po];
1704
        double[] z = new double[no_po];
1705
1706
        for (int i = 0; i < no_po; i++) {
1707
            x[i] = ords[i * dim]; // pp[i].getX();
1708
            y[i] = ords[(i * dim) + 1];
1709
1710
            if (dim >= 3) {
1711
                z[i] = ords[(i * dim) + 2];
1712
            }
1713
        }
1714
1715
        if (dim == 2) {
1716
            if (no_po == 1) {
1717
                ig = ShapeFactory.createPoint2D(x[0], y[0]);
1718
            }
1719
            else {
1720
                ig = ShapeFactory.createMultipoint2D(x, y);
1721
            }
1722
        }
1723
        else {
1724
            if (no_po == 1) {
1725
                ig = ShapeFactory.createPoint3D(x[0], y[0], z[0]);
1726
            }
1727
            else {
1728
                ig = ShapeFactory.createMultipoint3D(x, y, z);
1729
            }
1730
        }
1731
1732
        return ig;
1733
    }
1734
1735
    private IGeometry getFMapGeometrySdoPoint(JGeometry jgp, int d) {
1736
        double[] p = jgp.getPoint();
1737
        IGeometry ig = null;
1738
1739
        if (d == 2) {
1740
            ig = ShapeFactory.createPoint2D(p[0], p[1]);
1741
        }
1742
        else {
1743
            ig = ShapeFactory.createPoint3D(p[0], p[1], p[2]);
1744
        }
1745
1746
        return ig;
1747
    }
1748
1749
    private IGeometry getFMapGeometrySdoPoint(Datum[] the_data, int d) {
1750
        double x = 0;
1751
        double y = 0;
1752
        double z = 0;
1753
1754
        try {
1755
            Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
1756
            x = ((NUMBER) aux[0]).doubleValue();
1757
            y = ((NUMBER) aux[1]).doubleValue();
1758
1759
            if (d > 2) {
1760
                z = ((NUMBER) aux[2]).doubleValue();
1761
            }
1762
        }
1763
        catch (SQLException se) {
1764
            logger.error("While getting sdo point ordinates: " +
1765
                se.getMessage(), se);
1766
        }
1767
1768
        IGeometry ig = null;
1769
1770
        if (d == 2) {
1771
            ig = ShapeFactory.createPoint2D(x, y);
1772
        }
1773
        else {
1774
            ig = ShapeFactory.createPoint3D(x, y, z);
1775
        }
1776
1777
        return ig;
1778
    }
1779
1780
    private boolean isActuallyACollection(JGeometry jg) {
1781
        int[] info = jg.getElemInfo();
1782
1783
        if (info == null) {
1784
            return false; // sdo_point
1785
        }
1786
1787
        int size = info.length / 3;
1788
1789
        if (size == 1) {
1790
            return false;
1791
        }
1792
1793
        if (size == 2) {
1794
            return ((info[1] % 1000) != (info[4] % 1000));
1795
        }
1796
1797
        int second = info[4] % 1000;
1798
1799
        for (int i = 2; i < size; i++) {
1800
            if ((info[(i * 3) + 1] % 1000) != second) {
1801
                return true;
1802
            }
1803
        }
1804
1805
        return false;
1806
    }
1807
1808
    private boolean isActuallyACollection(Datum[] the_data) {
1809
        int[] info = null;
1810
1811
        try {
1812
            ARRAY aux = (ARRAY) the_data[3];
1813
1814
            if (aux == null) {
1815
                return false;
1816
            }
1817
1818
            info = aux.getIntArray();
1819
        }
1820
        catch (SQLException se) {
1821
            logger.error("While checking collection: " + se.getMessage());
1822
1823
            return false;
1824
        }
1825
1826
        if (info == null) {
1827
            return false; // sdo_point
1828
        }
1829
1830
        int size = info.length / 3;
1831
1832
        if (size == 1) {
1833
            return false;
1834
        }
1835
1836
        if (size == 2) {
1837
            return ((info[1] % 1000) != (info[4] % 1000));
1838
        }
1839
1840
        int second = info[4] % 1000;
1841
1842
        for (int i = 2; i < size; i++) {
1843
            if ((info[(i * 3) + 1] % 1000) != second) {
1844
                return true;
1845
            }
1846
        }
1847
1848
        return false;
1849
    }
1850
1851
    private IGeometry getFMapGeometryCollection(JGeometry jg, int dim, int _srid) {
1852
        int main_type = jg.getType();
1853
1854
        int[] all_info_array = jg.getElemInfo();
1855
        Object[] elems_info_aray = groupByElement(all_info_array);
1856
        double[] all_ords = jg.getOrdinatesArray();
1857
        Object[] ords_of_groups = getOrdOfGroups(all_ords, elems_info_aray);
1858
        Object[] _elems_info_aray = new Object[elems_info_aray.length];
1859
1860
        for (int i = 0; i < elems_info_aray.length; i++) {
1861
            _elems_info_aray[i] = updateIndexes((int[]) elems_info_aray[i]);
1862
        }
1863
1864
        // _elems_info_aray, ords_of_groups
1865
        int no_of_elems = ords_of_groups.length;
1866
        IGeometry[] geoms = new IGeometry[no_of_elems];
1867
1868
        for (int i = 0; i < no_of_elems; i++) {
1869
            int[] item_info_array = (int[]) _elems_info_aray[i];
1870
            double[] item_ords = (double[]) ords_of_groups[i];
1871
            int gtype = (dim * 1000) + (item_info_array[1] % 1000);
1872
1873
            // if it's the first geometry, the type is the collection's main type (no?)
1874
            if (i == 0) {
1875
                gtype = main_type;
1876
            }
1877
1878
            JGeometry itemjg = null;
1879
1880
            if (tableHasSrid) {
1881
                itemjg = new JGeometry(gtype, _srid, item_info_array, item_ords);
1882
            }
1883
            else {
1884
                itemjg = new JGeometry(gtype, 0, item_info_array, item_ords);
1885
            }
1886
1887
            geoms[i] = getFMapGeometry(itemjg, true);
1888
        }
1889
1890
        return new FGeometryCollection(geoms);
1891
    }
1892
1893
    private Datum[] updateIndexes(Datum[] info) {
1894
        int size = info.length / 3;
1895
        NUMBER[] resp = new NUMBER[3 * size];
1896
1897
        try {
1898
            int rest = info[0].intValue() - 1;
1899
1900
            for (int i = 0; i < size; i++) {
1901
                resp[3 * i] = new NUMBER(info[3 * i].intValue() - rest);
1902
                resp[(3 * i) + 1] = new NUMBER(info[(3 * i) + 1].intValue());
1903
                resp[(3 * i) + 2] = new NUMBER(info[(3 * i) + 2].intValue());
1904
            }
1905
        }
1906
        catch (SQLException se) {
1907
            logger.error("Unexpected error: " + se.getMessage());
1908
        }
1909
1910
        return resp;
1911
    }
1912
1913
    private int[] updateIndexes(int[] info) {
1914
        int size = info.length / 3;
1915
        int[] resp = new int[3 * size];
1916
        int rest = info[0] - 1;
1917
1918
        for (int i = 0; i < size; i++) {
1919
            resp[3 * i] = info[3 * i] - rest;
1920
            resp[(3 * i) + 1] = info[(3 * i) + 1];
1921
            resp[(3 * i) + 2] = info[(3 * i) + 2];
1922
        }
1923
1924
        return resp;
1925
    }
1926
1927
    private int[] appendIntArrays(int[] head, int[] tail) {
1928
        int[] resp = new int[head.length + tail.length];
1929
        int hsize = head.length;
1930
1931
        for (int i = 0; i < hsize; i++) {
1932
            resp[i] = head[i];
1933
        }
1934
1935
        for (int i = 0; i < tail.length; i++) {
1936
            resp[hsize + i] = tail[i];
1937
        }
1938
1939
        return resp;
1940
    }
1941
1942
    private Datum[] appendDatArrays(Datum[] head, Datum[] tail) {
1943
        Datum[] resp = new Datum[head.length + tail.length];
1944
        int hsize = head.length;
1945
1946
        for (int i = 0; i < hsize; i++) {
1947
            resp[i] = head[i];
1948
        }
1949
1950
        for (int i = 0; i < tail.length; i++) {
1951
            resp[hsize + i] = tail[i];
1952
        }
1953
1954
        return resp;
1955
    }
1956
1957
    private int[] getNthGroupOfThree(int[] list, int n) {
1958
        int[] resp = new int[3];
1959
        resp[0] = list[3 * n];
1960
        resp[1] = list[(3 * n) + 1];
1961
        resp[2] = list[(3 * n) + 2];
1962
1963
        return resp;
1964
    }
1965
1966
    private Datum[] getNthGroupOfThree(Datum[] list, int n) {
1967
        Datum[] resp = new Datum[3];
1968
        resp[0] = list[3 * n];
1969
        resp[1] = list[(3 * n) + 1];
1970
        resp[2] = list[(3 * n) + 2];
1971
1972
        return resp;
1973
    }
1974
1975
    private Datum[] getSubSet(Datum[] all, int first_inc, int last_inc) {
1976
        Datum[] resp = new Datum[last_inc - first_inc + 1];
1977
1978
        for (int i = first_inc; i <= last_inc; i++) {
1979
            resp[i - first_inc] = all[i];
1980
        }
1981
1982
        return resp;
1983
    }
1984
1985
    private double[] getSubSet(double[] all, int first_inc, int last_inc) {
1986
        double[] resp = new double[last_inc - first_inc + 1];
1987
1988
        for (int i = first_inc; i <= last_inc; i++) {
1989
            resp[i - first_inc] = all[i];
1990
        }
1991
1992
        return resp;
1993
    }
1994
1995
    private Object[] getOrdOfGroups(Datum[] all, Object[] groups) {
1996
        Object[] resp = new Object[groups.length];
1997
1998
        if (resp.length == 1) {
1999
            resp[0] = all;
2000
2001
            return resp;
2002
        }
2003
2004
        int ind = 0;
2005
        int[] aux = (int[]) groups[1];
2006
        int _end = aux[0] - 2;
2007
        Datum[] ord_aux = getSubSet(all, 0, _end);
2008
2009
        int _start = _end + 1;
2010
        resp[ind] = ord_aux;
2011
        ind++;
2012
2013
        for (int i = 2; i < groups.length; i++) {
2014
            aux = (int[]) groups[i];
2015
            _end = aux[0] - 2;
2016
            ord_aux = getSubSet(all, _start, _end);
2017
            resp[ind] = ord_aux;
2018
            ind++;
2019
            _start = _end + 1;
2020
        }
2021
2022
        // last
2023
        _end = all.length - 1;
2024
        ord_aux = getSubSet(all, _start, _end);
2025
        resp[groups.length - 1] = ord_aux;
2026
2027
        return resp;
2028
    }
2029
2030
    private Object[] getOrdOfGroups(double[] all, Object[] groups) {
2031
        Object[] resp = new Object[groups.length];
2032
2033
        if (resp.length == 1) {
2034
            resp[0] = all;
2035
2036
            return resp;
2037
        }
2038
2039
        int ind = 0;
2040
        int[] aux = (int[]) groups[1];
2041
        int _end = aux[0] - 2;
2042
        double[] ord_aux = getSubSet(all, 0, _end);
2043
2044
        int _start = _end + 1;
2045
        resp[ind] = ord_aux;
2046
        ind++;
2047
2048
        for (int i = 2; i < groups.length; i++) {
2049
            aux = (int[]) groups[i];
2050
            _end = aux[0] - 2;
2051
            ord_aux = getSubSet(all, _start, _end);
2052
            resp[ind] = ord_aux;
2053
            ind++;
2054
            _start = _end + 1;
2055
        }
2056
2057
        // last
2058
        _end = all.length - 1;
2059
        ord_aux = getSubSet(all, _start, _end);
2060
        resp[groups.length - 1] = ord_aux;
2061
2062
        return resp;
2063
    }
2064
2065
    private Object[] groupByElement(int[] all_elem) {
2066
        ArrayList resp = new ArrayList();
2067
2068
        int size = all_elem.length / 3;
2069
2070
        int[] aux = getNthGroupOfThree(all_elem, 0);
2071
2072
        int[] newaux;
2073
        int i = 1;
2074
2075
        while (i < size) {
2076
            newaux = getNthGroupOfThree(all_elem, i);
2077
2078
            if (newaux[0] == aux[0]) {
2079
                // aux[2] says how many components
2080
                for (int j = 0; j < aux[2]; j++) {
2081
                    aux = appendIntArrays(aux,
2082
                            getNthGroupOfThree(all_elem, j + i));
2083
                }
2084
2085
                resp.add(aux);
2086
                i = i + aux[2];
2087
                aux = getNthGroupOfThree(all_elem, i);
2088
            }
2089
            else {
2090
                if (newaux[1] == 2003) {
2091
                    aux = appendIntArrays(aux, newaux);
2092
                }
2093
                else {
2094
                    resp.add(aux);
2095
                    aux = getNthGroupOfThree(all_elem, i);
2096
                }
2097
            }
2098
2099
            i++;
2100
        }
2101
2102
        resp.add(aux);
2103
2104
        return resp.toArray();
2105
    }
2106
2107
    private Object[] groupByElement(Datum[] all_elem) {
2108
        ArrayList resp = new ArrayList();
2109
2110
        int size = all_elem.length / 3;
2111
2112
        Datum[] aux = getNthGroupOfThree(all_elem, 0);
2113
2114
        Datum[] newaux;
2115
        int i = 1;
2116
2117
        try {
2118
            while (i < size) {
2119
                newaux = getNthGroupOfThree(all_elem, i);
2120
2121
                if (newaux[0] == aux[0]) {
2122
                    // aux[2] says how many components
2123
                    for (int j = 0; j < ((NUMBER) aux[2]).intValue(); j++) {
2124
                        aux = appendDatArrays(aux,
2125
                                getNthGroupOfThree(all_elem, j + i));
2126
                    }
2127
2128
                    resp.add(aux);
2129
                    i = i + ((NUMBER) aux[2]).intValue();
2130
                    aux = getNthGroupOfThree(all_elem, i);
2131
                }
2132
                else {
2133
                    if (((NUMBER) newaux[1]).intValue() == 2003) {
2134
                        aux = appendDatArrays(aux, newaux);
2135
                    }
2136
                    else {
2137
                        resp.add(aux);
2138
                        aux = getNthGroupOfThree(all_elem, i);
2139
                    }
2140
                }
2141
2142
                i++;
2143
            }
2144
        }
2145
        catch (SQLException se) {
2146
            logger.error("Unexpected error: " + se.getMessage());
2147
        }
2148
2149
        resp.add(aux);
2150
2151
        return resp.toArray();
2152
    }
2153
2154
    private IGeometry getJGeometryPoint2D(JGeometry _jgeom) {
2155
        Point2D p = _jgeom.getJavaPoint();
2156
        IGeometry ig = ShapeFactory.createPoint2D(p.getX(), p.getY());
2157
2158
        return ig;
2159
    }
2160
2161
    private IGeometry getJGeometryMultiPoint2D(JGeometry _jgeom) {
2162
        Point2D[] pp = _jgeom.getJavaPoints();
2163
        int l = pp.length;
2164
        double[] x = new double[l];
2165
        double[] y = new double[l];
2166
2167
        for (int i = 0; i < l; i++) {
2168
            x[i] = pp[i].getX();
2169
            y[i] = pp[i].getY();
2170
        }
2171
2172
        IGeometry ig = ShapeFactory.createMultipoint2D(x, y);
2173
2174
        return ig;
2175
    }
2176
2177
    private IGeometry getJGeometryOther(JGeometry _jgeom) {
2178
        int type = oracleTypeToFShapeTypeExceptPointTypes(_jgeom.getType());
2179
        Shape shape = _jgeom.createShape();
2180
        GeneralPathX gpx = new GeneralPathX(shape);
2181
        IGeometry ig = null;
2182
2183
        switch (type) {
2184
        case FShape.LINE:
2185
2186
            FPolyline2D fpl = new FPolyline2D(gpx);
2187
            ig = ShapeFactory.createPolyline2D(gpx);
2188
2189
            break;
2190
2191
        case FShape.POLYGON:
2192
2193
            FPolygon2D fpg = new FPolygon2D(gpx);
2194
            ig = ShapeFactory.createPolygon2D(gpx);
2195
2196
            break;
2197
        }
2198
2199
        return ig;
2200
    }
2201
2202
//    private IGeometry getGeotoolsIGeometry(oracle.sql.STRUCT _struct) {
2203
//        Geometry geo_jts = null;
2204
//
2205
//        try {
2206
//            geo_jts = geotools_conv.asGeometry(_struct);
2207
//        }
2208
//        catch (SQLException e) {
2209
//            System.err.println("While using geotools converter: " +
2210
//                e.getMessage());
2211
//        }
2212
//
2213
//        IGeometry ig = FConverter.jts_to_igeometry(geo_jts);
2214
//
2215
//        return ig;
2216
//    }
2217
2218
    private int oracleTypeToFShapeTypeExceptPointTypes(int type) {
2219
        /*
2220
         * Tipos en Oracle Spatial usando JGeometry
2221
         *
2222
         * GTYPE_COLLECTION collection geometry type
2223
         * GTYPE_CURVE curve geoemtry type
2224
         * GTYPE_MULTICURVE multi-curve geometry type
2225
         * GTYPE_MULTIPOINT multi-point geometry type
2226
         * GTYPE_MULTIPOLYGON multi-polygon geometry type
2227
         * GTYPE_POINT point geometry type
2228
         * GTYPE_POLYGON  polygon geometry type
2229
         *
2230
         * Tipos gvSIG FShape
2231
         *
2232
         * NULL = 0;
2233
         * POINT = 1;
2234
         * LINE = 2;
2235
         * POLYGON = 4;
2236
         * TEXT = 8;
2237
         * MULTI = 16;
2238
         * MULTIPOINT = 32;
2239
         * CIRCLE = 64;
2240
         * ARC = 128;
2241
         * ELLIPSE=256;
2242
         * Z=512
2243
         */
2244
        switch (type) {
2245
        case JGeometry.GTYPE_POLYGON:
2246
        case JGeometry.GTYPE_MULTIPOLYGON:
2247
            return FShape.POLYGON;
2248
2249
        case JGeometry.GTYPE_CURVE:
2250
        case JGeometry.GTYPE_MULTICURVE:
2251
            return FShape.LINE;
2252
        }
2253
2254
        System.err.println("Unhandled Oracle Spatial geometry type: " + type +
2255
            " (conversion returned FShape.NULL)");
2256
2257
        return FShape.NULL;
2258
    }
2259
2260
    private void cleanWhereClause() {
2261
        emptyWhereClause = false;
2262
2263
        String aux = getWhereClauseWithoutWhere();
2264
2265
        for (int i = 0; i < aux.length(); i++)
2266
            if (aux.substring(i, i + 1).compareTo(" ") != 0) {
2267
                return;
2268
            }
2269
2270
        getLyrDef().setWhereClause("");
2271
        emptyWhereClause = true;
2272
    }
2273
2274
    private String getValidViewConstructor(
2275
                    STRUCT _st,
2276
                    String ora_srid,
2277
                    boolean _hassrid,
2278
                    boolean _isgeocs) {
2279
2280
            String sdo = getSdoConstructor(_st, _hassrid, _isgeocs);
2281
            String resp = "";
2282
            if ((_hassrid) && (_isgeocs)) {
2283
                    resp = "SDO_CS.VIEWPORT_TRANSFORM( " + sdo + " , " + ora_srid + ")";
2284
            } else {
2285
                    resp = sdo;
2286
            }
2287
2288
            return resp;
2289
    }
2290
2291
    private String getMainSelect(String viewsdo, String idsLoadWhere) {
2292
        String resp = "";
2293
2294
        if (isGeogCS) {
2295
            String vport = "sdo_filter(" + geoColName +
2296
                ", SDO_CS.VIEWPORT_TRANSFORM(" + viewsdo + ", " + oracleSRID +
2297
                "), 'querytype=window') = 'TRUE'";
2298
2299
                resp = "select " + getStandardSelectExpression() + ", c." +
2300
                    geoColName + " from " + getTableName() + " c where ";
2301
                if (idsLoadWhere.length() > 0) {
2302
                        resp = resp + " (" + idsLoadWhere + ") AND ";
2303
                }
2304
                resp = resp + "(" + vport + ")";
2305
        }
2306
        else {
2307
                resp = "select " + getStandardSelectExpression() + ", c." +
2308
                    geoColName + " from " + getTableName() + " c where ";
2309
                if (idsLoadWhere.length() > 0) {
2310
                        resp = resp + " (" + idsLoadWhere + ") AND ";
2311
                }
2312
                resp = resp + "(" + "sdo_relate(" + geoColName + ", " + viewsdo +
2313
                ", 'mask=anyinteract querytype=window') = 'TRUE')";
2314
        }
2315
        return resp;
2316
    }
2317
2318
    public void setWorkingArea(Rectangle2D rect) {
2319
    }
2320
2321
    private void setWAStructt() {
2322
    }
2323
2324
    private Geometry shapeToGeometry(Shape shp) {
2325
        if (shp == null) {
2326
            return null;
2327
        }
2328
2329
        int type = FShape.POLYGON;
2330
2331
        if ((shp instanceof FPolyline2D) && (!(shp instanceof FPolygon2D))) {
2332
            type = FShape.LINE;
2333
        }
2334
2335
        if (shp instanceof FPoint2D) {
2336
            type = FShape.POINT;
2337
        }
2338
2339
        if (shp instanceof FMultiPoint2D) {
2340
            type = FShape.MULTIPOINT;
2341
        }
2342
2343
        GeneralPathX wagp = new GeneralPathX(shp);
2344
        FShapeGeneralPathX fwagp = new FShapeGeneralPathX(wagp, type);
2345
2346
        return FConverter.java2d_to_jts(fwagp);
2347
    }
2348
2349
    public static Rectangle2D getBoundingBox(JGeometry _jg) {
2350
        Shape shape = _jg.createShape();
2351
2352
        return shape.getBounds2D();
2353
    }
2354
2355
    private void printStruct(STRUCT st) {
2356
        System.out.println("----------------------------------------------");
2357
2358
        try {
2359
            Object[] att = st.getAttributes();
2360
            int l = att.length;
2361
2362
            for (int i = 0; i < l; i++) {
2363
                System.out.println("ATT " + i + ": " + att[i].toString());
2364
            }
2365
        }
2366
        catch (Exception ex) {
2367
            System.out.println(
2368
                "- Error ---------------------------------------");
2369
        }
2370
2371
        System.out.println("----------------------------------------------");
2372
    }
2373
2374
    private static STRUCT rectangleToStruct(Rectangle2D r, boolean hasSrid,
2375
        boolean isView, boolean _isGeogCS, String _oracleSRID, Connection __conn) {
2376
        Point2D c1 = new Point2D.Double(r.getMinX(), r.getMinY());
2377
        Point2D c2 = new Point2D.Double(r.getMaxX(), r.getMaxY());
2378
2379
        if ((_isGeogCS) && (isView)) {
2380
            c1.setLocation(Math.max(c1.getX(), -180), Math.max(c1.getY(), -90));
2381
            c2.setLocation(Math.min(c2.getX(), 180), Math.min(c2.getY(), 90));
2382
        }
2383
2384
        STRUCT resp = null;
2385
2386
        try {
2387
            // System.out.println("ABIERTA: " + (!conn.isClosed()));
2388
            // resp = structCreator.toSTRUCT(rect_wkt.getBytes(), conn);
2389
            // Object[] old_obj = resp.getAttributes();
2390
            int size = 5;
2391
            Object[] new_obj = new Object[size];
2392
2393
            // for (int i=0; i<size; i++) new_obj[i] = old_obj[i];
2394
            new_obj[0] = new NUMBER(2003);
2395
2396
            if (hasSrid) {
2397
                new_obj[1] = new NUMBER(_oracleSRID);
2398
            }
2399
            else {
2400
                new_obj[1] = null;
2401
            }
2402
2403
            new_obj[2] = null;
2404
2405
            NUMBER[] elem_info = new NUMBER[3];
2406
            elem_info[0] = new NUMBER(1);
2407
            elem_info[1] = new NUMBER(1003);
2408
            elem_info[2] = new NUMBER(3);
2409
            new_obj[3] = elem_info;
2410
2411
            NUMBER[] ords = null;
2412
            ords = new NUMBER[4];
2413
            ords[0] = new NUMBER(c1.getX());
2414
            ords[1] = new NUMBER(c1.getY());
2415
            ords[2] = new NUMBER(c2.getX());
2416
            ords[3] = new NUMBER(c2.getY());
2417
            new_obj[4] = ords;
2418
2419
            // StructDescriptor dsc = StructDescriptor.createDescriptor("STRUCT", conn);
2420
            StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
2421
                    __conn);
2422
2423
            resp = new STRUCT(dsc, __conn, new_obj);
2424
        }
2425
        catch (Exception ex) {
2426
            logger.error("Error while creating rect struct: " +
2427
                ex.getMessage(), ex);
2428
        }
2429
2430
        return resp;
2431
    }
2432
2433
    private Object[] getViewResultSet(STRUCT geoStruct, String fixsql,
2434
        boolean hasSrid) throws DriverException {
2435
        String sdo_intersect = getSdoConstructor(geoStruct, hasSrid, isGeogCS);
2436
        String main_sel = "";
2437
2438
        if (fixsql == null) {
2439
            // main_sel = getMainSelect3(var_name);
2440
                String idswhere = getIdsQueryWhereClause(false);
2441
            main_sel = getMainSelect(sdo_intersect, idswhere);
2442
        }
2443
        else {
2444
            main_sel = fixsql;
2445
        }
2446
2447
        System.err.println("main sel = " + main_sel);
2448
2449
        ResultSet _rs = null;
2450
        Statement _stmnt = null;
2451
        Object[] _resp = new Object[2];
2452
2453
        try {
2454
            _stmnt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
2455
                    ResultSet.CONCUR_READ_ONLY);
2456
            _stmnt.setFetchDirection(ResultSet.FETCH_FORWARD);
2457
            _stmnt.setFetchSize(FETCH_SIZE);
2458
2459
            _rs = _stmnt.executeQuery(main_sel);
2460
2461
            // stmnt.close();
2462
        }
2463
        catch (SQLException se) {
2464
            logger.error("Tablename: " + getTableName() + ". Error while getting main cursor: " + se.getMessage(),
2465
                se);
2466
            throw new DriverException(se);
2467
        }
2468
2469
        // this method returns the statement too, so that it can be closed afterwards
2470
        _resp[0] = _rs;
2471
        _resp[1] = _stmnt;
2472
2473
        return _resp;
2474
    }
2475
2476
    private String getSdoConstructor(STRUCT geoStruct, boolean hasSrid, boolean _isGeogCS) {
2477
        String resp = "";
2478
2479
        try {
2480
            String mdsys_sdo_elem_info_array = "mdsys.sdo_elem_info_array(1, 1003, 3)";
2481
            String mdsys_sdo_ordinate_array = "";
2482
            Datum[] vertices = ((ARRAY) geoStruct.getOracleAttributes()[4]).getOracleArray();
2483
2484
            for (int i = 0; i < vertices.length; i++) {
2485
                mdsys_sdo_ordinate_array = mdsys_sdo_ordinate_array +
2486
                    vertices[i].doubleValue() + ", ";
2487
            }
2488
2489
            mdsys_sdo_ordinate_array = mdsys_sdo_ordinate_array.substring(0,
2490
                    mdsys_sdo_ordinate_array.length() - 2);
2491
            mdsys_sdo_ordinate_array = "mdsys.sdo_ordinate_array(" +
2492
                mdsys_sdo_ordinate_array + ")";
2493
2494
            String aux = "";
2495
2496
            if (hasSrid) {
2497
                aux = oracleSRID;
2498
2499
                if (_isGeogCS) {
2500
                    aux = "0";
2501
                }
2502
            }
2503
            else {
2504
                aux = "null";
2505
            }
2506
2507
            resp = "mdsys.sdo_geometry(2003, " + aux + ", null, " +
2508
                mdsys_sdo_elem_info_array + ", " + mdsys_sdo_ordinate_array +
2509
                ")";
2510
        }
2511
        catch (Exception ex) {
2512
            System.err.println("Error while getting sdo contructor: " +
2513
                ex.getMessage());
2514
        }
2515
2516
        return resp;
2517
    }
2518
2519
    private String getIdsQueryWhereClause(boolean with_where) {
2520
                String resp = "";
2521
2522
                String _where = "";
2523
                if (with_where) _where = " where ";
2524
2525
                if (workingAreaInTablesCSStruct == null) {
2526
                        if (emptyWhereClause) {
2527
                                // return "select rowid from " + getTableName();
2528
                        } else {
2529
                                resp = resp + _where + "(" + getWhereClauseWithoutWhere()
2530
                                                + ")";
2531
                        }
2532
                } else {
2533
                        String waqry = getValidViewConstructor(workingAreaInTablesCSStruct,
2534
                                        oracleSRID, tableHasSrid, isGeogCS);
2535
2536
                        if (emptyWhereClause) {
2537
                                resp = resp + _where + "(sdo_relate(" + geoColName + ", " + waqry
2538
                                                + ", 'mask=anyinteract querytype=window') = 'TRUE')";
2539
                        } else {
2540
                                resp = resp + _where + "((" + getWhereClauseWithoutWhere()
2541
                                                + ") AND (" + "sdo_relate(" + geoColName + ", " + waqry
2542
                                                + ", 'mask=anyinteract querytype=window') = 'TRUE'))";
2543
                        }
2544
                }
2545
2546
                // resp = resp + " order by rowid";
2547
                return resp;
2548
        }
2549
2550
    public String getIdAndElemInfoFullResulltSetQuery() {
2551
        String resp = "select rowid, c." + geoColName + ".SDO_ELEM_INFO from " +
2552
            getTableName() + " c";
2553
2554
        resp = resp + getIdsQueryWhereClause(true);
2555
        return resp;
2556
    }
2557
2558
    private String getSearchId() {
2559
        if (emptyWhereClause) {
2560
            return "select " + getStandardSelectExpression() + ", c." +
2561
            geoColName + " from " + getTableName() + " c where rowid = ?";
2562
        }
2563
        else {
2564
            return "select " + getStandardSelectExpression() + ", c." +
2565
            geoColName + " from " + getTableName() + " c " + " where " + "((" +
2566
            getWhereClauseWithoutWhere() + ") and (rowid = ?))";
2567
        }
2568
    }
2569
2570
    public int getShapeType() {
2571
        return shapeType;
2572
    }
2573
2574
    private String getWhereClauseWithoutWhere() {
2575
        String resp = "";
2576
        String old = getLyrDef().getWhereClause();
2577
        resp = old;
2578
2579
        if (old.length() <= 6) {
2580
            return old;
2581
        }
2582
2583
        if (old.substring(0, 6).compareToIgnoreCase("where ") == 0) {
2584
            resp = resp.substring(6, resp.length());
2585
        }
2586
2587
        return resp;
2588
    }
2589
2590
    private Rectangle2D doIntersect(Rectangle2D r1, Rectangle2D r2) {
2591
        if (r1.getMaxX() <= r2.getMinX()) {
2592
            return null;
2593
        }
2594
2595
        if (r2.getMaxX() <= r1.getMinX()) {
2596
            return null;
2597
        }
2598
2599
        if (r1.getMaxY() <= r2.getMinY()) {
2600
            return null;
2601
        }
2602
2603
        if (r2.getMaxY() <= r1.getMinY()) {
2604
            return null;
2605
        }
2606
2607
        double minx = Math.max(r1.getMinX(), r2.getMinX());
2608
        double miny = Math.max(r1.getMinY(), r2.getMinY());
2609
        double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
2610
        double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
2611
2612
        double w = maxx - minx;
2613
        double h = maxy - miny;
2614
2615
        return new Rectangle2D.Double(minx, miny, w, h);
2616
    }
2617
2618
    private static int maxSizeForFieldType(int _type) {
2619
        switch (_type) {
2620
        case Types.VARCHAR:
2621
            return OracleSpatialDriver.VARCHAR2_STANDARD_SIZE;
2622
2623
        case Types.LONGVARCHAR:
2624
            return OracleSpatialDriver.VARCHAR2_LONG_SIZE;
2625
        }
2626
2627
        return -1;
2628
    }
2629
2630
    public static String fieldTypeToSqlStringType(FieldDescription fieldDesc) {
2631
        String aux = "VARCHAR2(" + VARCHAR2_STANDARD_SIZE + " BYTE)"; // Por defecto.
2632
2633
        switch (fieldDesc.getFieldType()) {
2634
        case Types.SMALLINT:
2635
            aux = "NUMBER(5, 0)";
2636
2637
            break;
2638
2639
        case Types.INTEGER:
2640
            aux = "NUMBER(10, 0)";
2641
2642
            break;
2643
2644
        case Types.BIGINT:
2645
            aux = "NUMBER(38, 0)";
2646
2647
            break;
2648
2649
        case Types.BOOLEAN:
2650
            aux = "NUMBER(1, 0)";
2651
2652
            break;
2653
2654
        case Types.DECIMAL:
2655
            aux = "NUMBER";
2656
2657
            break;
2658
2659
        case Types.NUMERIC:
2660
            aux = "NUMBER";
2661
2662
            break;
2663
2664
        case Types.DOUBLE:
2665
            aux = "FLOAT";
2666
2667
            break;
2668
2669
        case Types.FLOAT:
2670
            aux = "FLOAT";
2671
2672
            break;
2673
2674
        case Types.CHAR:
2675
            aux = "CHAR(1 BYTE)";
2676
2677
            break;
2678
2679
        case Types.VARCHAR:
2680
            aux = "NVARCHAR2(" + fieldDesc.getFieldLength() + ")";
2681
2682
            break;
2683
2684
        case Types.LONGVARCHAR:
2685
            aux = "NVARCHAR2(" + fieldDesc.getFieldLength() + ")";
2686
2687
            break;
2688
        }
2689
2690
        return aux;
2691
    }
2692
2693
    // -----------------------------------------------------------
2694
    // -----------------------------------------------------------
2695
    public static String getDropTableSql(DBLayerDefinition dbLayerDef) {
2696
        return "DROP TABLE \"" + dbLayerDef.getTableName() +
2697
        "\" CASCADE CONSTRAINTS";
2698
    }
2699
2700
    public static String getTableCreationSql(DBLayerDefinition dbLayerDef) {
2701
        FieldDescription[] flds = dbLayerDef.getFieldsDesc();
2702
2703
        String type = "";
2704
        String name = "";
2705
2706
        String resp = "CREATE TABLE \"" + dbLayerDef.getTableName() + "\" ( ";
2707
2708
        for (int i = 0; i < flds.length; i++) {
2709
            name = flds[i].getFieldName();
2710
2711
            // -------------- FORBIDDEN FIELD NAMES -----------------
2712
            if (!isOracleAllowedFieldname(name)) {
2713
                continue;
2714
            }
2715
2716
            // ------------------------------------------------------
2717
            if (name.compareToIgnoreCase(DEFAULT_GEO_FIELD) == 0) {
2718
            }
2719
            else {
2720
                name = getValidOracleID(name, i);
2721
                resp = resp + "\"" + name + "\" ";
2722
                type = fieldTypeToSqlStringType(flds[i]);
2723
                resp = resp + type + ", ";
2724
            }
2725
        }
2726
2727
        resp = resp + "\"" + DEFAULT_GEO_FIELD + "\" ";
2728
        resp = resp + "\"MDSYS\".\"SDO_GEOMETRY\"";
2729
        resp = resp + ", ";
2730
2731
        String pk = "CONSTRAINT \"" + dbLayerDef.getTableName() +
2732
            "_PK\" PRIMARY KEY (\"" + OracleSpatialDriver.DEFAULT_ID_FIELD +
2733
            "\") ENABLE";
2734
2735
        resp = resp + pk + " )";
2736
2737
        return resp;
2738
    }
2739
2740
    public static String getIndexCreationSql(DBLayerDefinition dbLayerDef) {
2741
        String resp = "CREATE INDEX \"" + dbLayerDef.getTableName() +
2742
            "_SX\" ON \"" + dbLayerDef.getTableName() + "\" (\"" +
2743
            OracleSpatialDriver.DEFAULT_GEO_FIELD +
2744
            "\") INDEXTYPE IS \"MDSYS\".\"SPATIAL_INDEX\" ";
2745
2746
        return resp;
2747
    }
2748
2749
    public static String getRemoveMetadataSql(DBLayerDefinition dbLayerDef) {
2750
        return "DELETE FROM " + ORACLE_GEOMETADATA_VIEW +
2751
        " WHERE TABLE_NAME = '" + dbLayerDef.getTableName() + "'";
2752
    }
2753
2754
    /**
2755
     * UTility method to get the SQL sentence needed to update the geographic metadata table
2756
     * with a new bounding box and SRS
2757
     *
2758
     * @param tName table name
2759
     * @param ora_srid new SRS
2760
     * @param bbox new bounding box
2761
     * @param dim geometries dimension
2762
     * @param withsrid False if the SRS is set to NULL. True otherwise.
2763
     * @return the SQL sentence to perform the update
2764
     */
2765 13995 jldominguez@prodevelop.es
    public static String getMetadataUpdateSql(String schema, String tName, String ora_srid,
2766 13991 jldominguez@prodevelop.es
        Rectangle2D bbox, int dim, boolean withsrid) {
2767
        String[] dim_name = new String[dim];
2768
        double tolerance = 0.5;
2769
2770
        if (ora_srid.compareTo(GEODETIC_SRID) == 0) {
2771
            dim_name[0] = "LONGITUDE";
2772
            dim_name[1] = "LATITUDE";
2773
        }
2774
        else {
2775
            dim_name[0] = "X";
2776
            dim_name[1] = "Y";
2777
2778
            if (dim > 2) {
2779
                dim_name[2] = "Z";
2780
2781
                if (dim > 3) {
2782
                    dim_name[3] = "T";
2783
                }
2784
            }
2785
        }
2786
2787
        String resp = "INSERT INTO " + ORACLE_GEOMETADATA_VIEW + " " +
2788 13995 jldominguez@prodevelop.es
            " ( OWNER, TABLE_NAME, COLUMN_NAME, DIMINFO, SRID ) " + " VALUES ("
2789
            + "'" + schema + "', "
2790
            + "'" + tName + "', "
2791
            + "'" + DEFAULT_GEO_FIELD + "', " +
2792
            "MDSYS.SDO_DIM_ARRAY( " + "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[0] + "', " +
2793 13991 jldominguez@prodevelop.es
            bbox.getMinX() + ", " + bbox.getMaxX() + ", " + tolerance + " ), " +
2794 13995 jldominguez@prodevelop.es
            "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[1] + "', " + bbox.getMinY() + ", " +
2795 13991 jldominguez@prodevelop.es
            bbox.getMaxY() + ", " + tolerance + " ))";
2796
2797
        if (dim > 2) {
2798
            resp = resp.substring(0, resp.length() - 1) + ",";
2799 13995 jldominguez@prodevelop.es
            resp = resp + "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[2] +
2800 13991 jldominguez@prodevelop.es
                "', 0.0, 100.0, " + tolerance + " ))";
2801
2802
            if (dim > 3) {
2803
                resp = resp.substring(0, resp.length() - 1) + ",";
2804 13995 jldominguez@prodevelop.es
                resp = resp + "MDSYS.SDO_DIM_ELEMENT ('" + dim_name[3] +
2805 13991 jldominguez@prodevelop.es
                    "', 0.0, 100.0, " + tolerance + " ))";
2806
            }
2807
        }
2808
2809
        if (withsrid) {
2810
            resp = resp + ", " + ora_srid + " )";
2811
        }
2812
        else {
2813
            resp = resp + ", NULL )";
2814
        }
2815
2816
        return resp;
2817
    }
2818
2819
    /**
2820
     * Gets the SQL sentence to perform an insertion.
2821
     *
2822
     * @param feat feature to be added
2823
     * @param dbLayerDef layer definition
2824
     * @param rowInd row index
2825
     * @param _geoColName geometry field name
2826
     * @return the SQL sentence to perform the insertion
2827
     */
2828
    public static String getRowInsertSql(IFeature feat,
2829
        DBLayerDefinition dbLayerDef, int rowInd, String _geoColName) {
2830
        String name = "";
2831
        int ftype = -1;
2832
        String aux_orig = "";
2833
        String aux_limited = "";
2834
        String aux_quotes_ok = "";
2835
2836
        FieldDescription[] fieldsDescr = dbLayerDef.getFieldsDesc();
2837
2838
        String resp = "INSERT INTO \"" + dbLayerDef.getTableName() + "\" ( ";
2839
2840
        for (int i = 0; i < fieldsDescr.length; i++) {
2841
            name = fieldsDescr[i].getFieldName();
2842
            ftype = fieldsDescr[i].getFieldType();
2843
2844
            // -------------- FORBIDDEN FIELD NAMES & TYPES ---------
2845
            if (!isOracleAllowedFieldname(name)) continue;
2846
            if (!isUserEditableType(ftype, name, _geoColName)) continue;
2847
            // ------------------------------------------------------
2848
            if (name.compareToIgnoreCase(_geoColName) == 0) {
2849
            }
2850
            else {
2851
                name = getValidOracleID(name, i);
2852
                resp = resp + "\"" + name + "\"" + " , ";
2853
            }
2854
        }
2855
2856
        resp = resp + _geoColName + " ) VALUES ( ";
2857
2858
        for (int i = 0; i < fieldsDescr.length; i++) {
2859
            name = fieldsDescr[i].getFieldName();
2860
            ftype = fieldsDescr[i].getFieldType();
2861
2862
            // -------------- FORBIDDEN FIELD NAMES/Types -----------
2863
            if (!isOracleAllowedFieldname(name)) continue;
2864
            if (!isUserEditableType(ftype, name, _geoColName)) continue;
2865
            // ------------------------------------------------------
2866
            String sur = getValueSurroundFromType(fieldsDescr[i]);
2867
2868
            if (name.compareToIgnoreCase(_geoColName) == 0) {
2869
            }
2870
            else {
2871
                if (name.compareToIgnoreCase(
2872
                            OracleSpatialDriver.DEFAULT_ID_FIELD) == 0) {
2873
                    resp = resp + rowInd + " , ";
2874
                }
2875
                else {
2876
                    Value attValue = feat.getAttribute(i);
2877
2878
                    if (attValue.toString() == null) {
2879
                        resp = resp + "NULL , ";
2880
                    }
2881
                    else {
2882
                        if (sur.length() > 0) {
2883
                            aux_orig = attValue.toString();
2884
                            aux_limited = cropStringValue(aux_orig, i,
2885
                                    fieldsDescr);
2886
                            aux_quotes_ok = avoidQuoteProblem(aux_limited);
2887
2888
                            resp = resp + sur + aux_quotes_ok + sur + " , ";
2889
                        }
2890
                        else {
2891
                            String _aux = attValue.toString();
2892
2893
                            if (_aux.length() == 0) {
2894
                                _aux = "NULL";
2895
                            }
2896
2897
                            resp = resp + _aux + " , ";
2898
                        }
2899
                    }
2900
                }
2901
            }
2902
        }
2903
2904
        resp = resp + " ? )";
2905
2906
        return resp;
2907
    }
2908
2909
    private static boolean isUserEditableType(int ftype, String item_name, String geo_name) {
2910
2911
            if (item_name.compareToIgnoreCase(geo_name) == 0) {
2912
                    return true;
2913
            }
2914
2915
            if ((ftype == Types.BINARY)
2916
                || (ftype == Types.ARRAY)
2917
                || (ftype == Types.BLOB)
2918
                || (ftype == Types.CLOB)
2919
                || (ftype == Types.STRUCT)
2920
            ) {
2921
                    return false;
2922
            }
2923
                return true;
2924
        }
2925
2926
        /**
2927
     * Gets the SQL sentence to perform an update.
2928
     *
2929
     * @param feat feature to be updated
2930
     * @param dbLayerDef layer definition
2931
     * @param rowInd row index
2932
     * @param geoFieldName geometry field name
2933
     * @return the SQL sentence to perform the update
2934
     */
2935
    public static String getRowUpdateSql(IFeature feat,
2936
        DBLayerDefinition dbLayerDef, int rowInd, String geoFieldName) {
2937
        String name = "";
2938
        String aux_orig = "";
2939
        String aux_limited = "";
2940
        String aux_quotes_ok = "";
2941
2942
        Value[] atts = feat.getAttributes();
2943
        FieldDescription[] _fieldsDescr = dbLayerDef.getFieldsDesc();
2944
2945
        String resp = "UPDATE \"" + dbLayerDef.getTableName() + "\" SET ";
2946
2947
        for (int i = 0; i < _fieldsDescr.length; i++) {
2948
            name = _fieldsDescr[i].getFieldName();
2949
2950
            // -------------- FORBIDDEN FIELD NAMES -----------------
2951
            if (!isOracleAllowedFieldname(name)) {
2952
                logger.info("Field: " + name + " will not be updated.");
2953
                continue;
2954
            }
2955
2956
            if (isStructAndNotGeoField(_fieldsDescr[i].getFieldType(), name,
2957
                        geoFieldName)) {
2958
                logger.info("Field: " + name + " will not be updated (it's a struct).");
2959
                continue;
2960
            }
2961
2962
            // ------------------------------------------------------
2963
            if (name.compareToIgnoreCase(geoFieldName) == 0) {
2964
                // resp = resp + "\"" + name + "\"" + " = ?, ";
2965
            }
2966
            else {
2967
                String sur = getValueSurroundFromType(_fieldsDescr[i]);
2968
                aux_orig = atts[i].toString();
2969
                aux_limited = cropStringValue(aux_orig, i, _fieldsDescr);
2970
                aux_quotes_ok = avoidQuoteProblem(aux_limited);
2971
                resp = resp + "\"" + name + "\"" + " = " + sur + aux_quotes_ok +
2972
                    sur + ", ";
2973
            }
2974
        }
2975
2976
        resp = resp + "\"" + geoFieldName + "\" = ?";
2977
        resp = resp + " WHERE ROWID ='" + feat.getID() + "'";
2978
2979
        return resp;
2980
    }
2981
2982
    private static boolean isStructAndNotGeoField(int ftype, String fldname,
2983
        String geoname) {
2984
        if (ftype == Types.STRUCT) {
2985
            if (fldname.compareToIgnoreCase(geoname) != 0) {
2986
                return true;
2987
            }
2988
        }
2989
2990
        return false;
2991
    }
2992
2993
    /**
2994
     * Gets the SQL sentence to perform a deletion.
2995
     *
2996
     * @param dbLayerDef layer definition
2997
     * @param id ROWID of the record to be deleted
2998
     * @return the SQL sentence to perform the deletion
2999
     */
3000
    public static String getRowDeleteSql(DBLayerDefinition dbLayerDef, String id) {
3001
        String resp = "DELETE FROM \"" + dbLayerDef.getTableName() + "\"";
3002
        resp = resp + " WHERE ROWID ='" + id + "'";
3003
3004
        return resp;
3005
    }
3006
3007
    private static String cropStringValue(String orig_val, int i,
3008
        FieldDescription[] _flds) {
3009
        if (orig_val == null) {
3010
            return "NULL";
3011
        }
3012
3013
        int tpe = _flds[i].getFieldType();
3014
        int max_size = maxSizeForFieldType(tpe);
3015
3016
        if (max_size == -1) {
3017
            return orig_val;
3018
        }
3019
3020
        int or_size = orig_val.length();
3021
3022
        if (or_size <= max_size) {
3023
            return orig_val;
3024
        }
3025
3026
        return orig_val.substring(0, max_size);
3027
    }
3028
3029
    private static String avoidQuoteProblem(String str) {
3030
        return str.replaceAll("'", "''");
3031
    }
3032
3033
    private static String getValueSurroundFromType(FieldDescription fieldDesc) {
3034
        if (NumberUtilities.isNumeric(fieldDesc.getFieldType())) {
3035
            return "";
3036
        }
3037
3038
        return "'";
3039
    }
3040
3041
    /**
3042
     * Utility function to translate a SRS code from EPSG to Oracle.
3043
     * Uses a datasource based on a DBF file.
3044
     *
3045
     * @param epsg the EPSG code
3046
     * @return the Oracle code
3047
     */
3048
    public static String epsgSridToOracleSrid(String epsg) throws Exception {
3049
        String resp = "8307";
3050
3051
        // --------------------------------------------
3052
        String sql = "select ORACLE from " + ORACLE_EPSG_TABLE_NAME +
3053
            " where EPSG = " + epsg + " and PRF_ORACLE = 1;";
3054
        DataSource ds = null;
3055
3056
        try {
3057
            ds = LayerFactory.getDataSourceFactory()
3058
                             .executeSQL(sql,
3059
                    DataSourceFactory.AUTOMATIC_OPENING); //.MANUAL_OPENING);
3060
3061
            if (ds.getRowCount() == 0) {
3062
                logger.error("EPSG code not found in table: " + epsg);
3063
                throw new Exception("Unknown EPSG: " + epsg);
3064
            }
3065
3066
            if (ds.getRowCount() > 1) {
3067
                logger.error("===============");
3068
                logger.error(
3069
                    "DBF file is wrong: More than one preferred Oracle Spatial code found for EPSG code: " +
3070
                    epsg);
3071
3072
                for (int i = 0; i < ds.getRowCount(); i++) {
3073
                    int aux = (int) Math.round(((DoubleValue) ds.getRow(i)[0]).doubleValue());
3074
3075
                    if (i == 0) {
3076
                        resp = "" + aux;
3077
                    }
3078
3079
                    logger.error("" + aux);
3080
                }
3081
3082
                logger.error("===============");
3083
3084
                return resp;
3085
            }
3086
3087
            resp = "" +
3088
                Math.round(((DoubleValue) ds.getRow(0)[0]).doubleValue());
3089
        }
3090
        catch (Exception pe) {
3091
            logger.error("Error with SQL statement. " + pe.getMessage());
3092
        }
3093
3094
        return resp;
3095
    }
3096
3097
    /**
3098
     * Utility function to translate a SRS code from Oracle to EPSG.
3099
     * Uses a datasource based on a DBF file.
3100
     *
3101
     * @param ora the Oracle code
3102
     * @return the EPSG code
3103
     */
3104
    public static String oracleSridToEpsgSrid(String ora) throws Exception {
3105
        String resp = "4326";
3106
3107
        // --------------------------------------------
3108
        String sql = "select EPSG from " + ORACLE_EPSG_TABLE_NAME +
3109
            " where ORACLE = " + ora + ";";
3110
        DataSource ds = null;
3111
3112
        try {
3113
            ds = LayerFactory.getDataSourceFactory()
3114
                             .executeSQL(sql,
3115
                    DataSourceFactory.AUTOMATIC_OPENING);
3116
3117
            if (ds.getRowCount() == 0) {
3118
                logger.error("Oracle Spatial code not found in table: " + ora);
3119
                throw new Exception("Unknown Oracle code: " + ora);
3120
            }
3121
3122
            if (ds.getRowCount() > 1) {
3123
                logger.error("===============");
3124
                logger.error(
3125
                    "DBF file is wrong: More than one EPSG code found for Oracle Spatial code: " +
3126
                    ora);
3127
3128
                for (int i = 0; i < ds.getRowCount(); i++) {
3129
                    String aux = "" +
3130
                        Math.round(((DoubleValue) ds.getRow(i)[0]).doubleValue());
3131
3132
                    if (i == 0) {
3133
                        resp = aux;
3134
                    }
3135
3136
                    logger.error("" + aux);
3137
                }
3138
3139
                logger.error("===============");
3140
3141
                return resp;
3142
            }
3143
3144
            resp = "" +
3145
                Math.round(((DoubleValue) ds.getRow(0)[0]).doubleValue());
3146
        }
3147
        catch (Exception pe) {
3148
            logger.error("Error with SQL statement. " + pe.getMessage());
3149
        }
3150
3151
        return resp;
3152
    }
3153
3154
    /**
3155
     * This methos creates the datasource used to translate the SRS codes:
3156
     * EPSG <--> Oracle.
3157
     *
3158
     * It's called from several places, so checks that the datasource does not exist.
3159
     */
3160
    public static void createOracleEpsgTable() {
3161
        SourceInfo si = LayerFactory.getDataSourceFactory()
3162
                                    .getDriverInfo(ORACLE_EPSG_TABLE_NAME);
3163
3164
        if (si != null) { // already created, nothing done
3165
            return;
3166
        }
3167
3168
        // Create 'oracle codes - epsg codes' table
3169
        DBFDriver dbfdrv = new DBFDriver();
3170
3171
        // dbfdrv.setDataSourceFactory()
3172
        OFileDataSourceAdapter fdsa = new OFileDataSourceAdapter();
3173
3174
        fdsa.setDriver(dbfdrv);
3175
3176
        // ---------------------------------------------
3177
        FileSourceInfo fsi = new FileSourceInfo();
3178
        fsi.file = createFileString("dbf/" + ORACLE_EPSG_FILE_NAME);
3179
        fsi.spatial = false;
3180
        fsi.name = ORACLE_EPSG_TABLE_NAME;
3181
        fsi.driverName = dbfdrv.getName(); //"DBF Driver";
3182
                                           // ---------------------------------------------
3183
3184
        fdsa.setSourceInfo(fsi);
3185
3186
        SelectableDataSource sds = null;
3187
        EditableAdapter ea = new EditableAdapter();
3188
        ProjectTable pt = null;
3189
3190
        try {
3191
            sds = new SelectableDataSource(fdsa);
3192
            ea.setOriginalDataSource(sds);
3193
            pt = ProjectTableFactory.createTable(ORACLE_EPSG_TABLE_NAME, ea);
3194
        }
3195
        catch (Exception ex) {
3196
            System.err.println("While creating datasource: " + ex.getMessage());
3197
        }
3198
3199
        sds.setSourceInfo(fsi);
3200
3201
        DataSourceFactory dsf = LayerFactory.getDataSourceFactory();
3202
        dsf.addFileDataSource(fsi.driverName, fsi.name, fsi.file);
3203
        sds.setDataSourceFactory(dsf);
3204
    }
3205
3206
    private static String createFileString(String path) {
3207
        try {
3208
            File f = new File(
3209
                    "./gvSIG/extensiones/" + EXTENSION_DIR_NAME + "/" +
3210
                    path);
3211
3212
            return f.getCanonicalPath();
3213
        }
3214
        catch (Exception ex) {
3215
            return "./gvSIG/extensiones/" + EXTENSION_DIR_NAME + "/" +
3216
            path;
3217
        }
3218
    }
3219
3220
    /**
3221
     * Utility method to get a valid Oracle identifier (in terms of length)
3222
     *
3223
     * @param str Proposed string
3224
     * @param ind field index of the given field name (used by the method to
3225
     * improve the renaming)
3226
     * @return an acceptable oracle identifier.
3227
     */
3228
    public static String getValidOracleID(String str, int ind) {
3229
        if (str.length() <= MAX_ID_LENGTH) {
3230
            return str;
3231
        }
3232
3233
        String resp = str.substring(0, MAX_ID_LENGTH - 7);
3234
        resp = resp + str.substring(MAX_ID_LENGTH - 6, MAX_ID_LENGTH - 5);
3235
        resp = resp + str.substring(MAX_ID_LENGTH - 4, MAX_ID_LENGTH - 3);
3236
        resp = resp + str.substring(MAX_ID_LENGTH - 2, MAX_ID_LENGTH - 1);
3237
        resp = resp + "_" + (ind % 1000);
3238
3239
        return resp;
3240
    }
3241
3242
    private static ArrayList ensureSensibleShell(ArrayList cc) {
3243
        if (sameCoordinate((Coordinate) cc.get(0),
3244
                    (Coordinate) cc.get(cc.size() - 1))) {
3245
            if (cc.size() == 2) {
3246
                ArrayList resp = new ArrayList();
3247
                resp.add(cc.get(0));
3248
3249
                Coordinate newcoo = new Coordinate((Coordinate) cc.get(0));
3250
                newcoo.x = newcoo.x + IRRELEVANT_DISTANCE;
3251
                resp.add(newcoo);
3252
3253
                newcoo = new Coordinate((Coordinate) cc.get(0));
3254
                newcoo.x = newcoo.x + IRRELEVANT_DISTANCE;
3255
                newcoo.y = newcoo.y - IRRELEVANT_DISTANCE;
3256
                resp.add(newcoo);
3257
3258
                resp.add(cc.get(0));
3259
3260
                return resp;
3261
            }
3262
3263
            if (cc.size() == 3) {
3264
                cc.remove(1);
3265
3266
                return ensureSensibleShell(cc);
3267
            }
3268
3269
            return cc;
3270
        }
3271
        else {
3272
            cc.add(cc.get(0));
3273
3274
            return cc;
3275
        }
3276
    }
3277
3278
    private static ArrayList ensureSensibleHole(ArrayList cc) {
3279
        if (sameCoordinate((Coordinate) cc.get(0),
3280
                    (Coordinate) cc.get(cc.size() - 1))) {
3281
            if (cc.size() == 2) {
3282
                ArrayList resp = new ArrayList();
3283
                resp.add(cc.get(0));
3284
3285
                Coordinate newcoo = new Coordinate((Coordinate) cc.get(0));
3286
                newcoo.x = newcoo.x - IRRELEVANT_DISTANCE;
3287
                resp.add(newcoo);
3288
3289
                newcoo = new Coordinate((Coordinate) cc.get(0));
3290
                newcoo.x = newcoo.x - IRRELEVANT_DISTANCE;
3291
                newcoo.y = newcoo.y + IRRELEVANT_DISTANCE;
3292
                resp.add(newcoo);
3293
3294
                resp.add(cc.get(0));
3295
3296
                return resp;
3297
            }
3298
3299
            if (cc.size() == 3) {
3300
                cc.remove(1);
3301
3302
                return ensureSensibleHole(cc);
3303
            }
3304
3305
            return cc;
3306
        }
3307
        else {
3308
            cc.add(cc.get(0));
3309
3310
            return cc;
3311
        }
3312
    }
3313
3314
    private static ArrayList ensureSensibleLineString(ArrayList cc) {
3315
        if (cc.size() == 2) {
3316
            if (sameCoordinate((Coordinate) cc.get(0),
3317
                        (Coordinate) cc.get(cc.size() - 1))) {
3318
                ArrayList resp = new ArrayList();
3319
                resp.add(cc.get(0));
3320
3321
                Coordinate newc = new Coordinate((Coordinate) cc.get(0));
3322
                newc.x = newc.x + IRRELEVANT_DISTANCE;
3323
                resp.add(newc);
3324
3325
                return resp;
3326
            }
3327
        }
3328
3329
        return cc;
3330
    }
3331
3332
    private static boolean sameCoordinate(Coordinate c1, Coordinate c2) {
3333
        if (c1.x != c2.x) {
3334
            return false;
3335
        }
3336
3337
        if (c1.y != c2.y) {
3338
            return false;
3339
        }
3340
3341
        return true;
3342
    }
3343
3344
    private static ArrayList getClosedRelevantPolygon(ArrayList cc) {
3345
        if (cc.size() == 2) {
3346
            return null;
3347
        }
3348
3349
        if (cc.size() == 3) {
3350
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1))) {
3351
                return null;
3352
            }
3353
3354
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2))) {
3355
                return null;
3356
            }
3357
3358
            if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2))) {
3359
                return null;
3360
            }
3361
3362
            cc.add(cc.get(0));
3363
3364
            return cc;
3365
        }
3366
3367
        if (!sameCoordinate((Coordinate) cc.get(0),
3368
                    (Coordinate) cc.get(cc.size() - 1))) {
3369
            cc.add(cc.get(0));
3370
        }
3371
3372
        return cc;
3373
    }
3374
3375
    private static MultiPolygon getMinMultiPolygon(Coordinate c) {
3376
        Coordinate[] p = new Coordinate[4];
3377
        p[0] = c;
3378
3379
        Coordinate nc = new Coordinate(c);
3380
        nc.x = nc.x + IRRELEVANT_DISTANCE;
3381
3382
        Coordinate nc2 = new Coordinate(nc);
3383
        nc2.y = nc2.y - IRRELEVANT_DISTANCE;
3384
        p[1] = nc;
3385
        p[2] = nc2;
3386
        p[3] = new Coordinate(c);
3387
3388
        CoordinateArraySequence cs = new CoordinateArraySequence(p);
3389
        LinearRing ls = new LinearRing(cs, geomFactory);
3390
        Polygon po = new Polygon(ls, null, geomFactory);
3391
        Polygon[] pos = new Polygon[1];
3392
        pos[0] = po;
3393
3394
        MultiPolygon mpo = new MultiPolygon(pos, geomFactory);
3395
3396
        return mpo;
3397
    }
3398
3399
    public String getSourceProjection() {
3400
        // TODO Auto-generated method stub
3401
        if (tableHasSrid) {
3402
            return epsgSRID;
3403
        }
3404
3405
        return destProj;
3406
    }
3407
3408
    public String getDestProjection() {
3409
        return destProj;
3410
    }
3411
3412
    public void setDestProjection(String toEPSG) {
3413
        destProj = toEPSG;
3414
        try {
3415
                        destProjOracle = epsgSridToOracleSrid(destProj);
3416
                        isDestGeogCS = getIsGCS(destProjOracle, true);
3417
3418
                } catch (Exception e) {
3419
                        logger.error("Unknown EPSG code: " + destProj);
3420
                        destProjOracle = oracleSRID;
3421
                        isDestGeogCS = false;
3422
                }
3423
3424
    }
3425
3426
    public String getDestProjectionOracleCode() {
3427
            return destProjOracle;
3428
    }
3429
3430
    public boolean getIsDestProjectionGeog() {
3431
            return isDestGeogCS;
3432
    }
3433
3434
    public String getTableProjectionOracleCode() {
3435
            return oracleSRID;
3436
    }
3437
3438
    public boolean canReproject(String toEPSGdestinyProjection) {
3439
        return false;
3440
    }
3441
3442
    /**
3443
     * Utility function. Says whether a given field name can be a user field name
3444
     * or not (for example, "ROWID" is not a valid one because it's a system
3445
     * reserved word).
3446
     *
3447
     * @param str proposed firld name
3448
     * @return whether it is valid or not for Oracle databases
3449
     */
3450
    private static boolean isOracleAllowedFieldname(String str) {
3451
        if (str.compareToIgnoreCase("rowid") == 0) {
3452
            return false;
3453
        }
3454
3455
        if (str.compareToIgnoreCase("rownum") == 0) {
3456
            return false;
3457
        }
3458
3459
        return true;
3460
    }
3461
3462
    public Hashtable getHashRelate() {
3463
        return hashRelate;
3464
    }
3465
3466
    public void setHashRelate(Hashtable m) {
3467
        hashRelate = m;
3468
    }
3469
3470
    public void setNumReg(int n) {
3471
        numReg = n;
3472
    }
3473
3474
    private int[] getRandomSample(int maxn_one_based, int n) {
3475
        int[] resp = new int[n];
3476
3477
        if (maxn_one_based <= n) {
3478
            resp = new int[maxn_one_based];
3479
3480
            for (int i = 0; i < maxn_one_based; i++) {
3481
                resp[i] = i;
3482
            }
3483
        }
3484
        else {
3485
            Random rnd = new Random();
3486
3487
            for (int i = 0; i < n; i++) {
3488
                resp[i] = rnd.nextInt(maxn_one_based);
3489
            }
3490
        }
3491
3492
        return resp;
3493
    }
3494
3495
    private String getRowIdRestrictionCondition(int nrecords) {
3496
        int[] zero_based_rows = getRandomSample(nrecords,
3497
                GEODETIC_FULLEXTENT_SAMPLE_SIZE);
3498
        String resp = "(";
3499
        Object aux = "";
3500
        ROWID riaux = null;
3501
3502
        for (int i = 0; i < zero_based_rows.length; i++) {
3503
            aux = rowToId.get(new Integer(zero_based_rows[i]));
3504
            riaux = (ROWID) aux;
3505
            resp = resp + "(ROWID = '" + riaux.stringValue() + "') OR ";
3506
        }
3507
3508
        resp = resp.substring(0, resp.length() - 4);
3509
        resp = resp + ")";
3510
3511
        return resp;
3512
    }
3513
3514
    private Rectangle2D getBoundingFromSample(int n_max) {
3515
        String _qry = "SELECT " + geoColName + " FROM " + getTableName() +
3516
            " WHERE " + getRowIdRestrictionCondition(n_max);
3517
        STRUCT auxstr = null;
3518
        IGeometry theGeom = null;
3519
        Rectangle2D resp = null;
3520
3521
        try {
3522
            Statement st = conn.createStatement();
3523
            ResultSet rs = st.executeQuery(_qry);
3524
3525
            if (rs.next()) {
3526
                auxstr = (STRUCT) rs.getObject(1);
3527
3528
                if (auxstr != null) {
3529
                    theGeom = getGeometryUsing(auxstr, use_geotools);
3530
3531
                    if (resp == null) {
3532
                        resp = theGeom.getBounds2D();
3533
                    }
3534
                    else {
3535
                        resp.add(theGeom.getBounds2D());
3536
                    }
3537
                }
3538
3539
                while (rs.next()) {
3540
                    auxstr = (STRUCT) rs.getObject(1);
3541
3542
                    if (auxstr != null) {
3543
                        theGeom = getGeometryUsing(auxstr, use_geotools);
3544
3545
                        if (resp == null) {
3546
                            resp = theGeom.getBounds2D();
3547
                        }
3548
                        else {
3549
                            resp.add(theGeom.getBounds2D());
3550
                        }
3551
                    }
3552
                }
3553
3554
                rs.close();
3555
                st.close();
3556
            }
3557
            else {
3558
                throw new SQLException("Empty resultset from this query: " +
3559
                    _qry);
3560
            }
3561
        }
3562
        catch (SQLException se) {
3563
            System.err.println("Error while getting sample full extent: " +
3564
                se.getMessage());
3565
        }
3566
3567
        if (resp == null) {
3568
            logger.warn(
3569
                "Did not find a geometry to compute sample bbox. Returned geographic bbox for whole world.");
3570
3571
            return new Rectangle2D.Double(-180, -90, 360, 180);
3572
        }
3573
3574
        return resp;
3575
    }
3576
3577
    /**
3578
     * Does what it says, puts the LinearRing in counter clock wise
3579
     * order.
3580
     * @param ls The ring to set.
3581
     * @param gf a GeometryFactory object
3582
     * @return A new ring in CCW order.
3583
     *
3584
     */
3585
    public static LinearRing putInCCWOrderLR(LineString ls, GeometryFactory gf) {
3586
        Coordinate[] cc = ls.getCoordinates();
3587
3588
        if (CGAlgorithms.isCCW(cc)) {
3589
            return gf.createLinearRing(cc);
3590
        }
3591
        else {
3592
            if (ls instanceof LinearRing) {
3593
                return reverseRing((LinearRing) ls, gf);
3594
            }
3595
            else {
3596
                return reverseLineString(ls, gf);
3597
            }
3598
        }
3599
    }
3600
3601
    /**
3602
     * Does what it says, reverses the order of the Coordinates in the ring.
3603
     * @param lr The ring to reverse.
3604
     * @return A new ring with the reversed Coordinates.
3605
     *
3606
     */
3607
    public static LinearRing reverseRing(LinearRing lr, GeometryFactory gf) {
3608
        int numPoints = lr.getNumPoints() - 1;
3609
        Coordinate[] newCoords = new Coordinate[numPoints + 1];
3610
3611
        for (int t = numPoints; t >= 0; t--) {
3612
            newCoords[t] = lr.getCoordinateN(numPoints - t);
3613
        }
3614
3615
        return gf.createLinearRing(newCoords);
3616
    }
3617
3618
    /**
3619
     * Does what it says, reverses the order of the Coordinates in the linestring.
3620
     * @param ls The ls to reverse.
3621
     * @param gf a GeometryFactory object
3622
     * @return A new ls with the reversed Coordinates.
3623
     *
3624
     */
3625
    public static LinearRing reverseLineString(LineString ls, GeometryFactory gf) {
3626
        int numPoints = ls.getNumPoints() - 1;
3627
        Coordinate[] newCoords = new Coordinate[numPoints + 1];
3628
3629
        for (int t = numPoints; t >= 0; t--) {
3630
            newCoords[t] = ls.getCoordinateN(numPoints - t);
3631
        }
3632
3633
        return gf.createLinearRing(newCoords);
3634
    }
3635
3636
    private static Geometry putInCCWOrder(Geometry ge, GeometryFactory gf) {
3637
        if (ge instanceof MultiPolygon) {
3638
            MultiPolygon mp = (MultiPolygon) ge;
3639
            int size = ge.getNumGeometries();
3640
            Polygon[] pols = new Polygon[size];
3641
3642
            for (int i = 0; i < size; i++)
3643
                pols[i] = (Polygon) putInCCWOrder((Polygon) mp.getGeometryN(i),
3644
                        gf);
3645
3646
            return new MultiPolygon(pols, gf);
3647
        }
3648
        else {
3649
            if (ge instanceof Polygon) {
3650
                Polygon p = (Polygon) ge;
3651
                LinearRing exterior = putInCCWOrderLR(p.getExteriorRing(), gf);
3652
                int nholes = p.getNumInteriorRing();
3653
3654
                if (nholes > 0) {
3655
                    LinearRing[] holes = new LinearRing[nholes];
3656
3657
                    for (int i = 0; i < nholes; i++) {
3658
                        holes[i] = putInCCWOrderLR(p.getInteriorRingN(i), gf);
3659
                    }
3660
3661
                    return gf.createPolygon(exterior, holes);
3662
                }
3663
                else {
3664
                    return gf.createPolygon(exterior, null);
3665
                }
3666
            }
3667
            else {
3668
                return ge;
3669
            }
3670
        }
3671
    }
3672
3673
    /**
3674
     * Converts from IGeometry to STRUCT
3675
     *
3676
     * @param ig the geometry to convert
3677
     * @param _forced_type forced type to use
3678
     * @param _conn connection
3679
     * @param _o_srid  SRS (oracle code)
3680
     * @param withSrid whether this STRUCT has a non-NULL SRS
3681
     * @param agu_bien whether or not to check the correctness of the holes
3682
     * @param _isGeoCS whether the SRS is geodetic or not
3683
     * @return the generated STRUCT
3684
     */
3685
    public static STRUCT iGeometryToSTRUCT(IGeometry ig, int _forced_type,
3686
        Connection _conn, String _o_srid, boolean withSrid, boolean agu_bien,
3687
        boolean _isGeoCS) {
3688
        if (ig instanceof FGeometryCollection) {
3689
            FGeometryCollection coll = (FGeometryCollection) ig;
3690
3691
            return OracleSpatialUtils.appendGeometriesInStruct(coll,
3692
                _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS);
3693
3694
            // logger.error("Collections no soportadas por ahora.");
3695
            // return null;
3696
        }
3697
        else {
3698
            Shape shp = ig.getInternalShape();
3699
3700
            return shapeToStruct(shp, _forced_type, _conn, _o_srid, withSrid,
3701
                agu_bien, false, _isGeoCS);
3702
        }
3703
    }
3704
3705
    public STRUCT shapeToStruct(Shape shp, int force_type, boolean hasSrid,
3706
        boolean agu_bien, boolean isView) {
3707
3708
            if (shp == null) return null;
3709
        return shapeToStruct(shp, force_type, conn, oracleSRID, hasSrid,
3710
            agu_bien, isView, isGeogCS);
3711
    }
3712
3713
    public static STRUCT shapeToStruct(Shape shp, int forced_type,
3714
        Connection _conn, String o_srid, boolean hasSrid, boolean agu_bien,
3715
        boolean isView, boolean _isGeoCS) {
3716
        int _srid = -1;
3717
3718
        if (o_srid.length() > 0) {
3719
            _srid = Integer.parseInt(o_srid);
3720
        }
3721
3722
        if (shp == null) {
3723
            logger.info("Shape is null. shapeToStruct(Shape) returned null.");
3724
3725
            return null;
3726
        }
3727
3728
        if (shp instanceof Rectangle2D) {
3729
            return rectangleToStruct((Rectangle2D) shp, hasSrid, isView,
3730
                _isGeoCS, o_srid, _conn);
3731
        }
3732
3733
        try {
3734
            STRUCT the_struct = OracleSpatialUtils.fShapeToSTRUCT(shp, _conn,
3735
                    _srid, agu_bien, hasSrid);
3736
3737
            return the_struct;
3738
        }
3739
        catch (SQLException ex) {
3740
            logger.error("While creating STRUCT: " + ex.getMessage());
3741
3742
            return null;
3743
        }
3744
    }
3745
3746
    // -------------------------- not ready yet ----------------
3747
    public int getRowIndexByFID(IFeature _fid) {
3748
        if (isNotAvailableYet) {
3749
            return -1;
3750
        }
3751
        else {
3752
            return super.getRowIndexByFID(_fid);
3753
        }
3754
    }
3755
3756
    public int getShapeCount() throws IOException {
3757
        if (isNotAvailableYet) {
3758
            return 0;
3759
        }
3760
        else {
3761
            return numReg;
3762
        }
3763
    }
3764
3765
    public void setNotAvailableYet(boolean nav) {
3766
        isNotAvailableYet = nav;
3767
    }
3768
3769
    // -------------------------------------------------------
3770
    // -------------------------------------------------------
3771
    public String[] getTableNames(Connection conn, String catalog)
3772
        throws SQLException {
3773
        DatabaseMetaData dbmd = conn.getMetaData();
3774
        String[] types = { "TABLE", "VIEW" };
3775 13995 jldominguez@prodevelop.es
        // String[] types = { "VIEW" };
3776 13991 jldominguez@prodevelop.es
3777
        ResultSet rs = null;
3778
        rs = getTableNamesFromTable(dbmd.getTables(catalog, ORACLE_GEO_SCHEMA,
3779
                    ORACLE_GEOMETADATA_VIEW, types), conn);
3780 13993 fran.penarrubia@iver.es
//        rs = dbmd.getTables(catalog, ORACLE_GEO_SCHEMA,
3781
//                          ORACLE_GEOMETADATA_VIEW, types);
3782 13991 jldominguez@prodevelop.es
        TreeMap ret = new TreeMap();
3783
3784
        while (rs.next()) {
3785 13994 fran.penarrubia@iver.es
                String nomCompleto = rs.getString("OWNER") + "." +rs.getString("TABLE_NAME");
3786
            ret.put(nomCompleto, nomCompleto);
3787 13991 jldominguez@prodevelop.es
        }
3788
3789
        return (String[]) ret.keySet().toArray(new String[0]);
3790
    }
3791
3792
    private ResultSet getTableNamesFromTable(ResultSet res, Connection con)
3793
        throws SQLException {
3794
        String tablename = "";
3795
3796
3797
3798
        if (res.next()) {
3799
            tablename = res.getString("TABLE_NAME");
3800
3801
            // debug
3802
            // writeMetaTableToLog(con, tablename);
3803
3804
            Statement __st = con.createStatement();
3805
3806
            String sql = "(" + "(select TABLE_NAME from USER_TABLES) " +
3807
                "union (select VIEW_NAME from USER_VIEWS)) " +
3808
                "intersect (select TABLE_NAME from " + tablename + ")";
3809 13994 fran.penarrubia@iver.es
            sql = "SELECT TABLE_NAME, OWNER FROM " + tablename + "";
3810 13991 jldominguez@prodevelop.es
            ResultSet rs = __st.executeQuery(sql);
3811
3812
            return rs;
3813
        }
3814
        else {
3815
            logger.error("Error while getting geometry tables.");
3816
3817
            return null;
3818
        }
3819
    }
3820
3821
    private void writeMetaTableToLog(Connection con, String tname) {
3822
3823
            logger.debug("======================================================");
3824
            logger.debug("=     USER_SDO_GEOM_METADATA     =====================");
3825
            logger.debug("======================================================");
3826
3827
            try {
3828
            Statement _stmt = con.createStatement();
3829
            String sql = "SELECT * FROM " + tname;
3830
            ResultSet res = _stmt.executeQuery(sql);
3831
            while (res.next()) {
3832
                    logger.debug("======================================================");
3833
                    logger.debug("TABLE_NAME: " + res.getString("TABLE_NAME"));
3834
                    logger.debug("COLUMN_NAME: " + res.getString("COLUMN_NAME"));
3835
                    logger.debug("SRID: " + res.getString("SRID"));
3836
3837
                    ARRAY _aux = (ARRAY) res.getObject("DIMINFO");
3838
                    String dinfo = OracleSpatialUtils.getDimInfoAsString(_aux);
3839
                    logger.debug("DIMINFO: " + dinfo);
3840
                    logger.debug("======================================================");
3841
3842
            }
3843
            } catch (Throwable th) {
3844
3845
            }
3846
3847
3848
3849
3850
3851
                // TODO Auto-generated method stub
3852
3853
        }
3854
3855
        /**
3856
     * Gets the field names that can act as row id (always ROWID)
3857
     */
3858
    public String[] getIdFieldsCandidates(Connection conn, String table_name)
3859
        throws SQLException {
3860 13995 jldominguez@prodevelop.es
3861
            String rowid_avail_test = "SELECT ROWID FROM " + table_name + " WHERE ROWNUM = 1";
3862
            Statement _st = conn.createStatement();
3863
            ResultSet _rs = _st.executeQuery(rowid_avail_test);
3864
            _rs.close();
3865
            _st.close();
3866 13991 jldominguez@prodevelop.es
3867 13995 jldominguez@prodevelop.es
            String[] resp = { "ROWID" };
3868 13991 jldominguez@prodevelop.es
        return resp;
3869
    }
3870
3871
    /**
3872
     * Gets the field names that can act as geometry fields
3873
     * (queries the user's geographic metadata).
3874
     */
3875
    public String[] getGeometryFieldsCandidates(Connection conn,
3876
        String table_name) throws SQLException {
3877 13995 jldominguez@prodevelop.es
3878 13991 jldominguez@prodevelop.es
        Statement _st = conn.createStatement();
3879 13994 fran.penarrubia@iver.es
        String[] tokens = table_name.split("\\u002E", 2);
3880
        String qry;
3881
        if (tokens.length > 1)
3882
        {
3883
                qry = "select * from " + ORACLE_GEOMETADATA_VIEW +
3884
            " where OWNER = '" + tokens[0] + "' AND TABLE_NAME = '" +
3885
            tokens[1] + "'";
3886
        }
3887
        else
3888
        {
3889
                qry = "select * from " + ORACLE_GEOMETADATA_VIEW +
3890 13991 jldominguez@prodevelop.es
            " where TABLE_NAME = " + "'" + table_name + "'";
3891 13994 fran.penarrubia@iver.es
3892
        }
3893 13991 jldominguez@prodevelop.es
        ResultSet _rs = _st.executeQuery(qry);
3894
3895
        ArrayList aux = new ArrayList();
3896
3897
        while (_rs.next()) {
3898
            String _geo = _rs.getString("COLUMN_NAME");
3899
            aux.add(_geo);
3900
        }
3901
3902
        _rs.close();
3903
        _st.close();
3904
3905 13995 jldominguez@prodevelop.es
        String[] resp = (String[]) aux.toArray(new String[0]);
3906
3907
        return checkIndexes(conn, resp, table_name);
3908 13991 jldominguez@prodevelop.es
    }
3909
3910 13995 jldominguez@prodevelop.es
    private String[] checkIndexes(Connection c, String[] all, String __t) throws SQLException {
3911
3912
            ArrayList good_ones = new ArrayList();
3913
            String t = __t;
3914
            if (t.lastIndexOf(".") != -1) t = t.substring(t.lastIndexOf(".") + 1, t.length());
3915
3916
            for (int i=0; i<all.length; i++) {
3917
3918
                String qry = "SELECT SRID, DIMINFO FROM " + ORACLE_GEOMETADATA_VIEW +
3919
            " WHERE TABLE_NAME = " + "'" + t.toUpperCase() +
3920
            "' AND COLUMN_NAME = '" + all[i].toUpperCase() + "'";
3921
3922
                Statement _st = c.createStatement();
3923
                ResultSet _rs = _st.executeQuery(qry);
3924
                if (_rs.next()) {
3925
                        String _srid = toString((BigDecimal) _rs.getObject(1));
3926
                        ARRAY diminfo = (ARRAY) _rs.getObject(2);
3927
                        int len = diminfo.getOracleArray().length;
3928
                        if (allowsGeoQueries(c, t, all[i], _srid, len)) {
3929
                                good_ones.add(all[i]);
3930
                        }
3931
                }
3932
                _rs.close();
3933
                _st.close();
3934
            }
3935
3936
            if (good_ones.size() == 0) {
3937
                    throw new SQLException("no_indexes_on_declared_geo_fields");
3938
            }
3939
            return (String[]) good_ones.toArray(new String[0]);
3940
    }
3941
3942
    private String toString(BigDecimal number) {
3943
3944
            if (number == null) return "NULL";
3945
            return "" + number.intValue();
3946
        }
3947
3948
        private boolean allowsGeoQueries(Connection c, String _t, String gf, String _srid, int dims) {
3949
            String p = getPointConstructor(dims, _srid);
3950
            String qry = "SELECT * FROM " + _t.toUpperCase() + " WHERE (ROWNUM = 1)";
3951
            qry = "SELECT * FROM (" + qry + ") WHERE SDO_RELATE(" + "\"" + gf + "\", " + p + ", 'mask=TOUCH') = 'TRUE'";
3952
3953
            try {
3954
                        Statement _st = c.createStatement();
3955
                        ResultSet _rs = _st.executeQuery(qry);
3956
                        _rs.close();
3957
                        _st.close();
3958
                } catch (Exception ex) {
3959
                        return false;
3960
                }
3961
                return true;
3962
        }
3963
3964
        private String getPointConstructor(int dims, String _srid) {
3965
3966
                String coord = "";
3967
                for (int i=0; i<dims; i++) coord = coord + "0, ";
3968
                coord = coord.substring(0, coord.length() - 2);
3969
3970
                return "MDSYS.SDO_GEOMETRY(" + (dims * 1000 + 1) + ", " + _srid + ", NULL, " +
3971
                "MDSYS.SDO_ELEM_INFO_ARRAY(1, 1, 1), MDSYS.SDO_ORDINATE_ARRAY(" + coord + "))";
3972
        }
3973
3974
        private boolean stringInArrayListOfStrings(ArrayList l, String str) {
3975
3976
            if (l == null) return false;
3977
            if (str == null) return false;
3978
3979
            String item = "";
3980
            for (int i=0; i<l.size(); i++) {
3981
                    if (l.get(i) instanceof String) {
3982
                            item = (String) l.get(i);
3983
                            if (item.compareToIgnoreCase(str) == 0) return true;
3984
                    }
3985
            }
3986
            return false;
3987
    }
3988
3989
        /**
3990 13991 jldominguez@prodevelop.es
     * Utility method to check if a given table is empty.
3991
     */
3992
    public boolean isEmptyTable(Connection conn, String tableName) {
3993
        boolean res = true;
3994
3995
        try {
3996
            Statement st = conn.createStatement();
3997
            ResultSet rs = null;
3998
            rs = st.executeQuery("select * from " + tableName +
3999
                    " where rownum = 1");
4000
            res = !rs.next();
4001
            rs.close();
4002
            st.close();
4003
        }
4004
        catch (Exception ex) {
4005
            res = true;
4006
        }
4007
4008
        return res;
4009
    }
4010
4011
    /**
4012
     * Gets all the fields from a table name.
4013
     */
4014
    public String[] getAllFields(Connection conn, String table_name)
4015
        throws SQLException {
4016
        Statement st = conn.createStatement();
4017
        ResultSet rs = st.executeQuery("select * from " + table_name +
4018
                " where rownum = 1");
4019
        ResultSetMetaData rsmd = rs.getMetaData();
4020
        String[] ret = new String[rsmd.getColumnCount()];
4021
4022
        for (int i = 0; i < ret.length; i++) {
4023
            ret[i] = rsmd.getColumnName(i + 1);
4024
        }
4025
4026
        rs.close();
4027
        st.close();
4028
4029
        return ret;
4030
    }
4031
4032
    /**
4033
     * Gets all field type names from a table.
4034
     */
4035
    public String[] getAllFieldTypeNames(Connection conn, String table_name)
4036
        throws SQLException {
4037
        Statement st = conn.createStatement();
4038
        ResultSet rs = st.executeQuery("select * from " + table_name +
4039
                " where rownum = 1");
4040
        ResultSetMetaData rsmd = rs.getMetaData();
4041
        String[] ret = new String[rsmd.getColumnCount()];
4042
4043
        for (int i = 0; i < ret.length; i++) {
4044
            ret[i] = rsmd.getColumnTypeName(i + 1);
4045
        }
4046
4047
        rs.close();
4048
        st.close();
4049
4050
        close();
4051
4052
        return ret;
4053
    }
4054
4055
    /**
4056
     * Gets Oracle's specific connection string for the given parameters.
4057
     */
4058
    public String getConnectionString(String host, String port, String dbname,
4059
        String user, String pw) {
4060
        String _pw = pw;
4061
4062
        if (_pw == null) {
4063
            _pw = "null";
4064
        }
4065
4066
        String fullstr = CONN_STR_BEGIN;
4067
        fullstr = fullstr + user.toLowerCase() + "/" + _pw;
4068
        fullstr = fullstr + "@" + host.toLowerCase();
4069
        fullstr = fullstr + ":" + port;
4070
        fullstr = fullstr + ":" + dbname.toLowerCase();
4071
4072
        return fullstr;
4073
    }
4074
4075
    /**
4076
     * Gets the Pracle geometries writer associated with this driver.
4077
     */
4078
    public IWriter getWriter() {
4079
        // on(VectorialEditableDBAdapter.java:290)
4080
        if (writer == null) {
4081
            writer = new OracleSpatialWriter(getRowCount());
4082
            writer.setDriver(this);
4083
            writer.setLyrShapeType(getShapeType());
4084
            writer.setGeoCS(isGeogCS());
4085
            writer.setGeoColName(geoColName);
4086
            writer.setSRID(oracleSRID);
4087
4088
            try {
4089
                writer.initialize(getLyrDef());
4090
            }
4091
            catch (EditionException e) {
4092
                logger.error("While initializing OS Writer: " + e.getMessage(),
4093
                    e);
4094
            }
4095
4096
            writer.setStoreWithSrid(tableHasSrid);
4097
        }
4098
4099
        return writer;
4100
    }
4101
4102
    /**
4103
     * Tells whether the SRS is geodetic or not
4104
     * @return whether the SRS is geodetic or not
4105
     */
4106
    public boolean isGeogCS() {
4107
        return isGeogCS;
4108
    }
4109
4110
    /**
4111
     * Adds a row id to the inner set od IDs.
4112
     * @param id
4113
     */
4114
    public void addRow(String id) {
4115
        Value aux = ValueFactory.createValue(id);
4116
        Integer intobj = new Integer(numReg);
4117
        hashRelate.put(aux, intobj);
4118
        rowToId.put(intobj, id);
4119
4120
        numReg++;
4121
    }
4122
4123
    /**
4124
     * Removes a row id to the inner set od IDs.
4125
     * @param id
4126
     */
4127
    public void deleteRow(String id) {
4128
        Value aux = ValueFactory.createValue(id);
4129
        Integer intobj = (Integer) hashRelate.get(aux);
4130
        hashRelate.remove(aux);
4131
        rowToId.remove(intobj);
4132
4133
        numReg--;
4134
    }
4135
4136
    private String getStandardSelectExpression() {
4137
        if (standardSelectExpressionFalse == null) {
4138
            standardSelectExpressionFalse = "";
4139
4140
            String[] flds = getLyrDef().getFieldNames();
4141
            int size = flds.length;
4142
4143
            for (int i = 0; i < size; i++) {
4144
                if (i > 0) {
4145
                    standardSelectExpressionFalse = standardSelectExpressionFalse +
4146
                        "c.\"" + flds[i] + "\", ";
4147
                }
4148
                else {
4149
                    standardSelectExpressionFalse = standardSelectExpressionFalse +
4150
                        flds[i] + ", ";
4151
                }
4152
            }
4153
4154
            // standardSelectExpressionFalse = standardSelectExpressionFalse + "c." + geoColName;
4155
            standardSelectExpressionFalse = standardSelectExpressionFalse.substring(0,
4156
                    standardSelectExpressionFalse.length() - 2);
4157
        }
4158
4159
        return standardSelectExpressionFalse;
4160
    }
4161
4162
    /**
4163
     * Allows the method to decide what to do with the geometry field name
4164
     * (remove/add it from the user selected fields).
4165
     *
4166
     * @param flds
4167
     * @param geof
4168
     * @return the possibly modified field names
4169
     */
4170
    public String[] manageGeometryField(String[] flds, String geof) {
4171
        return addEndIfNotContained(flds, geof);
4172
    }
4173
4174
    /**
4175
     * Allows the method to decide what to do with the ID field name
4176
     * (remove/add it from the user selected fields).
4177
     *
4178
     * @param flds
4179
     * @param idf
4180
     * @return the possibly modified field names
4181
     */
4182
    public String[] manageIdField(String[] flds, String idf) {
4183
        return addStartIfNotContained(flds, idf);
4184
    }
4185
4186
    private String[] addEndIfNotContained(String[] arr, String item) {
4187
        if (contains(arr, item)) {
4188
            return arr;
4189
        }
4190
        else {
4191
            int size = arr.length;
4192
            String[] resp = new String[size + 1];
4193
4194
            for (int i = 0; i < size; i++) {
4195
                resp[i] = arr[i];
4196
            }
4197
4198
            resp[size] = item;
4199
4200
            return resp;
4201
        }
4202
    }
4203
4204
    private String[] addStartIfNotContained(String[] arr, String item) {
4205
        if (contains(arr, item)) {
4206
            return arr;
4207
        }
4208
        else {
4209
            int size = arr.length;
4210
            String[] resp = new String[size + 1];
4211
4212
            for (int i = 1; i <= size; i++) {
4213
                resp[i] = arr[i];
4214
            }
4215
4216
            resp[0] = item;
4217
4218
            return resp;
4219
        }
4220
    }
4221
4222
    private boolean contains(String[] arr, String item) {
4223
        for (int i = 0; i < arr.length; i++) {
4224
            if (arr[i].compareTo(item) == 0) {
4225
                return true;
4226
            }
4227
        }
4228
4229
        return false;
4230
    }
4231
4232
    /**
4233
     * This method is called when the user removes the layer from the view.
4234
     * If the IDs were being loaded, the driver will check this field and will
4235
     * let the thread 'die' quietly.
4236
     *
4237
     */
4238
    public void remove() {
4239
        cancelIDLoad = true;
4240
    }
4241
4242
    private boolean realiableExtent(Rectangle2D ext, boolean isgeodetic) {
4243
            if (!isgeodetic) return true;
4244
            if (ext.getMinX() > -179.99) return true;
4245
            if (ext.getMinY() > -89.99) return true;
4246
            if (ext.getWidth() < 359.99) return true;
4247
            if (ext.getHeight() < 179.99) return true;
4248
            return false;
4249
    }
4250
4251
    private Rectangle2D getFastEstimatedGeodeticExtent(
4252
                    String tname, String gfield, Connection c, int sample_size, double enlargement) {
4253
4254
            Rectangle2D world = new Rectangle2D.Double(-180, -90, 360, 180);
4255
            Rectangle2D resp_aux = null;
4256
            String qry = "SELECT " + gfield + " FROM " + tname + " WHERE ROWNUM <= " + sample_size;
4257
            ResultSet _rs = null;
4258
4259
            try {
4260
                        PreparedStatement _st = c.prepareStatement(qry);
4261
                        _rs = _st.executeQuery();
4262
                        while (_rs.next()) {
4263
                                STRUCT aux = (STRUCT) _rs.getObject(1);
4264
                                IGeometry ig = getGeometryUsing(aux, false);
4265
4266
                                if (ig == null) continue;
4267
4268
                                if (resp_aux == null) {
4269
                                        resp_aux = ig.getBounds2D();
4270
                                } else {
4271
                                        resp_aux.add(ig.getBounds2D());
4272
                                }
4273
4274
                        }
4275
                } catch (Exception ex) {
4276
                        logger.error("While getting random sample: " + ex.getMessage());
4277
                        return world;
4278
                }
4279
4280
                if (resp_aux == null) return world;
4281
                double w = resp_aux.getWidth();
4282
                double h = resp_aux.getHeight();
4283
                double x = resp_aux.getMinX();
4284
                double y = resp_aux.getMinY();
4285
4286
                // enlarge 10 times:
4287
                double newx = x - (0.5 * (enlargement - 1)) * w;
4288
                double newy = y - (0.5 * (enlargement - 1)) * w;
4289
                Rectangle2D resp_aux_large = new Rectangle2D.Double(newx, newy,
4290
                                enlargement * w,
4291
                                enlargement * h);
4292
4293
4294
                Rectangle2D.intersect(world, resp_aux_large, resp_aux);
4295
4296
                logger.debug("FAST BB:");
4297
                logger.debug(" min x:" + resp_aux.getMinX());
4298
                logger.debug(" min y:" + resp_aux.getMinY());
4299
                logger.debug("     w:" + resp_aux.getWidth());
4300
                logger.debug("     h:" + resp_aux.getHeight());
4301
                return resp_aux;
4302
    }
4303
4304
    private Rectangle2D getEstimatedGeodeticExtent(
4305
                    String tname, String gfield, Connection c, int sample_size, double enlargement) {
4306
4307
            Rectangle2D world = new Rectangle2D.Double(-180, -90, 360, 180);
4308
4309
            ArrayList ids = new ArrayList();
4310
            int _rnd_index = 0;
4311
            ROWID _id = null;
4312
            Random rnd = new Random(System.currentTimeMillis());
4313
4314
            for (int i=0; i<sample_size; i++) {
4315
                    _rnd_index = rnd.nextInt(numReg);
4316
                    _id = (ROWID) rowToId.get(new Integer((int) _rnd_index));
4317
                    ids.add(_id.stringValue());
4318
            }
4319
4320
            String qry = "SELECT " + gfield + " FROM " + tname + " WHERE (";
4321
            for (int i=0; i<ids.size(); i++) {
4322
                    qry = qry + "(ROWID = '" + ((String) ids.get(i)) + "') OR ";
4323
            }
4324
            qry = qry.substring(0, qry.length() - 4) + ")";
4325
4326
            Rectangle2D resp_aux = null;
4327
            ResultSet _rs = null;
4328
4329
            try {
4330
                        PreparedStatement _st = c.prepareStatement(qry);
4331
                        _rs = _st.executeQuery();
4332
                        while (_rs.next()) {
4333
                                STRUCT aux = (STRUCT) _rs.getObject(1);
4334
                                IGeometry ig = getGeometryUsing(aux, false);
4335
4336
                                if (ig == null) continue;
4337
4338
                                if (resp_aux == null) {
4339
                                        resp_aux = ig.getBounds2D();
4340
                                } else {
4341
                                        resp_aux.add(ig.getBounds2D());
4342
                                }
4343
4344
                        }
4345
                } catch (Exception ex) {
4346
                        logger.error("While getting random sample: " + ex.getMessage());
4347
                        return world;
4348
                }
4349
4350
                if (resp_aux == null) return world;
4351
                double w = resp_aux.getWidth();
4352
                double h = resp_aux.getHeight();
4353
                double x = resp_aux.getMinX();
4354
                double y = resp_aux.getMinY();
4355
4356
                // enlarge 10 times:
4357
                double newx = x - (0.5 * (enlargement - 1)) * w;
4358
                double newy = y - (0.5 * (enlargement - 1)) * w;
4359
                Rectangle2D resp_aux_large = new Rectangle2D.Double(newx, newy,
4360
                                enlargement * w,
4361
                                enlargement * h);
4362
4363
4364
                Rectangle2D.intersect(world, resp_aux_large, resp_aux);
4365
                return resp_aux;
4366
    }
4367
4368 13995 jldominguez@prodevelop.es
    public void setUserName(String u) {
4369
            userName = u;
4370
    }
4371 13991 jldominguez@prodevelop.es
4372 13995 jldominguez@prodevelop.es
    public String getUserName() {
4373
            return userName;
4374
    }
4375 13991 jldominguez@prodevelop.es
4376 13995 jldominguez@prodevelop.es
4377
4378 13991 jldominguez@prodevelop.es
}