Statistics
| Revision:

svn-gvsig-desktop / branches / v2_0_0_prep / extensions / extOracleSpatial / src / org / gvsig / oraclespatial / driver / OracleSpatialUtils.java @ 29455

History | View | Annotate | Download (93.3 KB)

1
/* 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 org.gvsig.oraclespatial.driver;
44

    
45
import java.awt.Shape;
46
import java.awt.geom.PathIterator;
47
import java.awt.geom.Point2D;
48
import java.awt.geom.Rectangle2D;
49
import java.io.BufferedReader;
50
import java.io.File;
51
import java.io.FileReader;
52
import java.lang.reflect.Array;
53
import java.net.URL;
54
import java.sql.PreparedStatement;
55
import java.sql.ResultSet;
56
import java.sql.SQLException;
57
import java.sql.Types;
58
import java.text.DecimalFormat;
59
import java.text.DecimalFormatSymbols;
60
import java.util.ArrayList;
61
import java.util.HashMap;
62
import java.util.Iterator;
63
import java.util.Random;
64

    
65
import oracle.sql.ARRAY;
66
import oracle.sql.Datum;
67
import oracle.sql.NUMBER;
68
import oracle.sql.STRUCT;
69
import oracle.sql.StructDescriptor;
70

    
71
import org.apache.log4j.Logger;
72
import org.gvsig.fmap.geom.Geometry;
73
import org.gvsig.fmap.geom.GeometryLocator;
74
import org.gvsig.fmap.geom.GeometryManager;
75
import org.gvsig.fmap.geom.primitive.GeneralPathX;
76

    
77

    
78
import com.vividsolutions.jts.algorithm.CGAlgorithms;
79
import com.vividsolutions.jts.geom.Coordinate;
80
import com.vividsolutions.jts.geom.CoordinateArrays;
81
import com.vividsolutions.jts.geom.Envelope;
82
import com.vividsolutions.jts.geom.GeometryFactory;
83
import com.vividsolutions.jts.geom.LineString;
84
import com.vividsolutions.jts.geom.LinearRing;
85
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
86

    
87

    
88
/**
89
 * Utility class with static methods.
90
 *
91
 * @author jldominguez
92
 *
93
 */
94
public class OracleSpatialUtils {
95
    private static Logger logger = Logger.getLogger(OracleSpatialUtils.class.getName());
96
    private static double FLATNESS = 0.8;
97
    private static GeometryFactory geomFactory = new GeometryFactory();
98
    private static final double IRRELEVANT_DISTANCE = 0.00000001;
99
    private static Random rnd = new Random();
100
    private static DecimalFormat df = new DecimalFormat();
101
    private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
102
    public static final int ORACLE_GTYPE_UNKNOWN = 0;
103
    public static final int ORACLE_GTYPE_POINT = 1;
104
    public static final int ORACLE_GTYPE_LINE = 2;
105
    public static final int ORACLE_GTYPE_POLYGON = 3;
106
    public static final int ORACLE_GTYPE_COLLECTION = 4;
107
    public static final int ORACLE_GTYPE_MULTIPOINT = 5;
108
    public static final int ORACLE_GTYPE_MULTILINE = 6;
109
    public static final int ORACLE_GTYPE_MULTIPOLYGON = 7;
110

    
111
    public static final int ORACLE_GTYPE_COMPLEX_VOIDED_POLYON = 3;
112
    public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_LINE = 4;
113
    public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON = 5;
114
    
115
    
116

    
117
    /**
118
     * COnstructs a geometry from a file that contains a vertex per line:
119
     *
120
     * x1 y1 z1
121
     * x2 y2 z2
122
     * ...
123
     *
124
     * @param filepath vertices text file path
125
     * @param polygon whether it is a polygon or not
126
     * @return the created geometry
127
     */
128
    public static Geometry readGeometry3D(URL filepath, boolean polygon) {
129
            
130
            GeometryManager gManager = GeometryLocator.getGeometryManager();
131
            
132
        GeneralPathX resp = new GeneralPathX();
133
        File file = new File(filepath.getFile());
134
        ArrayList z = new ArrayList();
135

    
136
        try {
137
            FileReader fr = new FileReader(file);
138
            BufferedReader br = new BufferedReader(fr);
139
            double[] coords = new double[3];
140

    
141
            boolean move = true;
142

    
143
            String line = br.readLine();
144

    
145
            while (line != null) {
146
                coords = parseLine(line);
147

    
148
                if (line.length() == 0) {
149
                    move = true;
150
                }
151
                else {
152
                    if (move) {
153
                        resp.moveTo(coords[0], coords[1]);
154
                        z.add(new Double(coords[2]));
155
                    }
156
                    else {
157
                        resp.lineTo(coords[0], coords[1]);
158
                        z.add(new Double(coords[2]));
159
                    }
160

    
161
                    move = false;
162
                }
163

    
164
                line = br.readLine();
165
            }
166
        }
167
        catch (Exception ex) {
168
                logger.error("While creating GeneralPathX: " +
169
                ex.getMessage());
170

    
171
            return null;
172
        }
173

    
174
        double[] zz = new double[z.size()];
175

    
176
        for (int i = 0; i < z.size(); i++) {
177
            zz[i] = ((Double) z.get(i)).doubleValue();
178
        }
179

    
180
        if (polygon) {
181
            return gManager.createSurface(resp, Geometry.SUBTYPES.GEOM3D);
182
        }
183
        else {
184
            return gManager.createMultiCurve(resp, Geometry.SUBTYPES.GEOM3D);
185
        }
186
    }
187

    
188
    private static double[] parseLine(String line) {
189
        String[] sep = line.split(" ");
190
        double[] resp = new double[3];
191

    
192
        for (int i = 0; i < 3; i++)
193
            resp[i] = 0.0;
194

    
195
        try {
196
            resp[0] = Double.parseDouble(sep[0]);
197
        }
198
        catch (Exception ex) {
199
        }
200

    
201
        if (sep.length > 1) {
202
            try {
203
                resp[1] = Double.parseDouble(sep[1]);
204
            }
205
            catch (Exception ex) {
206
            }
207

    
208
            if (sep.length > 2) {
209
                try {
210
                    resp[2] = Double.parseDouble(sep[2]);
211
                }
212
                catch (Exception ex) {
213
                }
214
            }
215
        }
216

    
217
        return resp;
218
    }
219

    
220
    /**
221
     * Utility method to convert a gvSIG FShape into a oracle struct
222
     *
223
     * @param fshp the FShape object
224
     * @param c the connection
225
     * @param srid the SRS (oarcle code)
226
     * @param agu_b whether to check holes validity
227
     * @param hasSrid whether the SRS is non-NULL
228
     * @return a oracle struct representing the geometry
229
     *
230
     * @throws SQLException
231
     */
232
    public static STRUCT fShapeToSTRUCT(Object fshp, Connection c, int srid,
233
        boolean agu_b, boolean hasSrid) throws SQLException {
234
        boolean three = false;
235
        
236
        GeometryManager gManager = GeometryLocator.getGeometryManager();
237

    
238
        if (fshp instanceof Geometry3D) {
239
            three = true;
240
        }
241

    
242
        STRUCT resp = null;
243

    
244
        if (fshp instanceof FMultiPoint2D) {
245
            resp = multiPoint2DToStruct((FMultiPoint2D) fshp, c, srid, hasSrid);
246

    
247
            return resp;
248
        }
249

    
250
        if (!(fshp instanceof FShape)) {
251
            logger.error("Unknown geometry: " + fshp.toString());
252

    
253
            return null;
254
        }
255

    
256
        if (fshp instanceof FPoint2D) { // point 2/3d
257

    
258
            // resp = pointToWKT((FPoint2D) fshp, three);
259
            Coordinate p = getSingleCoordinate((FPoint2D) fshp);
260
            resp = getMultiPointAsStruct(p, srid, three, c, hasSrid);
261
        }
262
        else {
263
            if (fshp instanceof FPolygon2D) { // polygon 2/3d
264

    
265
                if (fshp instanceof FCircle2D) {
266
                    resp = getCircleAsStruct((FCircle2D) fshp, srid, c, hasSrid);
267
                }
268
                else {
269
                    // also FEllipse2D
270
                    resp = getMultiPolygonAsStruct((FShape) fshp, srid, three,
271
                            c, agu_b, hasSrid);
272

    
273
                    // ArrayList polys = getPolygonsEasily(fshp);
274
                    // resp = getMultiPolygonAsStruct(polys, srid, three, c);
275
                }
276
            }
277
            else { // line 2/3d
278

    
279
                ArrayList _lines = getLineStrings((FShape) fshp);
280
                resp = getMultiLineAsStruct(_lines, srid, three, c, hasSrid);
281
            }
282
        }
283

    
284
        return resp;
285
    }
286

    
287
    private static STRUCT multiPoint2DToStruct(FMultiPoint2D mp2d,
288
        IConnection c, int srid, boolean hasSrid) throws SQLException {
289
        int np = mp2d.getNumPoints();
290
        boolean threed = (mp2d instanceof FMultipoint3D);
291
        int gtype = 2005;
292
        int dim = 2;
293
        FMultipoint3D mp3d = null;
294

    
295
        if (threed) {
296
            gtype = 3005;
297
            dim = 3;
298
            mp3d = (FMultipoint3D) mp2d;
299
        }
300

    
301
        NUMBER[] indices = new NUMBER[3];
302
        indices[0] = new NUMBER(1);
303
        indices[1] = new NUMBER(1);
304
        indices[2] = new NUMBER(np);
305

    
306
        NUMBER[] ords = new NUMBER[dim * np];
307

    
308
        for (int i = 0; i < np; i++) {
309
            ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
310
            ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY());
311

    
312
            if (threed) {
313
                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
314
            }
315
        }
316

    
317
        STRUCT resp;
318
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
319
                        ((ConnectionJDBC)c).getConnection());
320
        Object[] obj = new Object[5];
321
        obj[0] = new NUMBER(gtype);
322

    
323
        if (hasSrid) {
324
            obj[1] = new NUMBER(srid);
325
        }
326
        else { // , boolean hasSrid
327
            obj[1] = null;
328
        }
329

    
330
        obj[2] = null;
331
        obj[3] = indices;
332
        obj[4] = ords;
333
        resp = new STRUCT(dsc, ((ConnectionJDBC)c).getConnection(), obj);
334

    
335
        return resp;
336
    }
337

    
338
    private static STRUCT getCircleAsStruct(FCircle2D fcirc, int srid,
339
        IConnection _conn, boolean hasSrid) throws SQLException {
340
        int geotype = 2003;
341
        NUMBER[] indices = new NUMBER[3];
342
        indices[0] = new NUMBER(1);
343
        indices[1] = new NUMBER(1003);
344
        indices[2] = new NUMBER(4);
345

    
346
        NUMBER[] ords = new NUMBER[6];
347
        Coordinate[] three_points = getThreePointsOfCircumference(fcirc.getCenter(),
348
                fcirc.getRadio());
349

    
350
        for (int i = 0; i < three_points.length; i++) {
351
            ords[i * 2] = new NUMBER(three_points[i].x);
352
            ords[(i * 2) + 1] = new NUMBER(three_points[i].y);
353
        }
354

    
355
        STRUCT resp;
356
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
357
                        ((ConnectionJDBC)_conn).getConnection());
358
        Object[] obj = new Object[5];
359
        obj[0] = new NUMBER(geotype);
360

    
361
        if (hasSrid) {
362
            obj[1] = new NUMBER(srid);
363
        }
364
        else {
365
            obj[1] = null;
366
        }
367

    
368
        obj[2] = null;
369
        obj[3] = indices;
370
        obj[4] = ords;
371
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
372

    
373
        return resp;
374
    }
375

    
376
    private static Coordinate[] getThreePointsOfCircumference(Point2D cntr,
377
        double radius) {
378
        Coordinate[] resp = new Coordinate[3];
379
        double x;
380
        double y;
381
        double alpha = 0;
382

    
383
        for (int i = 0; i < 3; i++) {
384
            alpha = (i * 120.0 * Math.PI) / 180.0;
385
            x = cntr.getX() + (radius * Math.cos(alpha));
386
            y = cntr.getY() + (radius * Math.sin(alpha));
387
            resp[i] = new Coordinate(x, y);
388
        }
389

    
390
        return resp;
391
    }
392

    
393
    private static Coordinate getSingleCoordinate(FPoint2D p2d) {
394
        // TODO Auto-generated method stub
395
        Coordinate resp = new Coordinate();
396
        resp.x = p2d.getX();
397
        resp.y = p2d.getY();
398

    
399
        if (p2d instanceof FPoint3D) {
400
            resp.z = ((FPoint3D) p2d).getZs()[0];
401
        }
402

    
403
        return resp;
404
    }
405

    
406
    private static ArrayList ensureSensibleLineString(ArrayList cc) {
407
        if (cc.size() == 2) {
408
            if (sameCoordinate((Coordinate) cc.get(0),
409
                        (Coordinate) cc.get(cc.size() - 1))) {
410
                ArrayList resp = new ArrayList();
411
                resp.add(cc.get(0));
412

    
413
                Coordinate newc = new Coordinate((Coordinate) cc.get(0));
414
                newc.x = newc.x + IRRELEVANT_DISTANCE;
415
                resp.add(newc);
416

    
417
                return resp;
418
            }
419
        }
420

    
421
        return cc;
422
    }
423

    
424
    private static boolean sameCoordinate(Coordinate c1, Coordinate c2) {
425
        if (c1.x != c2.x) {
426
            return false;
427
        }
428

    
429
        if (c1.y != c2.y) {
430
            return false;
431
        }
432

    
433
        return true;
434
    }
435

    
436
    private static ArrayList getClosedRelevantPolygon(ArrayList cc) {
437
        if (cc.size() == 2) {
438
            return getMinClosedCoords((Coordinate) cc.get(0));
439
        }
440

    
441
        if (cc.size() == 3) {
442
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1))) {
443
                return getMinClosedCoords((Coordinate) cc.get(0));
444
            }
445

    
446
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2))) {
447
                return getMinClosedCoords((Coordinate) cc.get(0));
448
            }
449

    
450
            if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2))) {
451
                return getMinClosedCoords((Coordinate) cc.get(1));
452
            }
453

    
454
            cc.add(cc.get(0));
455

    
456
            return cc;
457
        }
458

    
459
        if (!sameCoordinate((Coordinate) cc.get(0),
460
                    (Coordinate) cc.get(cc.size() - 1))) {
461
            cc.add(cc.get(0));
462
        }
463

    
464
        return cc;
465
    }
466

    
467
    private static ArrayList getMinClosedCoords(Coordinate c) {
468
        ArrayList resp = new ArrayList();
469
        resp.add(c);
470

    
471
        Coordinate nc = new Coordinate(c);
472
        nc.x = nc.x + IRRELEVANT_DISTANCE;
473
        resp.add(nc);
474

    
475
        Coordinate nc2 = new Coordinate(nc);
476
        nc2.y = nc2.y + IRRELEVANT_DISTANCE;
477
        resp.add(nc2);
478

    
479
        resp.add(new Coordinate(c));
480

    
481
        return resp;
482
    }
483

    
484
    private static LinearRing getMinLinearRing(Coordinate c) {
485
        Coordinate[] p = new Coordinate[4];
486
        p[0] = c;
487

    
488
        Coordinate nc = new Coordinate(c);
489
        nc.x = nc.x + IRRELEVANT_DISTANCE;
490

    
491
        Coordinate nc2 = new Coordinate(nc);
492
        nc2.y = nc2.y - IRRELEVANT_DISTANCE;
493
        p[1] = nc;
494
        p[2] = nc2;
495
        p[3] = new Coordinate(c);
496

    
497
        CoordinateArraySequence cs = new CoordinateArraySequence(p);
498
        LinearRing ls = new LinearRing(cs, geomFactory);
499

    
500
        return ls;
501
    }
502

    
503
    private static double[] getMinLinearRingZ() {
504
        double[] resp = new double[4];
505

    
506
        for (int i = 0; i < 4; i++)
507
            resp[i] = 0.0;
508

    
509
        return resp;
510
    }
511

    
512
    private static boolean pointInList(Coordinate testPoint,
513
        Coordinate[] pointList) {
514
        int t;
515
        int numpoints;
516
        Coordinate p;
517

    
518
        numpoints = Array.getLength(pointList);
519

    
520
        for (t = 0; t < numpoints; t++) {
521
            p = pointList[t];
522

    
523
            if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
524
                    ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
525
            ) {
526
                return true;
527
            }
528
        }
529

    
530
        return false;
531
    }
532

    
533
    private static ArrayList getPolygonsEasily(FShape mpolygon) {
534
        boolean threed = false;
535

    
536
        if (mpolygon instanceof FPolygon3D) {
537
            threed = true;
538
        }
539

    
540
        int start_ind = 0;
541
        int end_ind = 0;
542
        int ind = 0;
543
        int new_size;
544
        ArrayList arrayCoords = null;
545
        ArrayList resp = new ArrayList();
546
        Coordinate[] points = null;
547
        int theType = -99;
548
        double[] theData = new double[6];
549
        Coordinate onlyCoord = null;
550
        int numParts = 0;
551

    
552
        PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
553

    
554
        while (!theIterator.isDone()) {
555
            //while not done
556
            theType = theIterator.currentSegment(theData);
557

    
558
            if (onlyCoord == null) {
559
                onlyCoord = new Coordinate();
560
                onlyCoord.x = theData[0];
561
                onlyCoord.y = theData[1];
562
            }
563

    
564
            switch (theType) {
565
            case PathIterator.SEG_MOVETO:
566

    
567
                if (arrayCoords == null) {
568
                    arrayCoords = new ArrayList();
569
                }
570
                else {
571
                    end_ind = ind - 1;
572

    
573
                    arrayCoords = getClosedRelevantPolygon(arrayCoords);
574
                    new_size = arrayCoords.size();
575

    
576
                    if (arrayCoords != null) {
577
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
578

    
579
                        try {
580
                            LinearRing aux = geomFactory.createLinearRing(points);
581
                            double[] z = null;
582

    
583
                            if (threed) {
584
                                z = getZ((FPolygon3D) mpolygon, start_ind,
585
                                        end_ind, new_size);
586
                            }
587

    
588
                            LineString3D ring = new LineString3D(aux, z);
589

    
590
                            if (CGAlgorithms.isCCW(points)) {
591
                                resp.add(ring);
592
                            }
593
                            else {
594
                                resp.add(ring.createReverse());
595
                            }
596
                        }
597
                        catch (Exception e) {
598
                                logger.error("Topology exception: " +
599
                                e.getMessage());
600

    
601
                            return null;
602
                        }
603
                    }
604

    
605
                    arrayCoords = new ArrayList();
606

    
607
                    start_ind = ind;
608
                }
609

    
610
                numParts++;
611

    
612
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
613
                ind++;
614

    
615
                break;
616

    
617
            case PathIterator.SEG_LINETO:
618
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
619
                ind++;
620

    
621
                break;
622

    
623
            case PathIterator.SEG_QUADTO:
624
                    logger.info("SEG_QUADTO Not supported here");
625
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
626
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
627
                ind++;
628
                ind++;
629

    
630
                break;
631

    
632
            case PathIterator.SEG_CUBICTO:
633
                    logger.info("SEG_CUBICTO Not supported here");
634
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
635
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
636
                arrayCoords.add(new Coordinate(theData[4], theData[5]));
637
                ind++;
638
                ind++;
639
                ind++;
640

    
641
                break;
642

    
643
            case PathIterator.SEG_CLOSE:
644

    
645
                // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
646
                // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
647
                break;
648
            } //end switch
649

    
650
            theIterator.next();
651
        } //end while loop
652

    
653
        end_ind = ind - 1;
654

    
655
        // null shape:
656
        if (arrayCoords == null) {
657
            arrayCoords = new ArrayList();
658

    
659
            Coordinate _c = new Coordinate(0, 0, 0);
660
            arrayCoords.add(new Coordinate(_c));
661
            arrayCoords.add(new Coordinate(_c));
662
        }
663

    
664
        // --------------------------------------------
665
        arrayCoords = getClosedRelevantPolygon(arrayCoords);
666
        new_size = arrayCoords.size();
667

    
668
        if (arrayCoords != null) {
669
            points = CoordinateArrays.toCoordinateArray(arrayCoords);
670

    
671
            try {
672
                LinearRing aux = geomFactory.createLinearRing(points);
673
                double[] z = null;
674

    
675
                if (threed) {
676
                    z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
677
                }
678

    
679
                LineString3D ring = new LineString3D(aux, z);
680

    
681
                if (CGAlgorithms.isCCW(points)) {
682
                    resp.add(ring);
683
                }
684
                else {
685
                    resp.add(ring.createReverse());
686
                }
687
            }
688
            catch (Exception e) {
689
                    logger.error("Topology exception: " + e.getMessage());
690

    
691
                return null;
692
            }
693
        }
694

    
695
        if (resp.size() == 0) {
696
            resp.add(new LineString3D(getMinLinearRing(onlyCoord),
697
                    getMinLinearRingZ()));
698
        }
699

    
700
        return resp;
701
    }
702

    
703
    /**
704
     * Utility method to reverse an array of doubles.
705
     *
706
     * @param _z an array of doubles to be reversed.
707
     *
708
     * @return the reversed array of doubles
709
     */
710
    public static double[] reverseArray(double[] _z) {
711
        int size = _z.length;
712
        double[] resp = new double[size];
713

    
714
        for (int i = 0; i < size; i++) {
715
            resp[i] = _z[size - 1 - i];
716
        }
717

    
718
        return resp;
719
    }
720

    
721
    /**
722
     * Utility method to reverse an array of coordinates
723
     *
724
     * @param _z an array of coordinaes to be reversed.
725
     *
726
     * @return the reversed array of coordinates
727
     */
728
    public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) {
729
        int size = _z.length;
730
        Coordinate[] resp = new Coordinate[size];
731

    
732
        for (int i = 0; i < size; i++) {
733
            resp[i] = _z[size - 1 - i];
734
        }
735

    
736
        return resp;
737
    }
738

    
739
    private static double[] getZ(FShape3D p3d, int _str, int _end, int size) {
740
        double[] resp = new double[size];
741
        double[] allz = p3d.getZs();
742

    
743
        for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) {
744
            resp[i - _str] = allz[i];
745
        }
746

    
747
        if ((_end - _str + 1) < size) {
748
            double repe = allz[_end];
749

    
750
            for (int i = (_end - _str + 1); i < size; i++) {
751
                resp[i] = repe;
752
            }
753
        }
754

    
755
        return resp;
756
    }
757

    
758
    private static ArrayList getLineStrings(FShape mlines) {
759
        boolean threed = false;
760

    
761
        if (mlines instanceof FPolyline3D) {
762
            threed = true;
763
        }
764

    
765
        int start_ind = 0;
766
        int end_ind = 0;
767
        int ind = 0;
768
        int new_size = 0;
769

    
770
        LineString3D lin;
771

    
772
        ArrayList arrayLines = new ArrayList();
773
        PathIterator theIterator = mlines.getPathIterator(null, FLATNESS);
774
        int theType = -99;
775
        double[] theData = new double[6];
776
        ArrayList arrayCoords = null;
777
        int numParts = 0;
778

    
779
        while (!theIterator.isDone()) {
780
            //while not done
781
            theType = theIterator.currentSegment(theData);
782

    
783
            switch (theType) {
784
            case PathIterator.SEG_MOVETO:
785

    
786
                if (arrayCoords == null) {
787
                    arrayCoords = new ArrayList();
788
                }
789
                else {
790
                    end_ind = ind - 1;
791
                    arrayCoords = ensureSensibleLineString(arrayCoords);
792
                    new_size = arrayCoords.size();
793

    
794
                    LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
795
                                arrayCoords));
796
                    double[] z = null;
797

    
798
                    if (threed) {
799
                        z = getZ((FPolyline3D) mlines, start_ind, end_ind,
800
                                new_size);
801
                    }
802

    
803
                    lin = new LineString3D(aux, z);
804
                    arrayLines.add(lin);
805
                    arrayCoords = new ArrayList();
806

    
807
                    start_ind = ind;
808
                }
809

    
810
                numParts++;
811
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
812

    
813
                break;
814

    
815
            case PathIterator.SEG_LINETO:
816
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
817

    
818
                break;
819

    
820
            case PathIterator.SEG_QUADTO:
821
                    logger.info("Not supported here: SEG_QUADTO");
822

    
823
                break;
824

    
825
            case PathIterator.SEG_CUBICTO:
826
                    logger.info("Not supported here: SEG_CUBICTO");
827

    
828
                break;
829

    
830
            case PathIterator.SEG_CLOSE:
831

    
832
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
833
                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
834

    
835
                break;
836
            } //end switch
837

    
838
            theIterator.next();
839
            ind++;
840
        } //end while loop
841

    
842
        arrayCoords = ensureSensibleLineString(arrayCoords);
843
        new_size = arrayCoords.size();
844

    
845
        LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
846
                    arrayCoords));
847
        double[] z = null;
848

    
849
        if (threed) {
850
            z = getZ((FPolyline3D) mlines, start_ind, end_ind, new_size);
851
        }
852

    
853
        lin = new LineString3D(aux, z);
854
        arrayLines.add(lin);
855

    
856
        return arrayLines;
857
    }
858

    
859
    private static String lineStringToWKT(LineString3D ls, boolean threed) {
860
        String resp = "(";
861
        Coordinate[] cc = ls.getLs().getCoordinates();
862
        double[] z = ls.getZc();
863
        int size = cc.length;
864

    
865
        if (threed) {
866
            for (int i = 0; i < size; i++) {
867
                resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", ";
868
            }
869

    
870
            resp = resp.substring(0, resp.length() - 2);
871
            resp = resp + ")";
872
        }
873
        else {
874
            for (int i = 0; i < size; i++) {
875
                resp = resp + cc[i].x + " " + cc[i].y + ", ";
876
            }
877

    
878
            resp = resp.substring(0, resp.length() - 2);
879
            resp = resp + ")";
880
        }
881

    
882
        return resp;
883
    }
884

    
885
    private static String multiLineStringToWKT(ArrayList ml, boolean threed) {
886
        String resp = "MULTILINESTRING(";
887

    
888
        for (int i = 0; i < ml.size(); i++) {
889
            LineString3D ls = (LineString3D) ml.get(i);
890
            resp = resp + lineStringToWKT(ls, threed) + ", ";
891
        }
892

    
893
        resp = resp.substring(0, resp.length() - 2) + ")";
894

    
895
        return resp;
896
    }
897

    
898
    private static String polygonsToWKT(ArrayList pols, boolean threed) {
899
        String resp = "MULTIPOLYGON(";
900
        LineString3D ls = null;
901

    
902
        for (int i = 0; i < pols.size(); i++) {
903
            ls = (LineString3D) pols.get(i);
904
            resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
905
        }
906

    
907
        resp = resp.substring(0, resp.length() - 2) + ")";
908

    
909
        return resp;
910
    }
911

    
912
    private static String shellAndHolesToWKT(LineString3D shell,
913
        ArrayList holes, boolean threed) {
914
        String resp = "(";
915
        resp = resp + lineStringToWKT(shell, threed);
916

    
917
        if (holes.size() > 0) {
918
            for (int i = 0; i < holes.size(); i++) {
919
                LineString3D ls = (LineString3D) holes.get(i);
920
                resp = resp + ", " + lineStringToWKT(ls, threed);
921
            }
922
        }
923

    
924
        resp = resp + ")";
925

    
926
        return resp;
927
    }
928

    
929
    private static String multiPolygonToWKT(ArrayList shells, ArrayList hFs,
930
        boolean threed) {
931
        String resp = "MULTIPOLYGON(";
932
        LineString3D ls = null;
933
        ArrayList holes;
934

    
935
        for (int i = 0; i < shells.size(); i++) {
936
            ls = (LineString3D) shells.get(i);
937
            holes = (ArrayList) hFs.get(i);
938
            resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
939
        }
940

    
941
        resp = resp.substring(0, resp.length() - 2) + ")";
942

    
943
        return resp;
944
    }
945

    
946
    private static String pointToWKT(FPoint2D point, boolean threed) {
947
        String resp = "POINT(" + point.getX() + " " + point.getY();
948

    
949
        if ((threed) && (point instanceof FPoint3D)) {
950
            resp = resp + " " + ((FPoint3D) point).getZs()[0];
951
        }
952

    
953
        resp = resp + ")";
954

    
955
        return resp;
956
    }
957

    
958
    private static int twoDIndexToDimsIndex(int n, int d) {
959
        return ((d * (n - 1)) / 2) + 1;
960
    }
961

    
962
    private static ARRAY setSubelementsToDim(ARRAY old, int d)
963
        throws SQLException {
964
        Datum[] infos = (Datum[]) old.getOracleArray();
965

    
966
        for (int i = 3; i < infos.length; i = i + 3) {
967
            int oldind = infos[i].intValue();
968
            oldind = twoDIndexToDimsIndex(oldind, d);
969
            infos[i] = new NUMBER(oldind);
970

    
971
            //
972
            oldind = infos[i + 1].intValue();
973
            infos[i + 1] = new NUMBER(infos[1].intValue());
974
        }
975

    
976
        ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
977
                infos);
978

    
979
        return resp;
980
    }
981

    
982
    private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
983
        Envelope env = ls.getEnvelopeInternal();
984

    
985
        if (!env.contains(p)) {
986
            return false;
987
        }
988

    
989
        return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
990
    }
991

    
992
    private static boolean lineString3DIsContainedBy(LineString3D contained,
993
        LineString3D container) {
994
        int samples = 10;
995
        LineString _in = contained.getLs();
996
        LineString _out = container.getLs();
997
        Coordinate[] inc = _in.getCoordinates();
998
        Coordinate aux;
999
        int size = inc.length;
1000

    
1001
        if (size <= 10) {
1002
            for (int i = 0; i < size; i++) {
1003
                aux = inc[i];
1004

    
1005
                if (!isPointInsideLineString(aux, _out)) {
1006
                    return false;
1007
                }
1008
            }
1009

    
1010
            return true;
1011
        }
1012
        else {
1013
            for (int i = 0; i < samples; i++) {
1014
                aux = inc[rnd.nextInt(size)];
1015

    
1016
                if (!isPointInsideLineString(aux, _out)) {
1017
                    return false;
1018
                }
1019
            }
1020

    
1021
            return true;
1022
        }
1023
    }
1024

    
1025
    private static STRUCT getMultiPolygonAsStruct(ArrayList pols, int srid,
1026
        boolean threed, IConnection _conn, boolean agu_bien, boolean hasSrid)
1027
        throws SQLException {
1028
        int size = pols.size();
1029
        int geotype = 2007;
1030
        int dim = 2;
1031
        int acum = 0;
1032

    
1033
        if (threed) {
1034
            geotype = 3007;
1035
            dim = 3;
1036
        }
1037

    
1038
        NUMBER[] indices = new NUMBER[3 * size];
1039

    
1040
        for (int i = 0; i < size; i++) {
1041
            indices[3 * i] = new NUMBER(acum + 1);
1042
            indices[(3 * i) + 1] = new NUMBER(1003);
1043
            indices[(3 * i) + 2] = new NUMBER(1);
1044
            acum = acum +
1045
                (dim * ((LineString3D) pols.get(i)).getLs().getNumPoints());
1046
        }
1047

    
1048
        int _ind = 0;
1049
        NUMBER[] ords = new NUMBER[acum];
1050

    
1051
        for (int i = 0; i < size; i++) {
1052
            LineString3D ls = (LineString3D) pols.get(i);
1053
            int num_p = ls.getLs().getNumPoints();
1054

    
1055
            for (int j = 0; j < num_p; j++) {
1056
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1057
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1058

    
1059
                if (threed) {
1060
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1061
                }
1062

    
1063
                _ind = _ind + dim;
1064
            }
1065
        }
1066

    
1067
        STRUCT resp;
1068
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1069
                        ((ConnectionJDBC)_conn).getConnection());
1070
        Object[] obj = new Object[5];
1071
        obj[0] = new NUMBER(geotype);
1072

    
1073
        if (hasSrid) {
1074
            obj[1] = new NUMBER(srid);
1075
        }
1076
        else {
1077
            obj[1] = null;
1078
        }
1079

    
1080
        obj[2] = null;
1081
        obj[3] = indices;
1082
        obj[4] = ords;
1083
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1084

    
1085
        return resp;
1086
    }
1087

    
1088
    private static STRUCT getMultiLineAsStruct(ArrayList lines, int srid,
1089
        boolean threed, IConnection _conn, boolean hasSrid)
1090
        throws SQLException {
1091
        /*
1092
        if (lines.size() == 1) {
1093
                return getOneLineStringAsStruct((LineString3D) lines.get(0), srid, threed, _conn);
1094
        }
1095
        */
1096
        int size = lines.size();
1097
        int geotype = 2006;
1098
        int dim = 2;
1099
        int acum = 0;
1100

    
1101
        if (threed) {
1102
            geotype = 3006;
1103
            dim = 3;
1104
        }
1105

    
1106
        NUMBER[] indices = new NUMBER[3 * size];
1107

    
1108
        for (int i = 0; i < size; i++) {
1109
            indices[3 * i] = new NUMBER(acum + 1);
1110
            indices[(3 * i) + 1] = new NUMBER(2);
1111
            indices[(3 * i) + 2] = new NUMBER(1);
1112
            acum = acum +
1113
                (dim * ((LineString3D) lines.get(i)).getLs().getNumPoints());
1114
        }
1115

    
1116
        int _ind = 0;
1117
        NUMBER[] ords = new NUMBER[acum];
1118

    
1119
        for (int i = 0; i < size; i++) {
1120
            LineString3D ls = (LineString3D) lines.get(i);
1121
            int num_p = ls.getLs().getNumPoints();
1122

    
1123
            for (int j = 0; j < num_p; j++) {
1124
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1125
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1126

    
1127
                if (threed) {
1128
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1129
                }
1130

    
1131
                _ind = _ind + dim;
1132
            }
1133
        }
1134

    
1135
        STRUCT resp;
1136
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1137
                        ((ConnectionJDBC)_conn).getConnection());
1138
        Object[] obj = new Object[5];
1139
        obj[0] = new NUMBER(geotype);
1140

    
1141
        if (hasSrid) {
1142
            obj[1] = new NUMBER(srid);
1143
        }
1144
        else {
1145
            obj[1] = null;
1146
        }
1147

    
1148
        obj[2] = null;
1149
        obj[3] = indices;
1150
        obj[4] = ords;
1151
        resp = new STRUCT(dsc,((ConnectionJDBC)_conn).getConnection(), obj);
1152

    
1153
        return resp;
1154
    }
1155

    
1156
    private static STRUCT getMultiPointAsStruct(Coordinate pnt, int srid,
1157
        boolean threed, IConnection _conn, boolean hasSrid)
1158
        throws SQLException {
1159
        int geotype = 2001;
1160
        int dim = 2;
1161

    
1162
        if (threed) {
1163
            geotype = 3001;
1164
            dim = 3;
1165
        }
1166

    
1167
        Object[] ords = new Object[3];
1168
        ords[0] = new NUMBER(pnt.x);
1169
        ords[1] = new NUMBER(pnt.y);
1170
        ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null; // ole ole y ole
1171

    
1172
        StructDescriptor ord_dsc = StructDescriptor.createDescriptor("MDSYS.SDO_POINT_TYPE",
1173
                        ((ConnectionJDBC)_conn).getConnection());
1174
        STRUCT ords_st = new STRUCT(ord_dsc, ((ConnectionJDBC)_conn).getConnection(), ords);
1175

    
1176
        STRUCT resp;
1177

    
1178
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1179
                        ((ConnectionJDBC)_conn).getConnection());
1180
        Object[] obj = new Object[5];
1181

    
1182
        obj[0] = new NUMBER(geotype);
1183

    
1184
        if (hasSrid) {
1185
            obj[1] = new NUMBER(srid);
1186
        }
1187
        else {
1188
            obj[1] = null;
1189
        }
1190

    
1191
        obj[2] = ords_st;
1192
        obj[3] = null;
1193
        obj[4] = null;
1194
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1195

    
1196
        return resp;
1197
    }
1198

    
1199
    /**
1200
     * Utility method to compute a circle's center and radius from three given points.
1201
     *
1202
     * @param points three points of a circumference
1203
     * @return a 2-item array with the circumference's center (Point2D) and radius (Double)
1204
     */
1205
    public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1206
        Object[] resp = new Object[2];
1207
        resp[0] = new Point2D.Double(0, 0);
1208
        resp[1] = new Double(0);
1209

    
1210
        double m11;
1211
        double m12;
1212
        double m13;
1213
        double m14;
1214

    
1215
        if (points.length != 3) {
1216
            logger.error("Needs 3 points (found " + points.length +
1217
                ") - circle cannot be computed.");
1218

    
1219
            // not a circle
1220
            return resp;
1221
        }
1222

    
1223
        double[][] a = new double[3][3];
1224

    
1225
        for (int i = 0; i < 3; i++) { // find minor 11
1226
            a[i][0] = points[i].getX();
1227
            a[i][1] = points[i].getY();
1228
            a[i][2] = 1;
1229
        }
1230

    
1231
        m11 = determinant(a, 3);
1232

    
1233
        for (int i = 0; i < 3; i++) { // find minor 12
1234
            a[i][0] = (points[i].getX() * points[i].getX()) +
1235
                (points[i].getY() * points[i].getY());
1236
            a[i][1] = points[i].getY();
1237
            a[i][2] = 1;
1238
        }
1239

    
1240
        m12 = determinant(a, 3);
1241

    
1242
        for (int i = 0; i < 3; i++) // find minor 13
1243
         {
1244
            a[i][0] = (points[i].getX() * points[i].getX()) +
1245
                (points[i].getY() * points[i].getY());
1246
            a[i][1] = points[i].getX();
1247
            a[i][2] = 1;
1248
        }
1249

    
1250
        m13 = determinant(a, 3);
1251

    
1252
        for (int i = 0; i < 3; i++) { // find minor 14
1253
            a[i][0] = (points[i].getX() * points[i].getX()) +
1254
                (points[i].getY() * points[i].getY());
1255
            a[i][1] = points[i].getX();
1256
            a[i][2] = points[i].getY();
1257
        }
1258

    
1259
        m14 = determinant(a, 3);
1260

    
1261
        Double resp_radius = new Double(0);
1262
        Point2D resp_center = new Point2D.Double(0, 0);
1263

    
1264
        if (m11 == 0) {
1265
            logger.error("Three points aligned - circle cannot be computed."); // not a circle
1266
        }
1267
        else {
1268
            double x = (0.5 * m12) / m11;
1269
            double y = (-0.5 * m13) / m11;
1270
            resp_center.setLocation(x, y);
1271
            resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11)));
1272
            resp[0] = resp_center;
1273
            resp[1] = resp_radius;
1274
        }
1275

    
1276
        return resp;
1277
    }
1278

    
1279
    /**
1280
     * Utility method to compute a matrix determinant
1281
     * @param a the matrix
1282
     * @param n matrix size
1283
     * @return the matrix's determinant
1284
     */
1285
    public static double determinant(double[][] a, int n) {
1286
        double resp = 0;
1287
        double[][] m = new double[3][3];
1288

    
1289
        if (n == 2) { // terminate recursion
1290
            resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1291
        }
1292
        else {
1293
            resp = 0;
1294

    
1295
            for (int j1 = 0; j1 < n; j1++) { // do each column
1296

    
1297
                for (int i = 1; i < n; i++) { // create minor
1298

    
1299
                    int j2 = 0;
1300

    
1301
                    for (int j = 0; j < n; j++) {
1302
                        if (j == j1) {
1303
                            continue;
1304
                        }
1305

    
1306
                        m[i - 1][j2] = a[i][j];
1307
                        j2++;
1308
                    }
1309
                }
1310

    
1311
                // sum (+/-)cofactor * minor
1312
                resp = resp +
1313
                    (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1314
            }
1315
        }
1316

    
1317
        return resp;
1318
    }
1319

    
1320
    private static int getSmallestContainerExcept(LineString3D ls,
1321
        ArrayList list, int self) {
1322
        int resp = -1;
1323
        ArrayList provList = new ArrayList();
1324

    
1325
        int size = list.size();
1326

    
1327
        for (int i = 0; i < self; i++) {
1328
            if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1329
                provList.add(new Integer(i));
1330
            }
1331
        }
1332

    
1333
        for (int i = (self + 1); i < size; i++) {
1334
            if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1335
                provList.add(new Integer(i));
1336
            }
1337
        }
1338

    
1339
        if (provList.size() == 0) {
1340
            // logger.debug("LineString is not contained by any other ls.");
1341
        }
1342
        else {
1343
            if (provList.size() == 1) {
1344
                resp = ((Integer) provList.get(0)).intValue();
1345
            }
1346
            else {
1347
                if (provList.size() == 2) {
1348
                    int ind_1 = ((Integer) provList.get(0)).intValue();
1349
                    int ind_2 = ((Integer) provList.get(1)).intValue();
1350
                    LineString3D ls1 = (LineString3D) list.get(ind_1);
1351
                    LineString3D ls2 = (LineString3D) list.get(ind_2);
1352

    
1353
                    if (lineString3DIsContainedBy(ls1, ls2)) {
1354
                        resp = ind_1;
1355
                    }
1356
                    else {
1357
                        resp = ind_2;
1358
                    }
1359
                }
1360
                else {
1361
                    // not so deep, sorry!
1362
                    // it's going to be a shell: resp = -1;
1363
                }
1364
            }
1365
        }
1366

    
1367
        return resp;
1368
    }
1369

    
1370
    private static int[] getIndicesOfShells(int[] containings) {
1371
        ArrayList resp = new ArrayList();
1372

    
1373
        for (int i = 0; i < containings.length; i++) {
1374
            if (containings[i] == -1) {
1375
                resp.add(new Integer(i));
1376
            }
1377
        }
1378

    
1379
        int size = resp.size();
1380
        int[] _resp = new int[size];
1381

    
1382
        for (int i = 0; i < size; i++) {
1383
            _resp[i] = ((Integer) resp.get(i)).intValue();
1384
        }
1385

    
1386
        return _resp;
1387
    }
1388

    
1389
    private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1390
        ArrayList resp = new ArrayList();
1391

    
1392
        for (int i = 0; i < containings.length; i++) {
1393
            int cont_by = containings[i];
1394

    
1395
            if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1396
                resp.add(new Integer(i));
1397
            }
1398
        }
1399

    
1400
        int size = resp.size();
1401
        int[] _resp = new int[size];
1402

    
1403
        for (int i = 0; i < size; i++) {
1404
            _resp[i] = ((Integer) resp.get(i)).intValue();
1405
        }
1406

    
1407
        return _resp;
1408
    }
1409

    
1410
    private static int[] getFinalContainings(int[] containings, int[] holes) {
1411
        ArrayList resp = new ArrayList();
1412

    
1413
        for (int i = 0; i < containings.length; i++) {
1414
            int cont_by = containings[i];
1415

    
1416
            if (isOneOf(cont_by, holes)) {
1417
                resp.add(new Integer(-1));
1418
            }
1419
            else {
1420
                resp.add(new Integer(cont_by));
1421
            }
1422
        }
1423

    
1424
        int size = resp.size();
1425
        int[] _resp = new int[size];
1426

    
1427
        for (int i = 0; i < size; i++) {
1428
            _resp[i] = ((Integer) resp.get(i)).intValue();
1429
        }
1430

    
1431
        return _resp;
1432
    }
1433

    
1434
    private static ArrayList getHolesOf(int ind, int[] final_contn,
1435
        ArrayList all) {
1436
        ArrayList resp_ind = new ArrayList();
1437

    
1438
        for (int i = 0; i < final_contn.length; i++) {
1439
            if (final_contn[i] == ind) {
1440
                resp_ind.add(new Integer(i));
1441
            }
1442
        }
1443

    
1444
        ArrayList resp = new ArrayList();
1445

    
1446
        for (int i = 0; i < resp_ind.size(); i++) {
1447
            Integer aux = (Integer) resp_ind.get(i);
1448
            resp.add(all.get(aux.intValue()));
1449
        }
1450

    
1451
        return resp;
1452
    }
1453

    
1454
    private static ArrayList getShellsIn(int[] final_contn, ArrayList all) {
1455
        ArrayList resp_ind = new ArrayList();
1456

    
1457
        for (int i = 0; i < final_contn.length; i++) {
1458
            if (final_contn[i] == -1) {
1459
                resp_ind.add(new Integer(i));
1460
            }
1461
        }
1462

    
1463
        ArrayList resp = new ArrayList();
1464

    
1465
        for (int i = 0; i < resp_ind.size(); i++) {
1466
            Integer aux = (Integer) resp_ind.get(i);
1467
            resp.add(all.get(aux.intValue()));
1468
        }
1469

    
1470
        return resp;
1471
    }
1472

    
1473
    /**
1474
     * This method tries to guess who is a shell and who is a hole from a set of
1475
     * linestrings.
1476
     *
1477
     * @param all_ls a set of linestrings to be checked.
1478
     *
1479
     * @return a 2-item array. the first is an arraylist of linestrings thought to be shells.
1480
     * the second is an array of arraylists containing the holes of each shell found in the
1481
     * first item
1482
     *
1483
     */
1484
    public static Object[] getHolesForShells(ArrayList all_ls) {
1485
        int no_of_ls = all_ls.size();
1486
        int[] containedby = new int[no_of_ls];
1487
        int[] shells;
1488
        int[] holes;
1489
        int[] final_cont;
1490

    
1491
        for (int i = 0; i < no_of_ls; i++) {
1492
            LineString3D ls_aux = (LineString3D) all_ls.get(i);
1493
            containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1494
        }
1495

    
1496
        shells = getIndicesOfShells(containedby);
1497
        holes = getIndicesOfHoles(containedby, shells);
1498
        final_cont = getFinalContainings(containedby, holes);
1499

    
1500
        // true shells:
1501
        shells = getIndicesOfShells(final_cont);
1502

    
1503
        ArrayList resp_shells = new ArrayList();
1504
        ArrayList resp_holes_for_shells = new ArrayList();
1505
        ArrayList aux_holes;
1506

    
1507
        for (int i = 0; i < shells.length; i++) {
1508
            resp_shells.add(all_ls.get(shells[i]));
1509
            aux_holes = getHolesOf(i, final_cont, all_ls);
1510
            resp_holes_for_shells.add(aux_holes);
1511
        }
1512

    
1513
        Object[] _resp = new Object[2];
1514
        _resp[0] = resp_shells;
1515
        _resp[1] = resp_holes_for_shells;
1516

    
1517
        return _resp;
1518
    }
1519

    
1520
    private static int getTotalSize(ArrayList listOfLists) {
1521
        int resp = 0;
1522

    
1523
        for (int i = 0; i < listOfLists.size(); i++) {
1524
            resp = resp + ((ArrayList) listOfLists.get(i)).size();
1525
        }
1526

    
1527
        return resp;
1528
    }
1529

    
1530
    // private static STRUCT // private static ArrayList getPolygonsEasily(FShape mpolygon) {
1531
    private static STRUCT getMultiPolygonAsStruct(FShape mpol, int srid,
1532
        boolean threed, IConnection _conn, boolean agu_bien, boolean hasSrid)
1533
        throws SQLException {
1534
        ArrayList all_ls = getPolygonsEasily(mpol);
1535
        Object[] hs = getHolesForShells(all_ls);
1536
        ArrayList sh = (ArrayList) hs[0];
1537
        ArrayList _ho = (ArrayList) hs[1];
1538
        ArrayList ho = reverseHoles(_ho);
1539

    
1540
        return getMultiPolygonAsStruct(sh, ho, srid, threed, _conn, agu_bien,
1541
            hasSrid);
1542
    }
1543

    
1544
    private static ArrayList reverseHoles(ArrayList hh) {
1545
        ArrayList resp = new ArrayList();
1546

    
1547
        for (int i = 0; i < hh.size(); i++) {
1548
            ArrayList item = (ArrayList) hh.get(i);
1549
            ArrayList newitem = new ArrayList();
1550

    
1551
            for (int j = 0; j < item.size(); j++) {
1552
                LineString3D ls = (LineString3D) item.get(j);
1553
                newitem.add(ls.createReverse());
1554
            }
1555

    
1556
            resp.add(newitem);
1557
        }
1558

    
1559
        return resp;
1560
    }
1561

    
1562
    private static STRUCT getMultiPolygonAsStruct(ArrayList shells,
1563
        ArrayList holes, int srid, boolean threed, IConnection _conn,
1564
        boolean explicito, boolean hasSrid) throws SQLException {
1565
        int t = 1003;
1566

    
1567
        if (explicito) {
1568
            t = 2003;
1569
        }
1570

    
1571
        int size = shells.size() + getTotalSize(holes);
1572
        int geotype = 2003;
1573
        if (size > 1) geotype = 2007;
1574

    
1575
        int dim = 2;
1576

    
1577
        if (threed) {
1578
            geotype = geotype + 1000;
1579
            dim = 3;
1580
        }
1581

    
1582
        NUMBER[] indices = new NUMBER[3 * size];
1583

    
1584
        int acum = 0;
1585
        int start_ind = 0;
1586

    
1587
        for (int i = 0; i < shells.size(); i++) {
1588
            indices[start_ind] = new NUMBER(acum + 1);
1589
            indices[start_ind + 1] = new NUMBER(1003);
1590
            indices[start_ind + 2] = new NUMBER(1);
1591
            start_ind = start_ind + 3;
1592
            acum = acum +
1593
                (dim * ((LineString3D) shells.get(i)).getLs().getNumPoints());
1594

    
1595
            ArrayList item_holes = (ArrayList) holes.get(i);
1596

    
1597
            for (int j = 0; j < item_holes.size(); j++) {
1598
                indices[start_ind] = new NUMBER(acum + 1);
1599
                indices[start_ind + 1] = new NUMBER(t); // 1003
1600
                indices[start_ind + 2] = new NUMBER(1);
1601
                start_ind = start_ind + 3;
1602
                acum = acum +
1603
                    (dim * ((LineString3D) item_holes.get(j)).getLs()
1604
                            .getNumPoints());
1605
            }
1606
        }
1607

    
1608
        int _ind = 0;
1609
        NUMBER[] ords = new NUMBER[acum];
1610

    
1611
        for (int i = 0; i < shells.size(); i++) {
1612
            // --------------------------------
1613
            LineString3D ls = (LineString3D) shells.get(i);
1614
            int num_p = ls.getLs().getNumPoints();
1615

    
1616
            for (int j = 0; j < num_p; j++) {
1617
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1618
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1619

    
1620
                if (threed) {
1621
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1622
                }
1623

    
1624
                _ind = _ind + dim;
1625
            }
1626

    
1627
            // -------------------------------
1628
            ArrayList item_holes = (ArrayList) holes.get(i);
1629

    
1630
            for (int j = 0; j < item_holes.size(); j++) {
1631
                ls = (LineString3D) item_holes.get(j);
1632
                num_p = ls.getLs().getNumPoints();
1633

    
1634
                for (int k = 0; k < num_p; k++) {
1635
                    ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
1636
                    ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1637

    
1638
                    if (threed) {
1639
                        ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1640
                    }
1641

    
1642
                    _ind = _ind + dim;
1643
                }
1644
            }
1645
        }
1646

    
1647
        STRUCT resp;
1648
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1649
                        ((ConnectionJDBC)_conn).getConnection());
1650
        Object[] obj = new Object[5];
1651
        obj[0] = new NUMBER(geotype);
1652

    
1653
        if (hasSrid) {
1654
            obj[1] = new NUMBER(srid);
1655
        }
1656
        else {
1657
            obj[1] = null;
1658
        }
1659

    
1660
        obj[2] = null;
1661
        obj[3] = indices;
1662
        obj[4] = ords;
1663

    
1664
        // String ind_str = printArray(indices);
1665
        // String ord_str = printArray(ords);
1666
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1667

    
1668
        return resp;
1669
    }
1670

    
1671
    public static String printArray(NUMBER[] array) {
1672
        String resp = "[ ";
1673

    
1674
        for (int i = 0; i < array.length; i++) {
1675
            resp = resp + " " + array[i].doubleValue() + " , ";
1676
        }
1677

    
1678
        resp = resp.substring(0, resp.length() - 2) + "]";
1679

    
1680
        return resp;
1681
    }
1682

    
1683
    private static boolean isOneOf(int ind, int[] list) {
1684
        for (int i = 0; i < list.length; i++) {
1685
            if (list[i] == ind) {
1686
                return true;
1687
            }
1688
        }
1689

    
1690
        return false;
1691
    }
1692

    
1693
    /**
1694
     * This method appends the geometries from a geometry collection in one STRUCT.
1695
     *
1696
     * @param co the geometry collection
1697
     * @param _forced_type a type that has to be used as the struct's main type
1698
     * @param _conn the connection
1699
     * @param _o_srid the geometry's SRS (oracle code)
1700
     * @param withSrid whether the SRS is non-NULL
1701
     * @param agu_bien whether to check holes' validity
1702
     * @param _isGeoCS whether the SRS is geodetic
1703
     * @return the STRUCT with the appended geometries
1704
     */
1705
    public static STRUCT appendGeometriesInStruct(FGeometryCollection co,
1706
        int _forced_type, IConnection _conn, String _o_srid, boolean withSrid,
1707
        boolean agu_bien, boolean _isGeoCS) {
1708
        IGeometry[] geoms = co.getGeometries();
1709
        int size = geoms.length;
1710
        STRUCT[] sts = new STRUCT[size];
1711

    
1712
        for (int i = 0; i < size; i++) {
1713
            sts[i] = OracleSpatialDriver.iGeometryToSTRUCT(geoms[i],
1714
                    _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS);
1715
        }
1716

    
1717
        if (size == 1) {
1718
            return sts[0];
1719
        }
1720

    
1721
        STRUCT aux = sts[0];
1722

    
1723
        for (int i = 1; i < size; i++) {
1724
            aux = appendStructs(aux, sts[i], _conn);
1725
        }
1726

    
1727
        return aux;
1728
    }
1729

    
1730
    private static STRUCT appendStructs(STRUCT st1, STRUCT st2, IConnection _conn) {
1731
        try {
1732
            ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1733
            int length_of_head_ords = _ords.getOracleArray().length;
1734

    
1735
            NUMBER gtype = new NUMBER(4 +
1736
                    (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1737
            NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1738
            NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1739

    
1740
            ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1741
            ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1742
            ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1743
            ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1744

    
1745
            Datum[] info = appendDatumArrays(info1.getOracleArray(),
1746
                    info2.getOracleArray(), length_of_head_ords);
1747

    
1748
            Datum[] ords = appendDatumArrays(ords1.getOracleArray(),
1749
                    ords2.getOracleArray(), 0);
1750

    
1751
            StructDescriptor dsc = st1.getDescriptor();
1752

    
1753
            Object[] atts = new Object[5];
1754
            atts[0] = gtype;
1755
            atts[1] = srid;
1756
            atts[2] = middle;
1757
            atts[3] = info;
1758
            atts[4] = ords;
1759

    
1760
            STRUCT resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), atts);
1761

    
1762
            return resp;
1763
        }
1764
        catch (SQLException sqle) {
1765
            logger.error("While appending structs: " + sqle.getMessage(), sqle);
1766
        }
1767

    
1768
        return null;
1769
    }
1770

    
1771
    private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
1772
        int offset) {
1773
        int head_l = head.length;
1774
        int tail_l = tail.length;
1775
        Datum[] resp = new Datum[head_l + tail_l];
1776

    
1777
        for (int i = 0; i < head_l; i++)
1778
            resp[i] = head[i];
1779

    
1780
        if (offset == 0) {
1781
            for (int i = 0; i < tail_l; i++)
1782
                resp[head_l + i] = tail[i];
1783
        }
1784
        else {
1785
            try {
1786
                for (int i = 0; i < tail_l; i++) {
1787
                    if ((i % 3) == 0) {
1788
                        resp[head_l + i] = new NUMBER(tail[i].intValue() +
1789
                                offset);
1790
                    }
1791
                    else {
1792
                        resp[head_l + i] = tail[i];
1793
                    }
1794
                }
1795
            }
1796
            catch (SQLException se) {
1797
                logger.error("Unexpected error: " + se.getMessage());
1798
            }
1799
        }
1800

    
1801
        return resp;
1802
    }
1803

    
1804
    /**
1805
     * Utility method to get an ineteger as a formatted string.
1806
     *
1807
     * @param n the integer
1808
     * @return the formatted string
1809
     */
1810
    public static String getFormattedInteger(int n) {
1811
        df.setGroupingUsed(true);
1812
        df.setGroupingSize(3);
1813
        dfs.setGroupingSeparator('.');
1814
        df.setDecimalFormatSymbols(dfs);
1815

    
1816
        return df.format(n);
1817
    }
1818

    
1819
    /**
1820
     * Tells whether these arrays belong to a rectangle polygon.
1821
     *
1822
     * @param info the struct's element info array
1823
     * @param ords the struct's coordinate array
1824
     * @return true if it is a rectangle polygon. false otherwise.
1825
     */
1826
    public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
1827
        try {
1828
            int[] infos = info.getIntArray();
1829

    
1830
            return ((infos[2] == 3) && (infos.length == 3));
1831
        }
1832
        catch (SQLException se) {
1833
            logger.error("While ckecking rectangle: " + se.getMessage(), se);
1834
        }
1835

    
1836
        return false;
1837
    }
1838

    
1839
    /**
1840
     * Utility method to deal with oracle info arrays.
1841
     */
1842
    public static ARRAY getDevelopedInfoArray(ARRAY info) {
1843
        ARRAY _resp = null;
1844

    
1845
        try {
1846
            Datum[] resp = new Datum[3];
1847
            Datum[] in = info.getOracleArray();
1848
            resp[0] = in[0];
1849
            resp[1] = in[1];
1850
            resp[2] = new NUMBER(1);
1851
            _resp = new ARRAY(info.getDescriptor(),
1852
                    info.getInternalConnection(), resp);
1853
        }
1854
        catch (SQLException se) {
1855
            logger.error("While creating ARRAY: " + se.getMessage(), se);
1856
        }
1857

    
1858
        return _resp;
1859
    }
1860

    
1861
    /**
1862
     * Utility method to deal with oracle coordinate arrays.
1863
     */
1864
    public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
1865
        ARRAY _resp = null;
1866

    
1867
        try {
1868
            Datum[] resp = new Datum[10];
1869
            Datum[] corners = ords.getOracleArray();
1870

    
1871
            // x
1872
            resp[0] = corners[0];
1873
            resp[2] = corners[2];
1874
            resp[4] = corners[2];
1875
            resp[6] = corners[0];
1876
            resp[8] = corners[0];
1877

    
1878
            // y
1879
            resp[1] = corners[1];
1880
            resp[3] = corners[1];
1881
            resp[5] = corners[3];
1882
            resp[7] = corners[3];
1883
            resp[9] = corners[1];
1884
            _resp = new ARRAY(ords.getDescriptor(),
1885
                    ords.getInternalConnection(), resp);
1886
        }
1887
        catch (SQLException se) {
1888
            logger.error("While creating ARRAY: " + se.getMessage(), se);
1889
        }
1890

    
1891
        return _resp;
1892
    }
1893

    
1894
    /**
1895
     * utility method to convert a STRUCT into a GeneralPathX
1896
     * @param aux the struct's datum array
1897
     * @return the GeneralPathX instance created
1898
     */
1899
    public static GeneralPathX structToGPX(Datum[] aux) {
1900
        GeneralPathX resp = new GeneralPathX();
1901
        ARRAY infoARRAY = null;
1902
        ARRAY ordsARRAY = null;
1903
        Datum[] info_array = null;
1904
        Datum[] ords_array = null;
1905
        int info_array_size = 0;
1906
        int[] start_ind;
1907
        int[] end_ind;
1908
        int dims = 0;
1909
        boolean next_must_do_first = true;
1910

    
1911
        try {
1912
            infoARRAY = (ARRAY) aux[3];
1913
            ordsARRAY = (ARRAY) aux[4];
1914

    
1915
            if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
1916
                infoARRAY = getDevelopedInfoArray(infoARRAY);
1917
                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
1918
            }
1919

    
1920
            dims = ((NUMBER) aux[0]).intValue() / 1000;
1921

    
1922
            if (dims == 0) {
1923
                dims = 2;
1924
            }
1925

    
1926
            info_array = (Datum[]) infoARRAY.getOracleArray();
1927
            ords_array = (Datum[]) ordsARRAY.getOracleArray();
1928
            info_array_size = info_array.length / 3;
1929

    
1930
            int last_index = ords_array.length - dims + 1;
1931

    
1932
            // set indices:
1933
            start_ind = new int[info_array_size];
1934
            end_ind = new int[info_array_size];
1935

    
1936
            for (int i = 0; i < info_array_size; i++)
1937
                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
1938

    
1939
            for (int i = 0; i < (info_array_size - 1); i++)
1940
                end_ind[i] = start_ind[i + 1] - 1;
1941

    
1942
            end_ind[info_array_size - 1] = last_index;
1943

    
1944
            int lineType = PathIterator.SEG_LINETO;
1945

    
1946
            if (end_ind[0] == 0) { // collection of paths
1947

    
1948
                for (int i = 1; i < info_array_size; i++) {
1949
                    lineType = getLineToType(info_array, i);
1950

    
1951
                    // -----------------------
1952
                    if (end_ind[i] == (start_ind[i] - 1))
1953
                            lineType = PathIterator.SEG_MOVETO;
1954
                    // -----------------------
1955

    
1956
                    next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
1957
                            end_ind[i] - 1, ords_array, dims, lineType,
1958
                            (i == 1) || (lineType == PathIterator.SEG_MOVETO),
1959
                            next_must_do_first);
1960
                }
1961
            } else {
1962
                // standard case, do the moveto always
1963
                for (int i = 0; i < info_array_size; i++) {
1964
                    lineType = getLineToType(info_array, i);
1965
                    addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1,
1966
                        ords_array, dims, lineType, true, true);
1967
                }
1968
            }
1969

    
1970
            // boolean do_the_moves = true;
1971
        }
1972
        catch (SQLException se) {
1973
            logger.error("While creating GPX: " + se.getMessage(), se);
1974
        }
1975

    
1976
        return resp;
1977
    }
1978

    
1979
    private static int getLineToType(Datum[] infos, int i) {
1980
        int resp = PathIterator.SEG_LINETO;
1981

    
1982
        try {
1983
            if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) {
1984
                resp = PathIterator.SEG_QUADTO;
1985
            }
1986
        }
1987
        catch (SQLException e) {
1988
            logger.error("While getting line-to type: " + e.getMessage() +
1989
                " (returned SEG_LINETO)");
1990
        }
1991

    
1992
        return resp;
1993
    }
1994

    
1995
    private static boolean addOrdsToGPX(GeneralPathX gpx, int zero_based_start,
1996
        int zero_based_include_end, Datum[] ords, int d, int ltype,
1997
        boolean do_the_move, boolean must_do_first) {
1998
        int length = ords.length;
1999
        boolean return_following_must_do_first = true;
2000

    
2001
        double x = ((NUMBER) ords[zero_based_start]).doubleValue();
2002
        double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
2003

    
2004
        if (must_do_first) {
2005
            if (do_the_move) {
2006
                gpx.moveTo(x, y);
2007
            }
2008
            else {
2009
                gpx.lineTo(x, y);
2010
            }
2011
        }
2012

    
2013
        int ind = 1;
2014

    
2015
        int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2016
        int indx;
2017
        int indx2;
2018

    
2019
        if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2020

    
2021
            double x2;
2022
            double y2;
2023

    
2024
            while (ind < size) {
2025
                indx = zero_based_start + (ind * d);
2026
                x = ((NUMBER) ords[indx]).doubleValue();
2027
                y = ((NUMBER) ords[indx + 1]).doubleValue();
2028

    
2029
                indx2 = zero_based_start + ((ind + 1) * d);
2030

    
2031
                if (indx >= length) {
2032
                    indx2 = zero_based_start;
2033
                }
2034

    
2035
                x2 = ((NUMBER) ords[indx2]).doubleValue();
2036
                y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
2037
                gpx.quadTo(x, y, x2, y2);
2038
                ind++;
2039
                ind++;
2040
            }
2041

    
2042
            return_following_must_do_first = false;
2043
        }
2044
        else { // PathIterator.SEG_LINETO (interpretation = 1)
2045

    
2046
            while (ind < size) {
2047
                indx = zero_based_start + (ind * d);
2048
                x = ((NUMBER) ords[indx]).doubleValue();
2049
                y = ((NUMBER) ords[indx + 1]).doubleValue();
2050
                gpx.lineTo(x, y);
2051
                ind++;
2052
            }
2053
        }
2054

    
2055
        return return_following_must_do_first;
2056
    }
2057

    
2058
    /**
2059
     * Utility method. Gets FShape type from oracle geometry type.
2060
     * @param otype
2061
     * @return FShape type
2062
     */
2063
    public static int oracleGTypeToFShapeType(int otype) {
2064
        switch (otype) {
2065
        case ORACLE_GTYPE_UNKNOWN:
2066
            return FShape.NULL;
2067

    
2068
        case ORACLE_GTYPE_POINT:
2069
        case ORACLE_GTYPE_MULTIPOINT:
2070
            return FShape.POINT;
2071

    
2072
        case ORACLE_GTYPE_LINE:
2073
        case ORACLE_GTYPE_MULTILINE:
2074
            return FShape.LINE;
2075

    
2076
        case ORACLE_GTYPE_POLYGON:
2077
        case ORACLE_GTYPE_MULTIPOLYGON:
2078
            return FShape.POLYGON;
2079

    
2080
        case ORACLE_GTYPE_COLLECTION:
2081
            return FShape.MULTI;
2082
        }
2083

    
2084
        logger.warn("Unknown oracle geometry type: " + otype);
2085

    
2086
        return FShape.NULL;
2087
    }
2088

    
2089
    /**
2090
     * Utility method to get struct's type.
2091
     * @param the_data the struct's datum array
2092
     * @return the struct type
2093
     */
2094
    public static int getStructType(Datum[] the_data) {
2095
        int resp = -1;
2096

    
2097
        try {
2098
            resp = ((NUMBER) the_data[0]).intValue() % 1000;
2099
        }
2100
        catch (SQLException se) {
2101
            logger.error("Error: " + se.getMessage(), se);
2102
        }
2103

    
2104
        return resp;
2105
    }
2106

    
2107
    /**
2108
     * Utility method to get struct's SRID.
2109
     * @param the_data the struct's datum array
2110
     * @return the struct0's SRID
2111
     */
2112
    public static int getStructSRID(Datum[] the_data) {
2113
        int resp = -1;
2114

    
2115
        try {
2116
            resp = ((NUMBER) the_data[1]).intValue();
2117
        }
2118
        catch (SQLException se) {
2119
            logger.error("Error: " + se.getMessage(), se);
2120
        }
2121

    
2122
        return resp;
2123
    }
2124

    
2125
    /**
2126
     * Utility method to find out if  a struct is a circle.
2127
     *
2128
     * @param the_data the struct's datum array
2129
     * @return whether it is a circle
2130
     */
2131
    public static boolean isCircle(Datum[] the_data) {
2132
        int[] info = null;
2133

    
2134
        try {
2135
            info = ((ARRAY) the_data[3]).getIntArray();
2136
        }
2137
        catch (SQLException se) {
2138
            logger.error("While cheking circle: " + se.getMessage(), se);
2139

    
2140
            return false;
2141
        }
2142

    
2143
        if (info == null) {
2144
            return false;
2145
        }
2146

    
2147
        boolean resp = ((info.length == 3) && (info[2] == 4));
2148

    
2149
        return resp;
2150
    }
2151

    
2152
    /**
2153
     * Gets the struct's dimension size.
2154
     * @param st the struct
2155
     * @return the structs dimension
2156
     */
2157
    public static int getStructDimensions(STRUCT st) {
2158
        int resp = -1;
2159

    
2160
        try {
2161
            resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2162
        }
2163
        catch (SQLException se) {
2164
            logger.error("Error: " + se.getMessage(), se);
2165
        }
2166

    
2167
        if (resp < 2) {
2168
            resp = 2;
2169
        }
2170

    
2171
        return resp;
2172
    }
2173

    
2174
    /**
2175
     * Gets a struct's coordinates array.
2176
     * @param the_data the struct's datum array
2177
     * @return the coordinates array
2178
     */
2179
    public static double[] getOrds(Datum[] the_data) {
2180
        double[] resp = null;
2181

    
2182
        try {
2183
            ARRAY aux = (ARRAY) the_data[4];
2184

    
2185
            if (aux == null) {
2186
                return null;
2187
            }
2188

    
2189
            resp = aux.getDoubleArray();
2190
        }
2191
        catch (SQLException se) {
2192
            logger.error("While getting ordinates: " + se.getMessage(), se);
2193
        }
2194

    
2195
        return resp;
2196
    }
2197

    
2198
    /**
2199
     * Utility method to create a struct with the given data.
2200
     * @param type struct type
2201
     * @param srid coordinate system
2202
     * @param info element info array
2203
     * @param ords coordinates array
2204
     * @param conn connection
2205
     * @return the created struct
2206
     */
2207
    public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info,
2208
        Datum[] ords, Connection conn) {
2209
        try {
2210
            StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
2211
                    conn);
2212
            Object[] obj = new Object[5];
2213
            obj[0] = type;
2214
            obj[1] = srid;
2215
            obj[2] = null;
2216
            obj[3] = info;
2217
            obj[4] = ords;
2218

    
2219
            return new STRUCT(dsc, conn, obj);
2220
        }
2221
        catch (SQLException se) {
2222
            logger.error("While creating STRUCT: " + se.getMessage(), se);
2223
        }
2224

    
2225
        return null;
2226
    }
2227

    
2228
    public static String getDimInfoAsString(ARRAY dim_info) {
2229
            String resp = "DIMENSIONS: ";
2230

    
2231
        if (dim_info == null) {
2232
            return "NULL" + "\n";
2233
        }
2234
        else {
2235
                try {
2236
                                Datum[] da = dim_info.getOracleArray();
2237
                                int size = da.length;
2238
                                resp = resp + size + "\n";
2239
                                for (int i = 0; i < size; i++) {
2240
                                        STRUCT dim_itemx = (STRUCT) da[i];
2241
                                        Object[] dim_desc = dim_itemx.getAttributes();
2242
                                        resp = resp + "DIMENSION " + i + ": " + ", NAME: "
2243
                                                        + dim_desc[0].toString() + ", MIN: "
2244
                                                        + dim_desc[1].toString() + ", MAX: "
2245
                                                        + dim_desc[2].toString() + ", TOL: "
2246
                                                        + dim_desc[3].toString();
2247
                                        if (i != (size -1)) {
2248
                                                resp = resp + "\n";
2249
                                        }
2250
                                }
2251
                        } catch (Exception ex) {
2252
                                return "ERROR: " + ex.getMessage() + "\n";
2253
                        }
2254
        }
2255
        return resp;
2256
    }
2257

    
2258
    public static STRUCT reprojectGeometry(IConnection conn, STRUCT fromStruct, String toSrid) {
2259

    
2260
            String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2261
            STRUCT resp = null;
2262

    
2263
            try {
2264
                        PreparedStatement _st = ((ConnectionJDBC)conn).getConnection().prepareStatement(qry);
2265
                        _st.setObject(1, fromStruct);
2266
                        ResultSet _rs = _st.executeQuery();
2267

    
2268
                        if (_rs.next()) {
2269
                                resp = (STRUCT) _rs.getObject(1);
2270
                        } else {
2271
                                logger.error("While executing reprojection: empty resultset (?)");
2272
                                return fromStruct;
2273
                        }
2274
                } catch (Exception ex) {
2275
                        logger.error("While reprojecting: " + ex.getMessage());
2276
                        return fromStruct;
2277
                }
2278

    
2279
        if (resp == null) {
2280
                return fromStruct;
2281
        } else {
2282
                return resp;
2283
        }
2284
    }
2285
    
2286
    
2287
    public static void printStruct(STRUCT st) {
2288
            
2289
        logger.debug("----------------------------------------------");
2290
        logger.debug("-- 16 FEBRERO 2009 ---------------------------");
2291
        logger.debug("----------------------------------------------");
2292

    
2293
        try {
2294
            Object[] att = st.getAttributes();
2295
            int l = att.length;
2296

    
2297
            for (int i = 0; i < l; i++) {
2298
                    if (att[i] != null) {
2299
                            if (att[i] instanceof ARRAY) {
2300
                                    ARRAY arr = (ARRAY) att[i];
2301
                                    logger.debug("ATT " + i + ": ");
2302
                                    printARRAY(arr);
2303
                            } else {
2304
                                    logger.debug("ATT " + i + ": " + att[i].toString());
2305
                            }
2306
                    logger.debug("----------------------------------------------");
2307
                    }
2308
            }
2309
        }
2310
        catch (Exception ex) {
2311
                logger.debug("-- Error: " + ex.getMessage());
2312
        }
2313

    
2314
    }
2315

    
2316
        private static void printARRAY(ARRAY arr) throws Exception {
2317
                
2318
                int[] intarr = arr.getIntArray();
2319
                if (intarr == null) {
2320
                        float[] floarr = arr.getFloatArray();
2321
                        if (floarr == null) {
2322
                                logger.debug("INT NULL y FLOAT NULL (?)");
2323
                        } else {
2324
                                int len = floarr.length;
2325
                                for (int i=0; i<len; i++) {
2326
                                        if (Math.min(i, (len - i)) < 20) {
2327
                                                logger.debug("" + floarr[i]);
2328
                                        }
2329
                                }
2330
                        }
2331
                        
2332
                } else {
2333
                        int len = intarr.length;
2334
                        for (int i=0; i<len; i++) {
2335
                                if (Math.min(i, (len - i)) < 20) {
2336
                                        logger.debug("" + intarr[i]);
2337
                                }
2338
                        }
2339
                }
2340
        }
2341

    
2342
    /**
2343
     * Utility method. Gets FShape type from oracle geometry type.
2344
     * @param otype
2345
     * @return FShape type
2346
     */
2347
    public static int oracleGTypeToFShapeType(int otype, boolean complex) {
2348
            
2349
            int resp = FShape.NULL;
2350
            
2351
            if (complex) {
2352
                    
2353
                    switch (otype) {
2354
                    case ORACLE_GTYPE_COMPLEX_VOIDED_POLYON:
2355
                    case ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON:
2356
                            resp = FShape.POLYGON;
2357
                            break;
2358
                    case ORACLE_GTYPE_COMPLEX_COMPOUND_LINE:
2359
                            resp = FShape.LINE;
2360
                            break;
2361
                    }
2362

    
2363
            } else {
2364

    
2365
                    // =========== not complex =================
2366
            switch (otype) {
2367
            case ORACLE_GTYPE_UNKNOWN:
2368
                    resp = FShape.NULL;
2369
                break;
2370

    
2371
            case ORACLE_GTYPE_POINT:
2372
            case ORACLE_GTYPE_MULTIPOINT:
2373
                    resp = FShape.POINT;
2374
                break;
2375

    
2376
            case ORACLE_GTYPE_LINE:
2377
            case ORACLE_GTYPE_MULTILINE:
2378
                    resp = FShape.LINE;
2379
                break;
2380

    
2381
            case ORACLE_GTYPE_POLYGON:
2382
            case ORACLE_GTYPE_MULTIPOLYGON:
2383
                    resp = FShape.POLYGON;
2384
                break;
2385

    
2386
            case ORACLE_GTYPE_COLLECTION:
2387
                    resp = FShape.MULTI;
2388
                break;
2389
            }
2390
                    // =========== not complex =================
2391
            }
2392
            
2393
            if (resp == FShape.NULL) {
2394
                    logger.error("Unknown oracle geometry type: " + otype);
2395
            }
2396
        return resp;
2397
    }
2398
    
2399
        public static void removeStructFields(DBLayerDefinition def, String[] arr) {
2400
                
2401
                FieldDescription[] flds = def.getFieldsDesc();
2402
                ArrayList aux = new ArrayList();
2403
                
2404
                for (int i=0; i<flds.length; i++) {
2405
                        if (!isOneOfThese(flds[i].getFieldName(), arr)) {
2406
                                aux.add(flds[i]);
2407
                        }
2408
                }
2409
                
2410
                FieldDescription[] flds_new =
2411
                        (FieldDescription[]) aux.toArray(new FieldDescription[0]);
2412
                def.setFieldsDesc(flds_new);
2413
        }
2414
        
2415
        private static boolean isOneOfThese(String name, String[] arr) {
2416

    
2417
                for (int i=0; i<arr.length; i++) {
2418
                                if (arr[i].compareToIgnoreCase(name) == 0) return true; 
2419
                        }
2420
                return false;
2421
        }
2422
        
2423
        public static void setUpperCase(DBLayerDefinition def) {
2424
                String aux = def.getCatalogName();
2425
                if (aux != null) def.setCatalogName(aux.toUpperCase());
2426

    
2427
                aux = def.getSchema();
2428
                if (aux != null) def.setSchema(aux.toUpperCase());
2429
        }
2430
        
2431
    public static boolean hasSeveralGeometryTypes(ArrayList tt, boolean are_dims) {
2432
        if (tt.size() == 0) {
2433
            return false;
2434
        }
2435

    
2436
        HashMap m = new HashMap();
2437

    
2438
        for (int i = 0; i < tt.size(); i++) {
2439
            Integer integ = (Integer) tt.get(i);
2440
            int val = integ.intValue();
2441

    
2442
            if ((val == 4) && (!are_dims)) {
2443
                return true;
2444
            }
2445

    
2446
            m.put("" + (val % 4), "a type");
2447
        }
2448

    
2449
        Iterator iter = m.keySet().iterator();
2450
        iter.next();
2451

    
2452
        return iter.hasNext();
2453
    }
2454

    
2455
    public static void showMemory() {
2456
        Runtime r = Runtime.getRuntime();
2457
        long mem = r.totalMemory() - r.freeMemory();
2458
        logger.info("Total memory : " + mem);
2459
    }
2460
    
2461

    
2462
    
2463
    private static double[] getIndDoublesModule(double[] input, int ind, int n) {
2464
        int size = input.length / n;
2465
        double[] resp = new double[size];
2466

    
2467
        for (int i = 0; i < size; i++) {
2468
            resp[i] = input[(i * n) + ind];
2469
        }
2470

    
2471
        return resp;
2472
    }
2473
    
2474
    private static double[] getIndBigDecimalModule(double[] input, int ind, int n) {
2475
        int size = input.length / n;
2476
        double[] resp = new double[size];
2477

    
2478
        for (int i = 0; i < size; i++) {
2479
            resp[i] = input[(i * n) + ind];
2480
        }
2481

    
2482
        return resp;
2483
    }
2484
    
2485
    public static IGeometry getFMapGeometryMultipolygon(Datum[] the_data, int dim) {
2486
        IGeometry ig = null;
2487

    
2488
        if (OracleSpatialUtils.isCircle(the_data)) {
2489
            ig = getCircleFromStruct(the_data);
2490
        }
2491
        else {
2492
            GeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
2493

    
2494
            if (dim == 2) {
2495
                ig = ShapeFactory.createPolygon2D(gpx);
2496
            }
2497
            else {
2498
                double[] ords = null;
2499

    
2500
                try {
2501
                    ords = ((ARRAY) the_data[4]).getDoubleArray();
2502
                }
2503
                catch (SQLException se) {
2504
                    logger.error("While getting ordinates: " + se.getMessage(),
2505
                        se);
2506
                }
2507

    
2508
                double[] z = getIndBigDecimalModule(ords, 2, dim);
2509
                ig = ShapeFactory.createPolygon3D(gpx, z);
2510
            }
2511
        }
2512

    
2513
        return ig;
2514
    }
2515
    
2516
    private static IGeometry getCircleFromStruct(Datum[] the_data) {
2517
        double[] threep = null;
2518

    
2519
        try {
2520
            threep = ((ARRAY) the_data[4]).getDoubleArray();
2521
        }
2522
        catch (SQLException se) {
2523
            logger.error("While getting ords from struct: " + se.getMessage(),
2524
                se);
2525

    
2526
            return new FNullGeometry();
2527
        }
2528

    
2529
        Point2D[] three = new Point2D.Double[3];
2530
        three[0] = new Point2D.Double(threep[0], threep[1]);
2531
        three[1] = new Point2D.Double(threep[2], threep[3]);
2532
        three[2] = new Point2D.Double(threep[4], threep[5]);
2533

    
2534
        Object[] cent_rad = OracleSpatialUtils.getCenterAndRadiousOfCirc(three);
2535

    
2536
        Point2D cent = (Point2D) cent_rad[0];
2537
        double radius = ((Double) cent_rad[1]).doubleValue();
2538

    
2539
        IGeometry circ = ShapeFactory.createCircle(cent, radius);
2540

    
2541
        return circ;
2542
    }
2543
    
2544
    public static IGeometry getFMapGeometryMultiLineString(Datum[] the_data, int dim) {
2545
        GeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
2546
        IGeometry ig = null;
2547
        double[] ords = null;
2548

    
2549
        if (dim == 2) {
2550
            ig = ShapeFactory.createPolyline2D(gpx);
2551
        }
2552
        else {
2553
            ords = OracleSpatialUtils.getOrds(the_data);
2554

    
2555
            double[] z = getIndBigDecimalModule(ords, 2, dim);
2556
            ig = ShapeFactory.createPolyline3D(gpx, z);
2557
        }
2558

    
2559
        return ig;
2560
    }
2561

    
2562
    
2563
    public static IGeometry getFMapGeometryPoint(Datum[] the_data, int dim) {
2564
        double[] ords = OracleSpatialUtils.getOrds(the_data);
2565

    
2566
        if (ords == null) { // sdo_point
2567

    
2568
            return getFMapGeometrySdoPoint(the_data, dim);
2569
        }
2570

    
2571
        IGeometry ig = null;
2572
        int total_size = ords.length;
2573
        int no_po = total_size / dim;
2574
        double[] x = new double[no_po];
2575
        double[] y = new double[no_po];
2576
        double[] z = new double[no_po];
2577

    
2578
        for (int i = 0; i < no_po; i++) {
2579
            x[i] = ords[i * dim]; // pp[i].getX();
2580
            y[i] = ords[(i * dim) + 1];
2581

    
2582
            if (dim >= 3) {
2583
                z[i] = ords[(i * dim) + 2];
2584
            }
2585
        }
2586

    
2587
        if (dim == 2) {
2588
            if (no_po == 1) {
2589
                ig = ShapeFactory.createPoint2D(x[0], y[0]);
2590
            }
2591
            else {
2592
                ig = ShapeFactory.createMultipoint2D(x, y);
2593
            }
2594
        }
2595
        else {
2596
            if (no_po == 1) {
2597
                ig = ShapeFactory.createPoint3D(x[0], y[0], z[0]);
2598
            }
2599
            else {
2600
                ig = ShapeFactory.createMultipoint3D(x, y, z);
2601
            }
2602
        }
2603

    
2604
        return ig;
2605
    }
2606
    
2607
    public static IGeometry getFMapGeometrySdoPoint(Datum[] the_data, int d) {
2608
        double x = 0;
2609
        double y = 0;
2610
        double z = 0;
2611

    
2612
        try {
2613
            Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
2614
            x = ((NUMBER) aux[0]).doubleValue();
2615
            y = ((NUMBER) aux[1]).doubleValue();
2616

    
2617
            if (d > 2) {
2618
                z = ((NUMBER) aux[2]).doubleValue();
2619
            }
2620
        }
2621
        catch (SQLException se) {
2622
            logger.error("While getting sdo point ordinates: " +
2623
                se.getMessage(), se);
2624
        }
2625

    
2626
        IGeometry ig = null;
2627

    
2628
        if (d == 2) {
2629
            ig = ShapeFactory.createPoint2D(x, y);
2630
        }
2631
        else {
2632
            ig = ShapeFactory.createPoint3D(x, y, z);
2633
        }
2634

    
2635
        return ig;
2636
    }
2637

    
2638
    
2639
    public static boolean isActuallyACollection(Datum[] the_data) {
2640
        int[] info = null;
2641

    
2642
        try {
2643
            ARRAY aux = (ARRAY) the_data[3];
2644

    
2645
            if (aux == null) {
2646
                return false;
2647
            }
2648

    
2649
            info = aux.getIntArray();
2650
        }
2651
        catch (SQLException se) {
2652
            logger.error("While checking collection: " + se.getMessage());
2653
            return false;
2654
        }
2655

    
2656
        if (info == null) {
2657
            return false; // sdo_point
2658
        }
2659

    
2660
        int size = info.length / 3;
2661

    
2662
        if (size == 1) {
2663
            return false;
2664
        }
2665

    
2666
        if (size == 2) {
2667
            return ((info[1] % 1000) != (info[4] % 1000)) &&
2668
            ( ! ((info[1] == 1005) && (info[4] == 2)) );
2669
        }
2670

    
2671
        int second = info[4] % 1000;
2672
        int item = 0;
2673

    
2674
        for (int i = 2; i < size; i++) {
2675
                item = info[(i * 3) + 1] % 1000;
2676
            if ((item != second) &&
2677
                            ( ! ((item == 5) && (second == 2)) )
2678
                            ) {
2679
                return true;
2680
            }
2681
        }
2682

    
2683
        return false;
2684
    }
2685

    
2686
    
2687
    public static Datum[] updateIndexes(Datum[] info) {
2688
        int size = info.length / 3;
2689
        NUMBER[] resp = new NUMBER[3 * size];
2690

    
2691
        try {
2692
            int rest = info[0].intValue() - 1;
2693

    
2694
            for (int i = 0; i < size; i++) {
2695
                resp[3 * i] = new NUMBER(info[3 * i].intValue() - rest);
2696
                resp[(3 * i) + 1] = new NUMBER(info[(3 * i) + 1].intValue());
2697
                resp[(3 * i) + 2] = new NUMBER(info[(3 * i) + 2].intValue());
2698
            }
2699
        }
2700
        catch (SQLException se) {
2701
            logger.error("Unexpected error: " + se.getMessage());
2702
        }
2703

    
2704
        return resp;
2705
    }
2706
    
2707
    public static double[] getSubSet(double[] all, int first_inc, int last_inc) {
2708
        double[] resp = new double[last_inc - first_inc + 1];
2709

    
2710
        for (int i = first_inc; i <= last_inc; i++) {
2711
            resp[i - first_inc] = all[i];
2712
        }
2713

    
2714
        return resp;
2715
    }
2716
    
2717
    public static Object[] getOrdOfGroups(Datum[] all, Object[] groups) throws SQLException {
2718
        Object[] resp = new Object[groups.length];
2719

    
2720
        if (resp.length == 1) {
2721
            resp[0] = all;
2722

    
2723
            return resp;
2724
        }
2725

    
2726
        int ind = 0;
2727
        Datum[] aux = (Datum[]) groups[1];
2728
        int _end = aux[0].intValue() - 2;
2729
        Datum[] ord_aux = getSubSet(all, 0, _end);
2730

    
2731
        int _start = _end + 1;
2732
        resp[ind] = ord_aux;
2733
        ind++;
2734

    
2735
        for (int i = 2; i < groups.length; i++) {
2736
            aux = (Datum[]) groups[i];
2737
            _end = aux[0].intValue() - 2;
2738
            ord_aux = getSubSet(all, _start, _end);
2739
            resp[ind] = ord_aux;
2740
            ind++;
2741
            _start = _end + 1;
2742
        }
2743

    
2744
        // last
2745
        _end = all.length - 1;
2746
        ord_aux = getSubSet(all, _start, _end);
2747
        resp[groups.length - 1] = ord_aux;
2748

    
2749
        return resp;
2750
    }
2751
    
2752
    
2753
    
2754
    public static Object[] getOrdOfGroups(double[] all, Object[] groups) {
2755
        Object[] resp = new Object[groups.length];
2756

    
2757
        if (resp.length == 1) {
2758
            resp[0] = all;
2759

    
2760
            return resp;
2761
        }
2762

    
2763
        int ind = 0;
2764
        int[] aux = (int[]) groups[1];
2765
        int _end = aux[0] - 2;
2766
        double[] ord_aux = getSubSet(all, 0, _end);
2767

    
2768
        int _start = _end + 1;
2769
        resp[ind] = ord_aux;
2770
        ind++;
2771

    
2772
        for (int i = 2; i < groups.length; i++) {
2773
            aux = (int[]) groups[i];
2774
            _end = aux[0] - 2;
2775
            ord_aux = getSubSet(all, _start, _end);
2776
            resp[ind] = ord_aux;
2777
            ind++;
2778
            _start = _end + 1;
2779
        }
2780

    
2781
        // last
2782
        _end = all.length - 1;
2783
        ord_aux = getSubSet(all, _start, _end);
2784
        resp[groups.length - 1] = ord_aux;
2785

    
2786
        return resp;
2787
    }
2788
    
2789
    
2790
    public static Object[] groupByElement(int[] all_elem) {
2791
        ArrayList resp = new ArrayList();
2792

    
2793
        int size = all_elem.length / 3;
2794

    
2795
        int[] aux = getNthGroupOfThree(all_elem, 0);
2796

    
2797
        int[] newaux;
2798
        int i = 1;
2799

    
2800
        while (i < size) {
2801
            newaux = getNthGroupOfThree(all_elem, i);
2802

    
2803
            if (newaux[0] == aux[0]) {
2804
                // aux[2] says how many components
2805
                for (int j = 0; j < aux[2]; j++) {
2806
                    aux = appendIntArrays(aux,
2807
                            getNthGroupOfThree(all_elem, j + i));
2808
                }
2809

    
2810
                resp.add(aux);
2811
                i = i + aux[2];
2812
                aux = getNthGroupOfThree(all_elem, i);
2813
            }
2814
            else {
2815
                if (newaux[1] == 2003) {
2816
                    aux = appendIntArrays(aux, newaux);
2817
                }
2818
                else {
2819
                    resp.add(aux);
2820
                    aux = getNthGroupOfThree(all_elem, i);
2821
                }
2822
            }
2823

    
2824
            i++;
2825
        }
2826

    
2827
        resp.add(aux);
2828

    
2829
        return resp.toArray();
2830
    }
2831
    
2832
    public static boolean isSimpleCollectionOfLines(Datum[] all_elem) {
2833
            
2834
            try {
2835
                int size = all_elem.length;
2836
                if (all_elem[1].intValue() != 4) return false;
2837
                int size3 = size / 3;
2838
                
2839
                for (int i=1; i<size3; i++) {
2840
                        if (all_elem[3 * i + 1].intValue() != 2) return false; 
2841
                }
2842
                return true;
2843
                
2844
            } catch (SQLException ex) {
2845
                    logger.error("While is simple line collection: " + ex.getMessage());
2846
            }
2847
            
2848
            return false;
2849
    }
2850
    
2851
    public static Datum[] removeThreeFirst(Datum[] elem) {
2852
            int sz = elem.length;
2853
            Datum[] resp = new Datum[sz - 3];
2854
            for (int i=3; i<sz; i++) resp[i - 3] = elem[i];
2855
            return resp;
2856
    }
2857
    
2858
    public static Object[] groupByElement(Datum[] all_elem) {
2859
            
2860
            if (isSimpleCollectionOfLines(all_elem)) {
2861
                    Object[] r = new Object[1];
2862
                    r[0] = removeThreeFirst(all_elem);
2863
                    return r;
2864
            }
2865
            
2866
        ArrayList resp = new ArrayList();
2867

    
2868
        int size = all_elem.length / 3;
2869

    
2870
        Datum[] aux = getNthGroupOfThree(all_elem, 0);
2871

    
2872
        Datum[] newaux;
2873
        int i = 1;
2874
        boolean add_last_time = true;
2875

    
2876
        try {
2877
            while (i < size) {
2878
                newaux = getNthGroupOfThree(all_elem, i);
2879

    
2880
                if (newaux[0].intValue() == aux[0].intValue()) {
2881
                    // aux[2] says how many components
2882
                    for (int j = 0; j < ((NUMBER) aux[2]).intValue(); j++) {
2883
                        aux = appendDatArrays(aux,
2884
                                getNthGroupOfThree(all_elem, j + i));
2885
                    }
2886

    
2887
                    resp.add(aux);
2888
                    i = i + ((NUMBER) aux[2]).intValue();
2889
                    if (i < size) { // in some cases (line collection, 4)
2890
                            aux = getNthGroupOfThree(all_elem, i);
2891
                    } else {
2892
                            add_last_time = false;
2893
                    }
2894
                }
2895
                else {
2896
                    if (((NUMBER) newaux[1]).intValue() == 2003) {
2897
                        aux = appendDatArrays(aux, newaux);
2898
                    } else {
2899
                        resp.add(aux);
2900
                        aux = getNthGroupOfThree(all_elem, i);
2901
                    }
2902
                }
2903

    
2904
                i++;
2905
            }
2906
        }
2907
        catch (SQLException se) {
2908
            logger.error("Unexpected error: " + se.getMessage());
2909
        }
2910

    
2911
        if (add_last_time) {
2912
                resp.add(aux);
2913
        }
2914

    
2915
        return resp.toArray();
2916
    }
2917
    
2918
    
2919
    
2920
    public static Geometry shapeToGeometry(Shape shp) {
2921
        if (shp == null) {
2922
            return null;
2923
        }
2924

    
2925
        int type = FShape.POLYGON;
2926

    
2927
        if ((shp instanceof FPolyline2D) && (!(shp instanceof FPolygon2D))) {
2928
            type = FShape.LINE;
2929
        }
2930

    
2931
        if (shp instanceof FPoint2D) {
2932
            type = FShape.POINT;
2933
        }
2934

    
2935
        if (shp instanceof FMultiPoint2D) {
2936
            type = FShape.MULTIPOINT;
2937
        }
2938

    
2939
        GeneralPathX wagp = new GeneralPathX(shp);
2940
        FShapeGeneralPathX fwagp = new FShapeGeneralPathX(wagp, type);
2941

    
2942
        return FConverter.java2d_to_jts(fwagp);
2943
    }
2944
    
2945
    public static STRUCT rectangleToStruct(Rectangle2D r, boolean hasSrid,
2946
            boolean isView, boolean _isGeogCS, String _oracleSRID, IConnection __conn) {
2947
            Point2D c1 = new Point2D.Double(r.getMinX(), r.getMinY());
2948
            Point2D c2 = new Point2D.Double(r.getMaxX(), r.getMaxY());
2949

    
2950
            if ((_isGeogCS) && (isView)) {
2951
                c1.setLocation(Math.max(c1.getX(), -180), Math.max(c1.getY(), -90));
2952
                c2.setLocation(Math.min(c2.getX(), 180), Math.min(c2.getY(), 90));
2953
            }
2954

    
2955
            STRUCT resp = null;
2956

    
2957
            try {
2958
                // System.out.println("ABIERTA: " + (!conn.isClosed()));
2959
                // resp = structCreator.toSTRUCT(rect_wkt.getBytes(), conn);
2960
                // Object[] old_obj = resp.getAttributes();
2961
                int size = 5;
2962
                Object[] new_obj = new Object[size];
2963

    
2964
                // for (int i=0; i<size; i++) new_obj[i] = old_obj[i];
2965
                new_obj[0] = new NUMBER(2003);
2966

    
2967
                if (hasSrid) {
2968
                    new_obj[1] = new NUMBER(_oracleSRID);
2969
                }
2970
                else {
2971
                    new_obj[1] = null;
2972
                }
2973

    
2974
                new_obj[2] = null;
2975

    
2976
                NUMBER[] elem_info = new NUMBER[3];
2977
                elem_info[0] = new NUMBER(1);
2978
                elem_info[1] = new NUMBER(1003);
2979
                elem_info[2] = new NUMBER(3);
2980
                new_obj[3] = elem_info;
2981

    
2982
                NUMBER[] ords = null;
2983
                ords = new NUMBER[4];
2984
                ords[0] = new NUMBER(c1.getX());
2985
                ords[1] = new NUMBER(c1.getY());
2986
                ords[2] = new NUMBER(c2.getX());
2987
                ords[3] = new NUMBER(c2.getY());
2988
                new_obj[4] = ords;
2989

    
2990
                // StructDescriptor dsc = StructDescriptor.createDescriptor("STRUCT", conn);
2991
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
2992
                                ((ConnectionJDBC)__conn).getConnection());
2993

    
2994
                resp = new STRUCT(dsc,((ConnectionJDBC)__conn).getConnection(), new_obj);
2995
            }
2996
            catch (Exception ex) {
2997
                logger.error("Error while creating rect struct: " +
2998
                    ex.getMessage(), ex);
2999
            }
3000

    
3001
            return resp;
3002
        }
3003
    
3004
    
3005
    public static Rectangle2D doIntersect(Rectangle2D r1, Rectangle2D r2) {
3006
        if (r1.getMaxX() <= r2.getMinX()) {
3007
            return null;
3008
        }
3009

    
3010
        if (r2.getMaxX() <= r1.getMinX()) {
3011
            return null;
3012
        }
3013

    
3014
        if (r1.getMaxY() <= r2.getMinY()) {
3015
            return null;
3016
        }
3017

    
3018
        if (r2.getMaxY() <= r1.getMinY()) {
3019
            return null;
3020
        }
3021

    
3022
        double minx = Math.max(r1.getMinX(), r2.getMinX());
3023
        double miny = Math.max(r1.getMinY(), r2.getMinY());
3024
        double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
3025
        double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
3026

    
3027
        double w = maxx - minx;
3028
        double h = maxy - miny;
3029

    
3030
        return new Rectangle2D.Double(minx, miny, w, h);
3031
    }
3032
    
3033
    
3034
    /**
3035
     * Utility method to find out if a coordinate system is geodetic or not.
3036
     *
3037
     * @param oracleSRID2 the coordinate system's oracle code
3038
     * @param thas whether the table has a coordinate system set.
3039
     * if not, the method returns false.
3040
     * @return whether the coordinate system is geodetic or not.
3041
     */
3042
    public static boolean getIsGCS(String oracleSRID2, boolean thas) {
3043

    
3044
        if (!thas) return false;
3045
        if (oracleSRID2 == null) return false;
3046
        
3047
        int ora_cs = 0;
3048

    
3049
        try {
3050
            ora_cs = Integer.parseInt(oracleSRID2);
3051
        }
3052
        catch (Exception ex) {
3053
            return false;
3054
        }
3055

    
3056
        if (((ora_cs >= 8000) && (ora_cs <= 8999)) || (ora_cs == 524288)) {
3057
            return true;
3058
        } else {
3059
                return false;
3060
        }
3061
    }
3062
    
3063
    
3064
    public static int getShapeTypeOfStruct(STRUCT sample) throws SQLException {
3065

    
3066
        int code = ((NUMBER) sample.getOracleAttributes()[0]).intValue();
3067
        
3068
        int type_part = code % 10;
3069
        int dim_part = code / 1000;
3070

    
3071
        int z_added = 0;
3072
        if (dim_part == 3) {
3073
                z_added = FShape.Z;
3074
        } else {
3075
            if (dim_part == 4) {
3076
                    z_added = FShape.Z | FShape.M;
3077
            }
3078
        }
3079

    
3080
        switch (type_part) {
3081
        case 1:
3082
            return z_added + FShape.POINT;
3083

    
3084
        case 2:
3085
            return z_added + FShape.LINE;
3086

    
3087
        case 3:
3088
            return z_added + FShape.POLYGON;
3089

    
3090
        case 4:
3091
            return z_added + FShape.MULTI;
3092

    
3093
        case 5:
3094
            return z_added + FShape.MULTIPOINT;
3095

    
3096
        case 6:
3097
            return z_added + FShape.LINE;
3098

    
3099
        case 7:
3100
            return z_added + FShape.POLYGON;
3101
        }
3102

    
3103
        logger.error("Unknown geometry type: " + code);
3104

    
3105
        return FShape.NULL;
3106
    }
3107
    
3108
    public static IGeometry NULL_GEOM = new FNullGeometry();
3109
    
3110

    
3111
    
3112
    
3113
    public static int[] updateIndexes(int[] info) {
3114
        int size = info.length / 3;
3115
        int[] resp = new int[3 * size];
3116
        int rest = info[0] - 1;
3117

    
3118
        for (int i = 0; i < size; i++) {
3119
            resp[3 * i] = info[3 * i] - rest;
3120
            resp[(3 * i) + 1] = info[(3 * i) + 1];
3121
            resp[(3 * i) + 2] = info[(3 * i) + 2];
3122
        }
3123

    
3124
        return resp;
3125
    }
3126
    
3127
    
3128

    
3129
    public static int[] appendIntArrays(int[] head, int[] tail) {
3130
        int[] resp = new int[head.length + tail.length];
3131
        int hsize = head.length;
3132

    
3133
        for (int i = 0; i < hsize; i++) {
3134
            resp[i] = head[i];
3135
        }
3136

    
3137
        for (int i = 0; i < tail.length; i++) {
3138
            resp[hsize + i] = tail[i];
3139
        }
3140

    
3141
        return resp;
3142
    }
3143
    
3144
    
3145
    public static Datum[] appendDatArrays(Datum[] head, Datum[] tail) {
3146
        Datum[] resp = new Datum[head.length + tail.length];
3147
        int hsize = head.length;
3148

    
3149
        for (int i = 0; i < hsize; i++) {
3150
            resp[i] = head[i];
3151
        }
3152

    
3153
        for (int i = 0; i < tail.length; i++) {
3154
            resp[hsize + i] = tail[i];
3155
        }
3156

    
3157
        return resp;
3158
    }
3159

    
3160
    public static int[] getNthGroupOfThree(int[] list, int n) {
3161
        int[] resp = new int[3];
3162
        resp[0] = list[3 * n];
3163
        resp[1] = list[(3 * n) + 1];
3164
        resp[2] = list[(3 * n) + 2];
3165

    
3166
        return resp;
3167
    }
3168

    
3169
    public static Datum[] getNthGroupOfThree(Datum[] list, int n) {
3170
        Datum[] resp = new Datum[3];
3171
        resp[0] = list[3 * n];
3172
        resp[1] = list[(3 * n) + 1];
3173
        resp[2] = list[(3 * n) + 2];
3174

    
3175
        return resp;
3176
    }
3177

    
3178
    public static Datum[] getSubSet(Datum[] all, int first_inc, int last_inc) {
3179
        Datum[] resp = new Datum[last_inc - first_inc + 1];
3180

    
3181
        for (int i = first_inc; i <= last_inc; i++) {
3182
            resp[i - first_inc] = all[i];
3183
        }
3184

    
3185
        return resp;
3186
    }
3187
    
3188
    
3189
    public static int maxSizeForFieldType(int _type) {
3190
        switch (_type) {
3191
        case Types.VARCHAR:
3192
            return OracleSpatialDriver.VARCHAR2_STANDARD_SIZE;
3193

    
3194
        case Types.LONGVARCHAR:
3195
            return OracleSpatialDriver.VARCHAR2_LONG_SIZE;
3196
        }
3197

    
3198
        return -1;
3199
    }
3200

    
3201

    
3202

    
3203

    
3204
}