Statistics
| Revision:

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

History | View | Annotate | Download (90.6 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.fmap.dal.store.oracle;
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.Connection;
55
import java.sql.PreparedStatement;
56
import java.sql.ResultSet;
57
import java.sql.SQLException;
58
import java.sql.Types;
59
import java.text.DecimalFormat;
60
import java.text.DecimalFormatSymbols;
61
import java.util.ArrayList;
62
import java.util.HashMap;
63
import java.util.Iterator;
64
import java.util.Random;
65

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

    
72
import org.apache.log4j.Logger;
73
import org.gvsig.fmap.geom.Geometry;
74
import org.gvsig.fmap.geom.GeometryLocator;
75
import org.gvsig.fmap.geom.GeometryManager;
76
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2D;
77
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2DZ;
78
import org.gvsig.fmap.geom.exception.CreateGeometryException;
79
import org.gvsig.fmap.geom.primitive.GeneralPathX;
80
import org.gvsig.fmap.geom.primitive.Surface;
81
import org.gvsig.fmap.geom.primitive.impl.Point2DZ;
82
import org.gvsig.oracle.utils.LineString3D;
83

    
84

    
85
import com.vividsolutions.jts.algorithm.CGAlgorithms;
86
import com.vividsolutions.jts.geom.Coordinate;
87
import com.vividsolutions.jts.geom.CoordinateArrays;
88
import com.vividsolutions.jts.geom.Envelope;
89
import com.vividsolutions.jts.geom.GeometryFactory;
90
import com.vividsolutions.jts.geom.LineString;
91
import com.vividsolutions.jts.geom.LinearRing;
92
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
93

    
94

    
95
/**
96
 * Utility class with static methods.
97
 *
98
 * @author jldominguez
99
 *
100
 */
101
public class OracleUtils {
102
    private static Logger logger = Logger.getLogger(OracleSpatialUtils.class.getName());
103
    private static double FLATNESS = 0.8;
104
    private static GeometryFactory geomFactory = new GeometryFactory();
105
    private static final double IRRELEVANT_DISTANCE = 0.00000001;
106
    private static Random rnd = new Random();
107
    private static DecimalFormat df = new DecimalFormat();
108
    private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
109
   
110

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

    
130
        try {
131
            FileReader fr = new FileReader(file);
132
            BufferedReader br = new BufferedReader(fr);
133
            double[] coords = new double[3];
134

    
135
            boolean move = true;
136

    
137
            String line = br.readLine();
138

    
139
            while (line != null) {
140
                coords = parseLine(line);
141

    
142
                if (line.length() == 0) {
143
                    move = true;
144
                }
145
                else {
146
                    if (move) {
147
                        resp.moveTo(coords[0], coords[1]);
148
                        z.add(new Double(coords[2]));
149
                    }
150
                    else {
151
                        resp.lineTo(coords[0], coords[1]);
152
                        z.add(new Double(coords[2]));
153
                    }
154

    
155
                    move = false;
156
                }
157

    
158
                line = br.readLine();
159
            }
160
        }
161
        catch (Exception ex) {
162
                logger.error("While creating GeneralPathX: " +
163
                ex.getMessage());
164

    
165
            return null;
166
        }
167

    
168
        double[] zz = new double[z.size()];
169

    
170
        for (int i = 0; i < z.size(); i++) {
171
            zz[i] = ((Double) z.get(i)).doubleValue();
172
        }
173

    
174
        if (polygon) {
175
                Surface surface = (Surface) geomManager.create(Geometry.TYPES.SURFACE, Geometry.SUBTYPES.GEOM2DZ);
176
                surface.
177
            return .createSurface(resp, org.gvsig.fmap.geom.Geometry.SUBTYPES.GEOM2DZ).createPolygon3D(resp, zz);
178
        }
179
        else {
180
            return ShapeFactory.createPolyline3D(resp, zz);
181
        }
182
    }
183

    
184
    private static double[] parseLine(String line) {
185
        String[] sep = line.split(" ");
186
        double[] resp = new double[3];
187

    
188
        for (int i = 0; i < 3; i++)
189
            resp[i] = 0.0;
190

    
191
        try {
192
            resp[0] = Double.parseDouble(sep[0]);
193
        }
194
        catch (Exception ex) {
195
        }
196

    
197
        if (sep.length > 1) {
198
            try {
199
                resp[1] = Double.parseDouble(sep[1]);
200
            }
201
            catch (Exception ex) {
202
            }
203

    
204
            if (sep.length > 2) {
205
                try {
206
                    resp[2] = Double.parseDouble(sep[2]);
207
                }
208
                catch (Exception ex) {
209
                }
210
            }
211
        }
212

    
213
        return resp;
214
    }
215

    
216
   
217

    
218
    private static STRUCT multiPoint2DToStruct(MultiPoint2D mp2d,
219
        Connection c, int srid, boolean hasSrid) throws SQLException {
220
        int np = mp2d.getNumPoints();
221
        boolean threed = (mp2d instanceof MultiPoint2DZ);
222
        int gtype = 2005;
223
        int dim = 2;
224
        MultiPoint2DZ mp3d = null;
225

    
226
        if (threed) {
227
            gtype = 3005;
228
            dim = 3;
229
            mp3d = (MultiPoint2DZ) mp2d;
230
        }
231

    
232
        NUMBER[] indices = new NUMBER[3];
233
        indices[0] = new NUMBER(1);
234
        indices[1] = new NUMBER(1);
235
        indices[2] = new NUMBER(np);
236

    
237
        NUMBER[] ords = new NUMBER[dim * np];
238

    
239
        for (int i = 0; i < np; i++) {
240
            ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
241
            ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY());
242

    
243
            if (threed) {
244
                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
245
            }
246
        }
247

    
248
        STRUCT resp;
249
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
250
                        ((ConnectionJDBC)c).getConnection());
251
        Object[] obj = new Object[5];
252
        obj[0] = new NUMBER(gtype);
253

    
254
        if (hasSrid) {
255
            obj[1] = new NUMBER(srid);
256
        }
257
        else { // , boolean hasSrid
258
            obj[1] = null;
259
        }
260

    
261
        obj[2] = null;
262
        obj[3] = indices;
263
        obj[4] = ords;
264
        resp = new STRUCT(dsc, ((ConnectionJDBC)c).getConnection(), obj);
265

    
266
        return resp;
267
    }
268

    
269
    private static STRUCT getCircleAsStruct(FCircle2D fcirc, int srid,
270
        Connection _conn, boolean hasSrid) throws SQLException {
271
        int geotype = 2003;
272
        NUMBER[] indices = new NUMBER[3];
273
        indices[0] = new NUMBER(1);
274
        indices[1] = new NUMBER(1003);
275
        indices[2] = new NUMBER(4);
276

    
277
        NUMBER[] ords = new NUMBER[6];
278
        Coordinate[] three_points = getThreePointsOfCircumference(fcirc.getCenter(),
279
                fcirc.getRadio());
280

    
281
        for (int i = 0; i < three_points.length; i++) {
282
            ords[i * 2] = new NUMBER(three_points[i].x);
283
            ords[(i * 2) + 1] = new NUMBER(three_points[i].y);
284
        }
285

    
286
        STRUCT resp;
287
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
288
                        ((ConnectionJDBC)_conn).getConnection());
289
        Object[] obj = new Object[5];
290
        obj[0] = new NUMBER(geotype);
291

    
292
        if (hasSrid) {
293
            obj[1] = new NUMBER(srid);
294
        }
295
        else {
296
            obj[1] = null;
297
        }
298

    
299
        obj[2] = null;
300
        obj[3] = indices;
301
        obj[4] = ords;
302
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
303

    
304
        return resp;
305
    }
306

    
307
    private static Coordinate[] getThreePointsOfCircumference(Point2D cntr,
308
        double radius) {
309
        Coordinate[] resp = new Coordinate[3];
310
        double x;
311
        double y;
312
        double alpha = 0;
313

    
314
        for (int i = 0; i < 3; i++) {
315
            alpha = (i * 120.0 * Math.PI) / 180.0;
316
            x = cntr.getX() + (radius * Math.cos(alpha));
317
            y = cntr.getY() + (radius * Math.sin(alpha));
318
            resp[i] = new Coordinate(x, y);
319
        }
320

    
321
        return resp;
322
    }
323

    
324
    private static Coordinate getSingleCoordinate(Point2D p2d) {
325
        // TODO Auto-generated method stub
326
        Coordinate resp = new Coordinate();
327
        resp.x = p2d.getX();
328
        resp.y = p2d.getY();
329

    
330
        if (p2d instanceof Point2DZ) {
331
            resp.z = ((Point2DZ) p2d).getZs()[0];
332
        }
333

    
334
        return resp;
335
    }
336

    
337
    private static ArrayList ensureSensibleLineString(ArrayList cc) {
338
        if (cc.size() == 2) {
339
            if (sameCoordinate((Coordinate) cc.get(0),
340
                        (Coordinate) cc.get(cc.size() - 1))) {
341
                ArrayList resp = new ArrayList();
342
                resp.add(cc.get(0));
343

    
344
                Coordinate newc = new Coordinate((Coordinate) cc.get(0));
345
                newc.x = newc.x + IRRELEVANT_DISTANCE;
346
                resp.add(newc);
347

    
348
                return resp;
349
            }
350
        }
351

    
352
        return cc;
353
    }
354

    
355
    private static boolean sameCoordinate(Coordinate c1, Coordinate c2) {
356
        if (c1.x != c2.x) {
357
            return false;
358
        }
359

    
360
        if (c1.y != c2.y) {
361
            return false;
362
        }
363

    
364
        return true;
365
    }
366

    
367
    private static ArrayList getClosedRelevantPolygon(ArrayList cc) {
368
        if (cc.size() == 2) {
369
            return getMinClosedCoords((Coordinate) cc.get(0));
370
        }
371

    
372
        if (cc.size() == 3) {
373
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1))) {
374
                return getMinClosedCoords((Coordinate) cc.get(0));
375
            }
376

    
377
            if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2))) {
378
                return getMinClosedCoords((Coordinate) cc.get(0));
379
            }
380

    
381
            if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2))) {
382
                return getMinClosedCoords((Coordinate) cc.get(1));
383
            }
384

    
385
            cc.add(cc.get(0));
386

    
387
            return cc;
388
        }
389

    
390
        if (!sameCoordinate((Coordinate) cc.get(0),
391
                    (Coordinate) cc.get(cc.size() - 1))) {
392
            cc.add(cc.get(0));
393
        }
394

    
395
        return cc;
396
    }
397

    
398
    private static ArrayList getMinClosedCoords(Coordinate c) {
399
        ArrayList resp = new ArrayList();
400
        resp.add(c);
401

    
402
        Coordinate nc = new Coordinate(c);
403
        nc.x = nc.x + IRRELEVANT_DISTANCE;
404
        resp.add(nc);
405

    
406
        Coordinate nc2 = new Coordinate(nc);
407
        nc2.y = nc2.y + IRRELEVANT_DISTANCE;
408
        resp.add(nc2);
409

    
410
        resp.add(new Coordinate(c));
411

    
412
        return resp;
413
    }
414

    
415
    private static LinearRing getMinLinearRing(Coordinate c) {
416
        Coordinate[] p = new Coordinate[4];
417
        p[0] = c;
418

    
419
        Coordinate nc = new Coordinate(c);
420
        nc.x = nc.x + IRRELEVANT_DISTANCE;
421

    
422
        Coordinate nc2 = new Coordinate(nc);
423
        nc2.y = nc2.y - IRRELEVANT_DISTANCE;
424
        p[1] = nc;
425
        p[2] = nc2;
426
        p[3] = new Coordinate(c);
427

    
428
        CoordinateArraySequence cs = new CoordinateArraySequence(p);
429
        LinearRing ls = new LinearRing(cs, geomFactory);
430

    
431
        return ls;
432
    }
433

    
434
    private static double[] getMinLinearRingZ() {
435
        double[] resp = new double[4];
436

    
437
        for (int i = 0; i < 4; i++)
438
            resp[i] = 0.0;
439

    
440
        return resp;
441
    }
442

    
443
    private static boolean pointInList(Coordinate testPoint,
444
        Coordinate[] pointList) {
445
        int t;
446
        int numpoints;
447
        Coordinate p;
448

    
449
        numpoints = Array.getLength(pointList);
450

    
451
        for (t = 0; t < numpoints; t++) {
452
            p = pointList[t];
453

    
454
            if ((testPoint.x == p.x) && (testPoint.y == p.y) &&
455
                    ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z))) //nan test; x!=x iff x is nan
456
            ) {
457
                return true;
458
            }
459
        }
460

    
461
        return false;
462
    }
463

    
464
    private static ArrayList getPolygonsEasily(FShape mpolygon) {
465
        boolean threed = false;
466

    
467
        if (mpolygon instanceof FPolygon3D) {
468
            threed = true;
469
        }
470

    
471
        int start_ind = 0;
472
        int end_ind = 0;
473
        int ind = 0;
474
        int new_size;
475
        ArrayList arrayCoords = null;
476
        ArrayList resp = new ArrayList();
477
        Coordinate[] points = null;
478
        int theType = -99;
479
        double[] theData = new double[6];
480
        Coordinate onlyCoord = null;
481
        int numParts = 0;
482

    
483
        PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
484

    
485
        while (!theIterator.isDone()) {
486
            //while not done
487
            theType = theIterator.currentSegment(theData);
488

    
489
            if (onlyCoord == null) {
490
                onlyCoord = new Coordinate();
491
                onlyCoord.x = theData[0];
492
                onlyCoord.y = theData[1];
493
            }
494

    
495
            switch (theType) {
496
            case PathIterator.SEG_MOVETO:
497

    
498
                if (arrayCoords == null) {
499
                    arrayCoords = new ArrayList();
500
                }
501
                else {
502
                    end_ind = ind - 1;
503

    
504
                    arrayCoords = getClosedRelevantPolygon(arrayCoords);
505
                    new_size = arrayCoords.size();
506

    
507
                    if (arrayCoords != null) {
508
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
509

    
510
                        try {
511
                            LinearRing aux = geomFactory.createLinearRing(points);
512
                            double[] z = null;
513

    
514
                            if (threed) {
515
                                z = getZ((FPolygon3D) mpolygon, start_ind,
516
                                        end_ind, new_size);
517
                            }
518

    
519
                            LineString3D ring = new LineString3D(aux, z);
520

    
521
                            if (CGAlgorithms.isCCW(points)) {
522
                                resp.add(ring);
523
                            }
524
                            else {
525
                                resp.add(ring.createReverse());
526
                            }
527
                        }
528
                        catch (Exception e) {
529
                                logger.error("Topology exception: " +
530
                                e.getMessage());
531

    
532
                            return null;
533
                        }
534
                    }
535

    
536
                    arrayCoords = new ArrayList();
537

    
538
                    start_ind = ind;
539
                }
540

    
541
                numParts++;
542

    
543
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
544
                ind++;
545

    
546
                break;
547

    
548
            case PathIterator.SEG_LINETO:
549
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
550
                ind++;
551

    
552
                break;
553

    
554
            case PathIterator.SEG_QUADTO:
555
                    logger.info("SEG_QUADTO Not supported here");
556
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
557
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
558
                ind++;
559
                ind++;
560

    
561
                break;
562

    
563
            case PathIterator.SEG_CUBICTO:
564
                    logger.info("SEG_CUBICTO Not supported here");
565
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
566
                arrayCoords.add(new Coordinate(theData[2], theData[3]));
567
                arrayCoords.add(new Coordinate(theData[4], theData[5]));
568
                ind++;
569
                ind++;
570
                ind++;
571

    
572
                break;
573

    
574
            case PathIterator.SEG_CLOSE:
575

    
576
                // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
577
                // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
578
                break;
579
            } //end switch
580

    
581
            theIterator.next();
582
        } //end while loop
583

    
584
        end_ind = ind - 1;
585

    
586
        // null shape:
587
        if (arrayCoords == null) {
588
            arrayCoords = new ArrayList();
589

    
590
            Coordinate _c = new Coordinate(0, 0, 0);
591
            arrayCoords.add(new Coordinate(_c));
592
            arrayCoords.add(new Coordinate(_c));
593
        }
594

    
595
        // --------------------------------------------
596
        arrayCoords = getClosedRelevantPolygon(arrayCoords);
597
        new_size = arrayCoords.size();
598

    
599
        if (arrayCoords != null) {
600
            points = CoordinateArrays.toCoordinateArray(arrayCoords);
601

    
602
            try {
603
                LinearRing aux = geomFactory.createLinearRing(points);
604
                double[] z = null;
605

    
606
                if (threed) {
607
                    z = getZ((FPolygon3D) mpolygon, start_ind, end_ind, new_size);
608
                }
609

    
610
                LineString3D ring = new LineString3D(aux, z);
611

    
612
                if (CGAlgorithms.isCCW(points)) {
613
                    resp.add(ring);
614
                }
615
                else {
616
                    resp.add(ring.createReverse());
617
                }
618
            }
619
            catch (Exception e) {
620
                    logger.error("Topology exception: " + e.getMessage());
621

    
622
                return null;
623
            }
624
        }
625

    
626
        if (resp.size() == 0) {
627
            resp.add(new LineString3D(getMinLinearRing(onlyCoord),
628
                    getMinLinearRingZ()));
629
        }
630

    
631
        return resp;
632
    }
633

    
634
    /**
635
     * Utility method to reverse an array of doubles.
636
     *
637
     * @param _z an array of doubles to be reversed.
638
     *
639
     * @return the reversed array of doubles
640
     */
641
    public static double[] reverseArray(double[] _z) {
642
        int size = _z.length;
643
        double[] resp = new double[size];
644

    
645
        for (int i = 0; i < size; i++) {
646
            resp[i] = _z[size - 1 - i];
647
        }
648

    
649
        return resp;
650
    }
651

    
652
    /**
653
     * Utility method to reverse an array of coordinates
654
     *
655
     * @param _z an array of coordinaes to be reversed.
656
     *
657
     * @return the reversed array of coordinates
658
     */
659
    public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) {
660
        int size = _z.length;
661
        Coordinate[] resp = new Coordinate[size];
662

    
663
        for (int i = 0; i < size; i++) {
664
            resp[i] = _z[size - 1 - i];
665
        }
666

    
667
        return resp;
668
    }
669

    
670
    private static double[] getZ(FShape3D p3d, int _str, int _end, int size) {
671
        double[] resp = new double[size];
672
        double[] allz = p3d.getZs();
673

    
674
        for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) {
675
            resp[i - _str] = allz[i];
676
        }
677

    
678
        if ((_end - _str + 1) < size) {
679
            double repe = allz[_end];
680

    
681
            for (int i = (_end - _str + 1); i < size; i++) {
682
                resp[i] = repe;
683
            }
684
        }
685

    
686
        return resp;
687
    }
688

    
689
    private static ArrayList getLineStrings(FShape mlines) {
690
        boolean threed = false;
691

    
692
        if (mlines instanceof FPolyline3D) {
693
            threed = true;
694
        }
695

    
696
        int start_ind = 0;
697
        int end_ind = 0;
698
        int ind = 0;
699
        int new_size = 0;
700

    
701
        LineString3D lin;
702

    
703
        ArrayList arrayLines = new ArrayList();
704
        PathIterator theIterator = mlines.getPathIterator(null, FLATNESS);
705
        int theType = -99;
706
        double[] theData = new double[6];
707
        ArrayList arrayCoords = null;
708
        int numParts = 0;
709

    
710
        while (!theIterator.isDone()) {
711
            //while not done
712
            theType = theIterator.currentSegment(theData);
713

    
714
            switch (theType) {
715
            case PathIterator.SEG_MOVETO:
716

    
717
                if (arrayCoords == null) {
718
                    arrayCoords = new ArrayList();
719
                }
720
                else {
721
                    end_ind = ind - 1;
722
                    arrayCoords = ensureSensibleLineString(arrayCoords);
723
                    new_size = arrayCoords.size();
724

    
725
                    LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
726
                                arrayCoords));
727
                    double[] z = null;
728

    
729
                    if (threed) {
730
                        z = getZ((FPolyline3D) mlines, start_ind, end_ind,
731
                                new_size);
732
                    }
733

    
734
                    lin = new LineString3D(aux, z);
735
                    arrayLines.add(lin);
736
                    arrayCoords = new ArrayList();
737

    
738
                    start_ind = ind;
739
                }
740

    
741
                numParts++;
742
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
743

    
744
                break;
745

    
746
            case PathIterator.SEG_LINETO:
747
                arrayCoords.add(new Coordinate(theData[0], theData[1]));
748

    
749
                break;
750

    
751
            case PathIterator.SEG_QUADTO:
752
                    logger.info("Not supported here: SEG_QUADTO");
753

    
754
                break;
755

    
756
            case PathIterator.SEG_CUBICTO:
757
                    logger.info("Not supported here: SEG_CUBICTO");
758

    
759
                break;
760

    
761
            case PathIterator.SEG_CLOSE:
762

    
763
                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
764
                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
765

    
766
                break;
767
            } //end switch
768

    
769
            theIterator.next();
770
            ind++;
771
        } //end while loop
772

    
773
        arrayCoords = ensureSensibleLineString(arrayCoords);
774
        new_size = arrayCoords.size();
775

    
776
        LineString aux = geomFactory.createLineString(CoordinateArrays.toCoordinateArray(
777
                    arrayCoords));
778
        double[] z = null;
779

    
780
        if (threed) {
781
            z = getZ((FPolyline3D) mlines, start_ind, end_ind, new_size);
782
        }
783

    
784
        lin = new LineString3D(aux, z);
785
        arrayLines.add(lin);
786

    
787
        return arrayLines;
788
    }
789

    
790
    private static String lineStringToWKT(LineString3D ls, boolean threed) {
791
        String resp = "(";
792
        Coordinate[] cc = ls.getLs().getCoordinates();
793
        double[] z = ls.getZc();
794
        int size = cc.length;
795

    
796
        if (threed) {
797
            for (int i = 0; i < size; i++) {
798
                resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", ";
799
            }
800

    
801
            resp = resp.substring(0, resp.length() - 2);
802
            resp = resp + ")";
803
        }
804
        else {
805
            for (int i = 0; i < size; i++) {
806
                resp = resp + cc[i].x + " " + cc[i].y + ", ";
807
            }
808

    
809
            resp = resp.substring(0, resp.length() - 2);
810
            resp = resp + ")";
811
        }
812

    
813
        return resp;
814
    }
815

    
816
    private static String multiLineStringToWKT(ArrayList ml, boolean threed) {
817
        String resp = "MULTILINESTRING(";
818

    
819
        for (int i = 0; i < ml.size(); i++) {
820
            LineString3D ls = (LineString3D) ml.get(i);
821
            resp = resp + lineStringToWKT(ls, threed) + ", ";
822
        }
823

    
824
        resp = resp.substring(0, resp.length() - 2) + ")";
825

    
826
        return resp;
827
    }
828

    
829
    private static String polygonsToWKT(ArrayList pols, boolean threed) {
830
        String resp = "MULTIPOLYGON(";
831
        LineString3D ls = null;
832

    
833
        for (int i = 0; i < pols.size(); i++) {
834
            ls = (LineString3D) pols.get(i);
835
            resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
836
        }
837

    
838
        resp = resp.substring(0, resp.length() - 2) + ")";
839

    
840
        return resp;
841
    }
842

    
843
    private static String shellAndHolesToWKT(LineString3D shell,
844
        ArrayList holes, boolean threed) {
845
        String resp = "(";
846
        resp = resp + lineStringToWKT(shell, threed);
847

    
848
        if (holes.size() > 0) {
849
            for (int i = 0; i < holes.size(); i++) {
850
                LineString3D ls = (LineString3D) holes.get(i);
851
                resp = resp + ", " + lineStringToWKT(ls, threed);
852
            }
853
        }
854

    
855
        resp = resp + ")";
856

    
857
        return resp;
858
    }
859

    
860
    private static String multiPolygonToWKT(ArrayList shells, ArrayList hFs,
861
        boolean threed) {
862
        String resp = "MULTIPOLYGON(";
863
        LineString3D ls = null;
864
        ArrayList holes;
865

    
866
        for (int i = 0; i < shells.size(); i++) {
867
            ls = (LineString3D) shells.get(i);
868
            holes = (ArrayList) hFs.get(i);
869
            resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
870
        }
871

    
872
        resp = resp.substring(0, resp.length() - 2) + ")";
873

    
874
        return resp;
875
    }
876

    
877
    private static String pointToWKT(FPoint2D point, boolean threed) {
878
        String resp = "POINT(" + point.getX() + " " + point.getY();
879

    
880
        if ((threed) && (point instanceof FPoint3D)) {
881
            resp = resp + " " + ((FPoint3D) point).getZs()[0];
882
        }
883

    
884
        resp = resp + ")";
885

    
886
        return resp;
887
    }
888

    
889
    private static int twoDIndexToDimsIndex(int n, int d) {
890
        return ((d * (n - 1)) / 2) + 1;
891
    }
892

    
893
    private static ARRAY setSubelementsToDim(ARRAY old, int d)
894
        throws SQLException {
895
        Datum[] infos = (Datum[]) old.getOracleArray();
896

    
897
        for (int i = 3; i < infos.length; i = i + 3) {
898
            int oldind = infos[i].intValue();
899
            oldind = twoDIndexToDimsIndex(oldind, d);
900
            infos[i] = new NUMBER(oldind);
901

    
902
            //
903
            oldind = infos[i + 1].intValue();
904
            infos[i + 1] = new NUMBER(infos[1].intValue());
905
        }
906

    
907
        ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
908
                infos);
909

    
910
        return resp;
911
    }
912

    
913
    private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
914
        Envelope env = ls.getEnvelopeInternal();
915

    
916
        if (!env.contains(p)) {
917
            return false;
918
        }
919

    
920
        return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
921
    }
922

    
923
    private static boolean lineString3DIsContainedBy(LineString3D contained,
924
        LineString3D container) {
925
        int samples = 10;
926
        LineString _in = contained.getLs();
927
        LineString _out = container.getLs();
928
        Coordinate[] inc = _in.getCoordinates();
929
        Coordinate aux;
930
        int size = inc.length;
931

    
932
        if (size <= 10) {
933
            for (int i = 0; i < size; i++) {
934
                aux = inc[i];
935

    
936
                if (!isPointInsideLineString(aux, _out)) {
937
                    return false;
938
                }
939
            }
940

    
941
            return true;
942
        }
943
        else {
944
            for (int i = 0; i < samples; i++) {
945
                aux = inc[rnd.nextInt(size)];
946

    
947
                if (!isPointInsideLineString(aux, _out)) {
948
                    return false;
949
                }
950
            }
951

    
952
            return true;
953
        }
954
    }
955

    
956
    private static STRUCT getMultiPolygonAsStruct(ArrayList pols, int srid,
957
        boolean threed, IConnection _conn, boolean agu_bien, boolean hasSrid)
958
        throws SQLException {
959
        int size = pols.size();
960
        int geotype = 2007;
961
        int dim = 2;
962
        int acum = 0;
963

    
964
        if (threed) {
965
            geotype = 3007;
966
            dim = 3;
967
        }
968

    
969
        NUMBER[] indices = new NUMBER[3 * size];
970

    
971
        for (int i = 0; i < size; i++) {
972
            indices[3 * i] = new NUMBER(acum + 1);
973
            indices[(3 * i) + 1] = new NUMBER(1003);
974
            indices[(3 * i) + 2] = new NUMBER(1);
975
            acum = acum +
976
                (dim * ((LineString3D) pols.get(i)).getLs().getNumPoints());
977
        }
978

    
979
        int _ind = 0;
980
        NUMBER[] ords = new NUMBER[acum];
981

    
982
        for (int i = 0; i < size; i++) {
983
            LineString3D ls = (LineString3D) pols.get(i);
984
            int num_p = ls.getLs().getNumPoints();
985

    
986
            for (int j = 0; j < num_p; j++) {
987
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
988
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
989

    
990
                if (threed) {
991
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
992
                }
993

    
994
                _ind = _ind + dim;
995
            }
996
        }
997

    
998
        STRUCT resp;
999
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1000
                        ((ConnectionJDBC)_conn).getConnection());
1001
        Object[] obj = new Object[5];
1002
        obj[0] = new NUMBER(geotype);
1003

    
1004
        if (hasSrid) {
1005
            obj[1] = new NUMBER(srid);
1006
        }
1007
        else {
1008
            obj[1] = null;
1009
        }
1010

    
1011
        obj[2] = null;
1012
        obj[3] = indices;
1013
        obj[4] = ords;
1014
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1015

    
1016
        return resp;
1017
    }
1018

    
1019
    private static STRUCT getMultiLineAsStruct(ArrayList lines, int srid,
1020
        boolean threed, IConnection _conn, boolean hasSrid)
1021
        throws SQLException {
1022
        /*
1023
        if (lines.size() == 1) {
1024
                return getOneLineStringAsStruct((LineString3D) lines.get(0), srid, threed, _conn);
1025
        }
1026
        */
1027
        int size = lines.size();
1028
        int geotype = 2006;
1029
        int dim = 2;
1030
        int acum = 0;
1031

    
1032
        if (threed) {
1033
            geotype = 3006;
1034
            dim = 3;
1035
        }
1036

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

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

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

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

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

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

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

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

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

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

    
1084
        return resp;
1085
    }
1086

    
1087
    private static STRUCT getMultiPointAsStruct(Coordinate pnt, int srid,
1088
        boolean threed, IConnection _conn, boolean hasSrid)
1089
        throws SQLException {
1090
        int geotype = 2001;
1091
        int dim = 2;
1092

    
1093
        if (threed) {
1094
            geotype = 3001;
1095
            dim = 3;
1096
        }
1097

    
1098
        Object[] ords = new Object[3];
1099
        ords[0] = new NUMBER(pnt.x);
1100
        ords[1] = new NUMBER(pnt.y);
1101
        ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null; // ole ole y ole
1102

    
1103
        StructDescriptor ord_dsc = StructDescriptor.createDescriptor("MDSYS.SDO_POINT_TYPE",
1104
                        ((ConnectionJDBC)_conn).getConnection());
1105
        STRUCT ords_st = new STRUCT(ord_dsc, ((ConnectionJDBC)_conn).getConnection(), ords);
1106

    
1107
        STRUCT resp;
1108

    
1109
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1110
                        ((ConnectionJDBC)_conn).getConnection());
1111
        Object[] obj = new Object[5];
1112

    
1113
        obj[0] = new NUMBER(geotype);
1114

    
1115
        if (hasSrid) {
1116
            obj[1] = new NUMBER(srid);
1117
        }
1118
        else {
1119
            obj[1] = null;
1120
        }
1121

    
1122
        obj[2] = ords_st;
1123
        obj[3] = null;
1124
        obj[4] = null;
1125
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1126

    
1127
        return resp;
1128
    }
1129

    
1130
    /**
1131
     * Utility method to compute a circle's center and radius from three given points.
1132
     *
1133
     * @param points three points of a circumference
1134
     * @return a 2-item array with the circumference's center (Point2D) and radius (Double)
1135
     */
1136
    public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1137
        Object[] resp = new Object[2];
1138
        resp[0] = new Point2D.Double(0, 0);
1139
        resp[1] = new Double(0);
1140

    
1141
        double m11;
1142
        double m12;
1143
        double m13;
1144
        double m14;
1145

    
1146
        if (points.length != 3) {
1147
            logger.error("Needs 3 points (found " + points.length +
1148
                ") - circle cannot be computed.");
1149

    
1150
            // not a circle
1151
            return resp;
1152
        }
1153

    
1154
        double[][] a = new double[3][3];
1155

    
1156
        for (int i = 0; i < 3; i++) { // find minor 11
1157
            a[i][0] = points[i].getX();
1158
            a[i][1] = points[i].getY();
1159
            a[i][2] = 1;
1160
        }
1161

    
1162
        m11 = determinant(a, 3);
1163

    
1164
        for (int i = 0; i < 3; i++) { // find minor 12
1165
            a[i][0] = (points[i].getX() * points[i].getX()) +
1166
                (points[i].getY() * points[i].getY());
1167
            a[i][1] = points[i].getY();
1168
            a[i][2] = 1;
1169
        }
1170

    
1171
        m12 = determinant(a, 3);
1172

    
1173
        for (int i = 0; i < 3; i++) // find minor 13
1174
         {
1175
            a[i][0] = (points[i].getX() * points[i].getX()) +
1176
                (points[i].getY() * points[i].getY());
1177
            a[i][1] = points[i].getX();
1178
            a[i][2] = 1;
1179
        }
1180

    
1181
        m13 = determinant(a, 3);
1182

    
1183
        for (int i = 0; i < 3; i++) { // find minor 14
1184
            a[i][0] = (points[i].getX() * points[i].getX()) +
1185
                (points[i].getY() * points[i].getY());
1186
            a[i][1] = points[i].getX();
1187
            a[i][2] = points[i].getY();
1188
        }
1189

    
1190
        m14 = determinant(a, 3);
1191

    
1192
        Double resp_radius = new Double(0);
1193
        Point2D resp_center = new Point2D.Double(0, 0);
1194

    
1195
        if (m11 == 0) {
1196
            logger.error("Three points aligned - circle cannot be computed."); // not a circle
1197
        }
1198
        else {
1199
            double x = (0.5 * m12) / m11;
1200
            double y = (-0.5 * m13) / m11;
1201
            resp_center.setLocation(x, y);
1202
            resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11)));
1203
            resp[0] = resp_center;
1204
            resp[1] = resp_radius;
1205
        }
1206

    
1207
        return resp;
1208
    }
1209

    
1210
    /**
1211
     * Utility method to compute a matrix determinant
1212
     * @param a the matrix
1213
     * @param n matrix size
1214
     * @return the matrix's determinant
1215
     */
1216
    public static double determinant(double[][] a, int n) {
1217
        double resp = 0;
1218
        double[][] m = new double[3][3];
1219

    
1220
        if (n == 2) { // terminate recursion
1221
            resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1222
        }
1223
        else {
1224
            resp = 0;
1225

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

    
1228
                for (int i = 1; i < n; i++) { // create minor
1229

    
1230
                    int j2 = 0;
1231

    
1232
                    for (int j = 0; j < n; j++) {
1233
                        if (j == j1) {
1234
                            continue;
1235
                        }
1236

    
1237
                        m[i - 1][j2] = a[i][j];
1238
                        j2++;
1239
                    }
1240
                }
1241

    
1242
                // sum (+/-)cofactor * minor
1243
                resp = resp +
1244
                    (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1245
            }
1246
        }
1247

    
1248
        return resp;
1249
    }
1250

    
1251
    private static int getSmallestContainerExcept(LineString3D ls,
1252
        ArrayList list, int self) {
1253
        int resp = -1;
1254
        ArrayList provList = new ArrayList();
1255

    
1256
        int size = list.size();
1257

    
1258
        for (int i = 0; i < self; i++) {
1259
            if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1260
                provList.add(new Integer(i));
1261
            }
1262
        }
1263

    
1264
        for (int i = (self + 1); i < size; i++) {
1265
            if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1266
                provList.add(new Integer(i));
1267
            }
1268
        }
1269

    
1270
        if (provList.size() == 0) {
1271
            // logger.debug("LineString is not contained by any other ls.");
1272
        }
1273
        else {
1274
            if (provList.size() == 1) {
1275
                resp = ((Integer) provList.get(0)).intValue();
1276
            }
1277
            else {
1278
                if (provList.size() == 2) {
1279
                    int ind_1 = ((Integer) provList.get(0)).intValue();
1280
                    int ind_2 = ((Integer) provList.get(1)).intValue();
1281
                    LineString3D ls1 = (LineString3D) list.get(ind_1);
1282
                    LineString3D ls2 = (LineString3D) list.get(ind_2);
1283

    
1284
                    if (lineString3DIsContainedBy(ls1, ls2)) {
1285
                        resp = ind_1;
1286
                    }
1287
                    else {
1288
                        resp = ind_2;
1289
                    }
1290
                }
1291
                else {
1292
                    // not so deep, sorry!
1293
                    // it's going to be a shell: resp = -1;
1294
                }
1295
            }
1296
        }
1297

    
1298
        return resp;
1299
    }
1300

    
1301
    private static int[] getIndicesOfShells(int[] containings) {
1302
        ArrayList resp = new ArrayList();
1303

    
1304
        for (int i = 0; i < containings.length; i++) {
1305
            if (containings[i] == -1) {
1306
                resp.add(new Integer(i));
1307
            }
1308
        }
1309

    
1310
        int size = resp.size();
1311
        int[] _resp = new int[size];
1312

    
1313
        for (int i = 0; i < size; i++) {
1314
            _resp[i] = ((Integer) resp.get(i)).intValue();
1315
        }
1316

    
1317
        return _resp;
1318
    }
1319

    
1320
    private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1321
        ArrayList resp = new ArrayList();
1322

    
1323
        for (int i = 0; i < containings.length; i++) {
1324
            int cont_by = containings[i];
1325

    
1326
            if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1327
                resp.add(new Integer(i));
1328
            }
1329
        }
1330

    
1331
        int size = resp.size();
1332
        int[] _resp = new int[size];
1333

    
1334
        for (int i = 0; i < size; i++) {
1335
            _resp[i] = ((Integer) resp.get(i)).intValue();
1336
        }
1337

    
1338
        return _resp;
1339
    }
1340

    
1341
    private static int[] getFinalContainings(int[] containings, int[] holes) {
1342
        ArrayList resp = new ArrayList();
1343

    
1344
        for (int i = 0; i < containings.length; i++) {
1345
            int cont_by = containings[i];
1346

    
1347
            if (isOneOf(cont_by, holes)) {
1348
                resp.add(new Integer(-1));
1349
            }
1350
            else {
1351
                resp.add(new Integer(cont_by));
1352
            }
1353
        }
1354

    
1355
        int size = resp.size();
1356
        int[] _resp = new int[size];
1357

    
1358
        for (int i = 0; i < size; i++) {
1359
            _resp[i] = ((Integer) resp.get(i)).intValue();
1360
        }
1361

    
1362
        return _resp;
1363
    }
1364

    
1365
    private static ArrayList getHolesOf(int ind, int[] final_contn,
1366
        ArrayList all) {
1367
        ArrayList resp_ind = new ArrayList();
1368

    
1369
        for (int i = 0; i < final_contn.length; i++) {
1370
            if (final_contn[i] == ind) {
1371
                resp_ind.add(new Integer(i));
1372
            }
1373
        }
1374

    
1375
        ArrayList resp = new ArrayList();
1376

    
1377
        for (int i = 0; i < resp_ind.size(); i++) {
1378
            Integer aux = (Integer) resp_ind.get(i);
1379
            resp.add(all.get(aux.intValue()));
1380
        }
1381

    
1382
        return resp;
1383
    }
1384

    
1385
    private static ArrayList getShellsIn(int[] final_contn, ArrayList all) {
1386
        ArrayList resp_ind = new ArrayList();
1387

    
1388
        for (int i = 0; i < final_contn.length; i++) {
1389
            if (final_contn[i] == -1) {
1390
                resp_ind.add(new Integer(i));
1391
            }
1392
        }
1393

    
1394
        ArrayList resp = new ArrayList();
1395

    
1396
        for (int i = 0; i < resp_ind.size(); i++) {
1397
            Integer aux = (Integer) resp_ind.get(i);
1398
            resp.add(all.get(aux.intValue()));
1399
        }
1400

    
1401
        return resp;
1402
    }
1403

    
1404
    /**
1405
     * This method tries to guess who is a shell and who is a hole from a set of
1406
     * linestrings.
1407
     *
1408
     * @param all_ls a set of linestrings to be checked.
1409
     *
1410
     * @return a 2-item array. the first is an arraylist of linestrings thought to be shells.
1411
     * the second is an array of arraylists containing the holes of each shell found in the
1412
     * first item
1413
     *
1414
     */
1415
    public static Object[] getHolesForShells(ArrayList all_ls) {
1416
        int no_of_ls = all_ls.size();
1417
        int[] containedby = new int[no_of_ls];
1418
        int[] shells;
1419
        int[] holes;
1420
        int[] final_cont;
1421

    
1422
        for (int i = 0; i < no_of_ls; i++) {
1423
            LineString3D ls_aux = (LineString3D) all_ls.get(i);
1424
            containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1425
        }
1426

    
1427
        shells = getIndicesOfShells(containedby);
1428
        holes = getIndicesOfHoles(containedby, shells);
1429
        final_cont = getFinalContainings(containedby, holes);
1430

    
1431
        // true shells:
1432
        shells = getIndicesOfShells(final_cont);
1433

    
1434
        ArrayList resp_shells = new ArrayList();
1435
        ArrayList resp_holes_for_shells = new ArrayList();
1436
        ArrayList aux_holes;
1437

    
1438
        for (int i = 0; i < shells.length; i++) {
1439
            resp_shells.add(all_ls.get(shells[i]));
1440
            aux_holes = getHolesOf(i, final_cont, all_ls);
1441
            resp_holes_for_shells.add(aux_holes);
1442
        }
1443

    
1444
        Object[] _resp = new Object[2];
1445
        _resp[0] = resp_shells;
1446
        _resp[1] = resp_holes_for_shells;
1447

    
1448
        return _resp;
1449
    }
1450

    
1451
    private static int getTotalSize(ArrayList listOfLists) {
1452
        int resp = 0;
1453

    
1454
        for (int i = 0; i < listOfLists.size(); i++) {
1455
            resp = resp + ((ArrayList) listOfLists.get(i)).size();
1456
        }
1457

    
1458
        return resp;
1459
    }
1460

    
1461
    // private static STRUCT // private static ArrayList getPolygonsEasily(FShape mpolygon) {
1462
    private static STRUCT getMultiPolygonAsStruct(FShape mpol, int srid,
1463
        boolean threed, IConnection _conn, boolean agu_bien, boolean hasSrid)
1464
        throws SQLException {
1465
        ArrayList all_ls = getPolygonsEasily(mpol);
1466
        Object[] hs = getHolesForShells(all_ls);
1467
        ArrayList sh = (ArrayList) hs[0];
1468
        ArrayList _ho = (ArrayList) hs[1];
1469
        ArrayList ho = reverseHoles(_ho);
1470

    
1471
        return getMultiPolygonAsStruct(sh, ho, srid, threed, _conn, agu_bien,
1472
            hasSrid);
1473
    }
1474

    
1475
    private static ArrayList reverseHoles(ArrayList hh) {
1476
        ArrayList resp = new ArrayList();
1477

    
1478
        for (int i = 0; i < hh.size(); i++) {
1479
            ArrayList item = (ArrayList) hh.get(i);
1480
            ArrayList newitem = new ArrayList();
1481

    
1482
            for (int j = 0; j < item.size(); j++) {
1483
                LineString3D ls = (LineString3D) item.get(j);
1484
                newitem.add(ls.createReverse());
1485
            }
1486

    
1487
            resp.add(newitem);
1488
        }
1489

    
1490
        return resp;
1491
    }
1492

    
1493
    private static STRUCT getMultiPolygonAsStruct(ArrayList shells,
1494
        ArrayList holes, int srid, boolean threed, IConnection _conn,
1495
        boolean explicito, boolean hasSrid) throws SQLException {
1496
        int t = 1003;
1497

    
1498
        if (explicito) {
1499
            t = 2003;
1500
        }
1501

    
1502
        int size = shells.size() + getTotalSize(holes);
1503
        int geotype = 2003;
1504
        if (size > 1) geotype = 2007;
1505

    
1506
        int dim = 2;
1507

    
1508
        if (threed) {
1509
            geotype = geotype + 1000;
1510
            dim = 3;
1511
        }
1512

    
1513
        NUMBER[] indices = new NUMBER[3 * size];
1514

    
1515
        int acum = 0;
1516
        int start_ind = 0;
1517

    
1518
        for (int i = 0; i < shells.size(); i++) {
1519
            indices[start_ind] = new NUMBER(acum + 1);
1520
            indices[start_ind + 1] = new NUMBER(1003);
1521
            indices[start_ind + 2] = new NUMBER(1);
1522
            start_ind = start_ind + 3;
1523
            acum = acum +
1524
                (dim * ((LineString3D) shells.get(i)).getLs().getNumPoints());
1525

    
1526
            ArrayList item_holes = (ArrayList) holes.get(i);
1527

    
1528
            for (int j = 0; j < item_holes.size(); j++) {
1529
                indices[start_ind] = new NUMBER(acum + 1);
1530
                indices[start_ind + 1] = new NUMBER(t); // 1003
1531
                indices[start_ind + 2] = new NUMBER(1);
1532
                start_ind = start_ind + 3;
1533
                acum = acum +
1534
                    (dim * ((LineString3D) item_holes.get(j)).getLs()
1535
                            .getNumPoints());
1536
            }
1537
        }
1538

    
1539
        int _ind = 0;
1540
        NUMBER[] ords = new NUMBER[acum];
1541

    
1542
        for (int i = 0; i < shells.size(); i++) {
1543
            // --------------------------------
1544
            LineString3D ls = (LineString3D) shells.get(i);
1545
            int num_p = ls.getLs().getNumPoints();
1546

    
1547
            for (int j = 0; j < num_p; j++) {
1548
                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1549
                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1550

    
1551
                if (threed) {
1552
                    ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1553
                }
1554

    
1555
                _ind = _ind + dim;
1556
            }
1557

    
1558
            // -------------------------------
1559
            ArrayList item_holes = (ArrayList) holes.get(i);
1560

    
1561
            for (int j = 0; j < item_holes.size(); j++) {
1562
                ls = (LineString3D) item_holes.get(j);
1563
                num_p = ls.getLs().getNumPoints();
1564

    
1565
                for (int k = 0; k < num_p; k++) {
1566
                    ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
1567
                    ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1568

    
1569
                    if (threed) {
1570
                        ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1571
                    }
1572

    
1573
                    _ind = _ind + dim;
1574
                }
1575
            }
1576
        }
1577

    
1578
        STRUCT resp;
1579
        StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
1580
                        ((ConnectionJDBC)_conn).getConnection());
1581
        Object[] obj = new Object[5];
1582
        obj[0] = new NUMBER(geotype);
1583

    
1584
        if (hasSrid) {
1585
            obj[1] = new NUMBER(srid);
1586
        }
1587
        else {
1588
            obj[1] = null;
1589
        }
1590

    
1591
        obj[2] = null;
1592
        obj[3] = indices;
1593
        obj[4] = ords;
1594

    
1595
        // String ind_str = printArray(indices);
1596
        // String ord_str = printArray(ords);
1597
        resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), obj);
1598

    
1599
        return resp;
1600
    }
1601

    
1602
    public static String printArray(NUMBER[] array) {
1603
        String resp = "[ ";
1604

    
1605
        for (int i = 0; i < array.length; i++) {
1606
            resp = resp + " " + array[i].doubleValue() + " , ";
1607
        }
1608

    
1609
        resp = resp.substring(0, resp.length() - 2) + "]";
1610

    
1611
        return resp;
1612
    }
1613

    
1614
    private static boolean isOneOf(int ind, int[] list) {
1615
        for (int i = 0; i < list.length; i++) {
1616
            if (list[i] == ind) {
1617
                return true;
1618
            }
1619
        }
1620

    
1621
        return false;
1622
    }
1623

    
1624
    /**
1625
     * This method appends the geometries from a geometry collection in one STRUCT.
1626
     *
1627
     * @param co the geometry collection
1628
     * @param _forced_type a type that has to be used as the struct's main type
1629
     * @param _conn the connection
1630
     * @param _o_srid the geometry's SRS (oracle code)
1631
     * @param withSrid whether the SRS is non-NULL
1632
     * @param agu_bien whether to check holes' validity
1633
     * @param _isGeoCS whether the SRS is geodetic
1634
     * @return the STRUCT with the appended geometries
1635
     */
1636
    public static STRUCT appendGeometriesInStruct(FGeometryCollection co,
1637
        int _forced_type, IConnection _conn, String _o_srid, boolean withSrid,
1638
        boolean agu_bien, boolean _isGeoCS) {
1639
        Geometry[] geoms = co.getGeometries();
1640
        int size = geoms.length;
1641
        STRUCT[] sts = new STRUCT[size];
1642

    
1643
        for (int i = 0; i < size; i++) {
1644
            sts[i] = OracleSpatialDriver.iGeometryToSTRUCT(geoms[i],
1645
                    _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS);
1646
        }
1647

    
1648
        if (size == 1) {
1649
            return sts[0];
1650
        }
1651

    
1652
        STRUCT aux = sts[0];
1653

    
1654
        for (int i = 1; i < size; i++) {
1655
            aux = appendStructs(aux, sts[i], _conn);
1656
        }
1657

    
1658
        return aux;
1659
    }
1660

    
1661
    private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection _conn) {
1662
        try {
1663
            ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1664
            int length_of_head_ords = _ords.getOracleArray().length;
1665

    
1666
            NUMBER gtype = new NUMBER(4 +
1667
                    (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1668
            NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1669
            NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1670

    
1671
            ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1672
            ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1673
            ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1674
            ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1675

    
1676
            Datum[] info = appendDatumArrays(info1.getOracleArray(),
1677
                    info2.getOracleArray(), length_of_head_ords);
1678

    
1679
            Datum[] ords = appendDatumArrays(ords1.getOracleArray(),
1680
                    ords2.getOracleArray(), 0);
1681

    
1682
            StructDescriptor dsc = st1.getDescriptor();
1683

    
1684
            Object[] atts = new Object[5];
1685
            atts[0] = gtype;
1686
            atts[1] = srid;
1687
            atts[2] = middle;
1688
            atts[3] = info;
1689
            atts[4] = ords;
1690

    
1691
            STRUCT resp = new STRUCT(dsc, ((ConnectionJDBC)_conn).getConnection(), atts);
1692

    
1693
            return resp;
1694
        }
1695
        catch (SQLException sqle) {
1696
            logger.error("While appending structs: " + sqle.getMessage(), sqle);
1697
        }
1698

    
1699
        return null;
1700
    }
1701

    
1702
    private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
1703
        int offset) {
1704
        int head_l = head.length;
1705
        int tail_l = tail.length;
1706
        Datum[] resp = new Datum[head_l + tail_l];
1707

    
1708
        for (int i = 0; i < head_l; i++)
1709
            resp[i] = head[i];
1710

    
1711
        if (offset == 0) {
1712
            for (int i = 0; i < tail_l; i++)
1713
                resp[head_l + i] = tail[i];
1714
        }
1715
        else {
1716
            try {
1717
                for (int i = 0; i < tail_l; i++) {
1718
                    if ((i % 3) == 0) {
1719
                        resp[head_l + i] = new NUMBER(tail[i].intValue() +
1720
                                offset);
1721
                    }
1722
                    else {
1723
                        resp[head_l + i] = tail[i];
1724
                    }
1725
                }
1726
            }
1727
            catch (SQLException se) {
1728
                logger.error("Unexpected error: " + se.getMessage());
1729
            }
1730
        }
1731

    
1732
        return resp;
1733
    }
1734

    
1735
    /**
1736
     * Utility method to get an ineteger as a formatted string.
1737
     *
1738
     * @param n the integer
1739
     * @return the formatted string
1740
     */
1741
    public static String getFormattedInteger(int n) {
1742
        df.setGroupingUsed(true);
1743
        df.setGroupingSize(3);
1744
        dfs.setGroupingSeparator('.');
1745
        df.setDecimalFormatSymbols(dfs);
1746

    
1747
        return df.format(n);
1748
    }
1749

    
1750
    /**
1751
     * Tells whether these arrays belong to a rectangle polygon.
1752
     *
1753
     * @param info the struct's element info array
1754
     * @param ords the struct's coordinate array
1755
     * @return true if it is a rectangle polygon. false otherwise.
1756
     */
1757
    public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
1758
        try {
1759
            int[] infos = info.getIntArray();
1760

    
1761
            return ((infos[2] == 3) && (infos.length == 3));
1762
        }
1763
        catch (SQLException se) {
1764
            logger.error("While ckecking rectangle: " + se.getMessage(), se);
1765
        }
1766

    
1767
        return false;
1768
    }
1769

    
1770
    /**
1771
     * Utility method to deal with oracle info arrays.
1772
     */
1773
    public static ARRAY getDevelopedInfoArray(ARRAY info) {
1774
        ARRAY _resp = null;
1775

    
1776
        try {
1777
            Datum[] resp = new Datum[3];
1778
            Datum[] in = info.getOracleArray();
1779
            resp[0] = in[0];
1780
            resp[1] = in[1];
1781
            resp[2] = new NUMBER(1);
1782
            _resp = new ARRAY(info.getDescriptor(),
1783
                    info.getInternalConnection(), resp);
1784
        }
1785
        catch (SQLException se) {
1786
            logger.error("While creating ARRAY: " + se.getMessage(), se);
1787
        }
1788

    
1789
        return _resp;
1790
    }
1791

    
1792
    /**
1793
     * Utility method to deal with oracle coordinate arrays.
1794
     */
1795
    public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
1796
        ARRAY _resp = null;
1797

    
1798
        try {
1799
            Datum[] resp = new Datum[10];
1800
            Datum[] corners = ords.getOracleArray();
1801

    
1802
            // x
1803
            resp[0] = corners[0];
1804
            resp[2] = corners[2];
1805
            resp[4] = corners[2];
1806
            resp[6] = corners[0];
1807
            resp[8] = corners[0];
1808

    
1809
            // y
1810
            resp[1] = corners[1];
1811
            resp[3] = corners[1];
1812
            resp[5] = corners[3];
1813
            resp[7] = corners[3];
1814
            resp[9] = corners[1];
1815
            _resp = new ARRAY(ords.getDescriptor(),
1816
                    ords.getInternalConnection(), resp);
1817
        }
1818
        catch (SQLException se) {
1819
            logger.error("While creating ARRAY: " + se.getMessage(), se);
1820
        }
1821

    
1822
        return _resp;
1823
    }
1824

    
1825
    /**
1826
     * utility method to convert a STRUCT into a GeneralPathX
1827
     * @param aux the struct's datum array
1828
     * @return the GeneralPathX instance created
1829
     */
1830
    public static GeneralPathX structToGPX(Datum[] aux) {
1831
        GeneralPathX resp = new GeneralPathX();
1832
        ARRAY infoARRAY = null;
1833
        ARRAY ordsARRAY = null;
1834
        Datum[] info_array = null;
1835
        Datum[] ords_array = null;
1836
        int info_array_size = 0;
1837
        int[] start_ind;
1838
        int[] end_ind;
1839
        int dims = 0;
1840
        boolean next_must_do_first = true;
1841

    
1842
        try {
1843
            infoARRAY = (ARRAY) aux[3];
1844
            ordsARRAY = (ARRAY) aux[4];
1845

    
1846
            if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
1847
                infoARRAY = getDevelopedInfoArray(infoARRAY);
1848
                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
1849
            }
1850

    
1851
            dims = ((NUMBER) aux[0]).intValue() / 1000;
1852

    
1853
            if (dims == 0) {
1854
                dims = 2;
1855
            }
1856

    
1857
            info_array = (Datum[]) infoARRAY.getOracleArray();
1858
            ords_array = (Datum[]) ordsARRAY.getOracleArray();
1859
            info_array_size = info_array.length / 3;
1860

    
1861
            int last_index = ords_array.length - dims + 1;
1862

    
1863
            // set indices:
1864
            start_ind = new int[info_array_size];
1865
            end_ind = new int[info_array_size];
1866

    
1867
            for (int i = 0; i < info_array_size; i++)
1868
                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
1869

    
1870
            for (int i = 0; i < (info_array_size - 1); i++)
1871
                end_ind[i] = start_ind[i + 1] - 1;
1872

    
1873
            end_ind[info_array_size - 1] = last_index;
1874

    
1875
            int lineType = PathIterator.SEG_LINETO;
1876

    
1877
            if (end_ind[0] == 0) { // collection of paths
1878

    
1879
                for (int i = 1; i < info_array_size; i++) {
1880
                    lineType = getLineToType(info_array, i);
1881

    
1882
                    // -----------------------
1883
                    if (end_ind[i] == (start_ind[i] - 1))
1884
                            lineType = PathIterator.SEG_MOVETO;
1885
                    // -----------------------
1886

    
1887
                    next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
1888
                            end_ind[i] - 1, ords_array, dims, lineType,
1889
                            (i == 1) || (lineType == PathIterator.SEG_MOVETO),
1890
                            next_must_do_first);
1891
                }
1892
            } else {
1893
                // standard case, do the moveto always
1894
                for (int i = 0; i < info_array_size; i++) {
1895
                    lineType = getLineToType(info_array, i);
1896
                    addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1,
1897
                        ords_array, dims, lineType, true, true);
1898
                }
1899
            }
1900

    
1901
            // boolean do_the_moves = true;
1902
        }
1903
        catch (SQLException se) {
1904
            logger.error("While creating GPX: " + se.getMessage(), se);
1905
        }
1906

    
1907
        return resp;
1908
    }
1909

    
1910
    private static int getLineToType(Datum[] infos, int i) {
1911
        int resp = PathIterator.SEG_LINETO;
1912

    
1913
        try {
1914
            if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) {
1915
                resp = PathIterator.SEG_QUADTO;
1916
            }
1917
        }
1918
        catch (SQLException e) {
1919
            logger.error("While getting line-to type: " + e.getMessage() +
1920
                " (returned SEG_LINETO)");
1921
        }
1922

    
1923
        return resp;
1924
    }
1925

    
1926
    private static boolean addOrdsToGPX(GeneralPathX gpx, int zero_based_start,
1927
        int zero_based_include_end, Datum[] ords, int d, int ltype,
1928
        boolean do_the_move, boolean must_do_first) {
1929
        int length = ords.length;
1930
        boolean return_following_must_do_first = true;
1931

    
1932
        double x = ((NUMBER) ords[zero_based_start]).doubleValue();
1933
        double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
1934

    
1935
        if (must_do_first) {
1936
            if (do_the_move) {
1937
                gpx.moveTo(x, y);
1938
            }
1939
            else {
1940
                gpx.lineTo(x, y);
1941
            }
1942
        }
1943

    
1944
        int ind = 1;
1945

    
1946
        int size = ((zero_based_include_end - zero_based_start) / d) + 1;
1947
        int indx;
1948
        int indx2;
1949

    
1950
        if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
1951

    
1952
            double x2;
1953
            double y2;
1954

    
1955
            while (ind < size) {
1956
                indx = zero_based_start + (ind * d);
1957
                x = ((NUMBER) ords[indx]).doubleValue();
1958
                y = ((NUMBER) ords[indx + 1]).doubleValue();
1959

    
1960
                indx2 = zero_based_start + ((ind + 1) * d);
1961

    
1962
                if (indx >= length) {
1963
                    indx2 = zero_based_start;
1964
                }
1965

    
1966
                x2 = ((NUMBER) ords[indx2]).doubleValue();
1967
                y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
1968
                gpx.quadTo(x, y, x2, y2);
1969
                ind++;
1970
                ind++;
1971
            }
1972

    
1973
            return_following_must_do_first = false;
1974
        }
1975
        else { // PathIterator.SEG_LINETO (interpretation = 1)
1976

    
1977
            while (ind < size) {
1978
                indx = zero_based_start + (ind * d);
1979
                x = ((NUMBER) ords[indx]).doubleValue();
1980
                y = ((NUMBER) ords[indx + 1]).doubleValue();
1981
                gpx.lineTo(x, y);
1982
                ind++;
1983
            }
1984
        }
1985

    
1986
        return return_following_must_do_first;
1987
    }
1988

    
1989
    /**
1990
     * Utility method. Gets FShape type from oracle geometry type.
1991
     * @param otype
1992
     * @return FShape type
1993
     */
1994
    public static int oracleGTypeToGvsigGeometryType(int otype) {
1995
            switch (otype) {
1996
                case OracleValues.ORACLE_GTYPE_UNKNOWN:
1997
                        return Geometry.TYPES.NULL;
1998

    
1999
                case OracleValues.ORACLE_GTYPE_POINT:
2000
                case OracleValues.ORACLE_GTYPE_MULTIPOINT:
2001
                        return Geometry.TYPES.POINT;
2002

    
2003
                case OracleValues.ORACLE_GTYPE_LINE:
2004
                case OracleValues.ORACLE_GTYPE_MULTILINE:
2005
                        return Geometry.TYPES.CURVE;
2006

    
2007
                case OracleValues.ORACLE_GTYPE_POLYGON:
2008
                case OracleValues.ORACLE_GTYPE_MULTIPOLYGON:
2009
                        return Geometry.TYPES.SURFACE;
2010

    
2011
                case OracleValues.ORACLE_GTYPE_COLLECTION:
2012
                        return Geometry.TYPES.AGGREGATE;
2013
                }
2014

    
2015
                logger.warn("Unknown oracle geometry type: " + otype);
2016

    
2017
                return Geometry.TYPES.NULL;
2018
    }
2019

    
2020
    /**
2021
     * Utility method to get struct's type.
2022
     * @param the_data the struct's datum array
2023
     * @return the struct type
2024
     */
2025
    public static int getStructType(Datum[] the_data) {
2026
        int resp = -1;
2027

    
2028
        try {
2029
            resp = ((NUMBER) the_data[0]).intValue() % 1000;
2030
        }
2031
        catch (SQLException se) {
2032
            logger.error("Error: " + se.getMessage(), se);
2033
        }
2034

    
2035
        return resp;
2036
    }
2037

    
2038
    /**
2039
     * Utility method to get struct's SRID.
2040
     * @param the_data the struct's datum array
2041
     * @return the struct0's SRID
2042
     */
2043
    public static int getStructSRID(Datum[] the_data) {
2044
        int resp = -1;
2045

    
2046
        try {
2047
            resp = ((NUMBER) the_data[1]).intValue();
2048
        }
2049
        catch (SQLException se) {
2050
            logger.error("Error: " + se.getMessage(), se);
2051
        }
2052

    
2053
        return resp;
2054
    }
2055

    
2056
    /**
2057
     * Utility method to find out if  a struct is a circle.
2058
     *
2059
     * @param the_data the struct's datum array
2060
     * @return whether it is a circle
2061
     */
2062
    public static boolean isCircle(Datum[] the_data) {
2063
        int[] info = null;
2064

    
2065
        try {
2066
            info = ((ARRAY) the_data[3]).getIntArray();
2067
        }
2068
        catch (SQLException se) {
2069
            logger.error("While cheking circle: " + se.getMessage(), se);
2070

    
2071
            return false;
2072
        }
2073

    
2074
        if (info == null) {
2075
            return false;
2076
        }
2077

    
2078
        boolean resp = ((info.length == 3) && (info[2] == 4));
2079

    
2080
        return resp;
2081
    }
2082

    
2083
    /**
2084
     * Gets the struct's dimension size.
2085
     * @param st the struct
2086
     * @return the structs dimension
2087
     */
2088
    public static int getStructDimensions(STRUCT st) {
2089
        int resp = -1;
2090

    
2091
        try {
2092
            resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2093
        }
2094
        catch (SQLException se) {
2095
            logger.error("Error: " + se.getMessage(), se);
2096
        }
2097

    
2098
        if (resp < 2) {
2099
            resp = 2;
2100
        }
2101

    
2102
        return resp;
2103
    }
2104

    
2105
    /**
2106
     * Gets a struct's coordinates array.
2107
     * @param the_data the struct's datum array
2108
     * @return the coordinates array
2109
     */
2110
    public static double[] getOrds(Datum[] the_data) {
2111
        double[] resp = null;
2112

    
2113
        try {
2114
            ARRAY aux = (ARRAY) the_data[4];
2115

    
2116
            if (aux == null) {
2117
                return null;
2118
            }
2119

    
2120
            resp = aux.getDoubleArray();
2121
        }
2122
        catch (SQLException se) {
2123
            logger.error("While getting ordinates: " + se.getMessage(), se);
2124
        }
2125

    
2126
        return resp;
2127
    }
2128

    
2129
    /**
2130
     * Utility method to create a struct with the given data.
2131
     * @param type struct type
2132
     * @param srid coordinate system
2133
     * @param info element info array
2134
     * @param ords coordinates array
2135
     * @param conn connection
2136
     * @return the created struct
2137
     */
2138
    public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info,
2139
        Datum[] ords, Connection conn) {
2140
        try {
2141
            StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
2142
                    conn);
2143
            Object[] obj = new Object[5];
2144
            obj[0] = type;
2145
            obj[1] = srid;
2146
            obj[2] = null;
2147
            obj[3] = info;
2148
            obj[4] = ords;
2149

    
2150
            return new STRUCT(dsc, conn, obj);
2151
        }
2152
        catch (SQLException se) {
2153
            logger.error("While creating STRUCT: " + se.getMessage(), se);
2154
        }
2155

    
2156
        return null;
2157
    }
2158

    
2159
    public static String getDimInfoAsString(ARRAY dim_info) {
2160
            String resp = "DIMENSIONS: ";
2161

    
2162
        if (dim_info == null) {
2163
            return "NULL" + "\n";
2164
        }
2165
        else {
2166
                try {
2167
                                Datum[] da = dim_info.getOracleArray();
2168
                                int size = da.length;
2169
                                resp = resp + size + "\n";
2170
                                for (int i = 0; i < size; i++) {
2171
                                        STRUCT dim_itemx = (STRUCT) da[i];
2172
                                        Object[] dim_desc = dim_itemx.getAttributes();
2173
                                        resp = resp + "DIMENSION " + i + ": " + ", NAME: "
2174
                                                        + dim_desc[0].toString() + ", MIN: "
2175
                                                        + dim_desc[1].toString() + ", MAX: "
2176
                                                        + dim_desc[2].toString() + ", TOL: "
2177
                                                        + dim_desc[3].toString();
2178
                                        if (i != (size -1)) {
2179
                                                resp = resp + "\n";
2180
                                        }
2181
                                }
2182
                        } catch (Exception ex) {
2183
                                return "ERROR: " + ex.getMessage() + "\n";
2184
                        }
2185
        }
2186
        return resp;
2187
    }
2188

    
2189
    public static STRUCT reprojectGeometry(Connection conn, STRUCT fromStruct, String toSrid) {
2190

    
2191
            String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2192
            STRUCT resp = null;
2193

    
2194
            try {
2195
                        PreparedStatement _st = ((ConnectionJDBC)conn).getConnection().prepareStatement(qry);
2196
                        _st.setObject(1, fromStruct);
2197
                        ResultSet _rs = _st.executeQuery();
2198

    
2199
                        if (_rs.next()) {
2200
                                resp = (STRUCT) _rs.getObject(1);
2201
                        } else {
2202
                                logger.error("While executing reprojection: empty resultset (?)");
2203
                                return fromStruct;
2204
                        }
2205
                } catch (Exception ex) {
2206
                        logger.error("While reprojecting: " + ex.getMessage());
2207
                        return fromStruct;
2208
                }
2209

    
2210
        if (resp == null) {
2211
                return fromStruct;
2212
        } else {
2213
                return resp;
2214
        }
2215
    }
2216
    
2217
    
2218
    public static void printStruct(STRUCT st) {
2219
            
2220
        logger.debug("----------------------------------------------");
2221
        logger.debug("-- 16 FEBRERO 2009 ---------------------------");
2222
        logger.debug("----------------------------------------------");
2223

    
2224
        try {
2225
            Object[] att = st.getAttributes();
2226
            int l = att.length;
2227

    
2228
            for (int i = 0; i < l; i++) {
2229
                    if (att[i] != null) {
2230
                            if (att[i] instanceof ARRAY) {
2231
                                    ARRAY arr = (ARRAY) att[i];
2232
                                    logger.debug("ATT " + i + ": ");
2233
                                    printARRAY(arr);
2234
                            } else {
2235
                                    logger.debug("ATT " + i + ": " + att[i].toString());
2236
                            }
2237
                    logger.debug("----------------------------------------------");
2238
                    }
2239
            }
2240
        }
2241
        catch (Exception ex) {
2242
                logger.debug("-- Error: " + ex.getMessage());
2243
        }
2244

    
2245
    }
2246

    
2247
        private static void printARRAY(ARRAY arr) throws Exception {
2248
                
2249
                int[] intarr = arr.getIntArray();
2250
                if (intarr == null) {
2251
                        float[] floarr = arr.getFloatArray();
2252
                        if (floarr == null) {
2253
                                logger.debug("INT NULL y FLOAT NULL (?)");
2254
                        } else {
2255
                                int len = floarr.length;
2256
                                for (int i=0; i<len; i++) {
2257
                                        if (Math.min(i, (len - i)) < 20) {
2258
                                                logger.debug("" + floarr[i]);
2259
                                        }
2260
                                }
2261
                        }
2262
                        
2263
                } else {
2264
                        int len = intarr.length;
2265
                        for (int i=0; i<len; i++) {
2266
                                if (Math.min(i, (len - i)) < 20) {
2267
                                        logger.debug("" + intarr[i]);
2268
                                }
2269
                        }
2270
                }
2271
        }
2272

    
2273
    /**
2274
     * Utility method. Gets FShape type from oracle geometry type.
2275
     * @param otype
2276
     * @return FShape type
2277
     */
2278
    public static int oracleGTypeToFShapeType(int otype, boolean complex) {
2279
            
2280
            int resp = FShape.NULL;
2281
            
2282
            if (complex) {
2283
                    
2284
                    switch (otype) {
2285
                    case ORACLE_GTYPE_COMPLEX_VOIDED_POLYON:
2286
                    case ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON:
2287
                            resp = FShape.POLYGON;
2288
                            break;
2289
                    case ORACLE_GTYPE_COMPLEX_COMPOUND_LINE:
2290
                            resp = FShape.LINE;
2291
                            break;
2292
                    }
2293

    
2294
            } else {
2295

    
2296
                    // =========== not complex =================
2297
            switch (otype) {
2298
            case ORACLE_GTYPE_UNKNOWN:
2299
                    resp = FShape.NULL;
2300
                break;
2301

    
2302
            case ORACLE_GTYPE_POINT:
2303
            case ORACLE_GTYPE_MULTIPOINT:
2304
                    resp = FShape.POINT;
2305
                break;
2306

    
2307
            case ORACLE_GTYPE_LINE:
2308
            case ORACLE_GTYPE_MULTILINE:
2309
                    resp = FShape.LINE;
2310
                break;
2311

    
2312
            case ORACLE_GTYPE_POLYGON:
2313
            case ORACLE_GTYPE_MULTIPOLYGON:
2314
                    resp = FShape.POLYGON;
2315
                break;
2316

    
2317
            case ORACLE_GTYPE_COLLECTION:
2318
                    resp = FShape.MULTI;
2319
                break;
2320
            }
2321
                    // =========== not complex =================
2322
            }
2323
            
2324
            if (resp == FShape.NULL) {
2325
                    logger.error("Unknown oracle geometry type: " + otype);
2326
            }
2327
        return resp;
2328
    }
2329
    
2330

    
2331
        
2332
        private static boolean isOneOfThese(String name, String[] arr) {
2333

    
2334
                for (int i=0; i<arr.length; i++) {
2335
                                if (arr[i].compareToIgnoreCase(name) == 0) return true; 
2336
                        }
2337
                return false;
2338
        }
2339
        
2340
    public static boolean hasSeveralGeometryTypes(ArrayList tt, boolean are_dims) {
2341
        if (tt.size() == 0) {
2342
            return false;
2343
        }
2344

    
2345
        HashMap m = new HashMap();
2346

    
2347
        for (int i = 0; i < tt.size(); i++) {
2348
            Integer integ = (Integer) tt.get(i);
2349
            int val = integ.intValue();
2350

    
2351
            if ((val == 4) && (!are_dims)) {
2352
                return true;
2353
            }
2354

    
2355
            m.put("" + (val % 4), "a type");
2356
        }
2357

    
2358
        Iterator iter = m.keySet().iterator();
2359
        iter.next();
2360

    
2361
        return iter.hasNext();
2362
    }
2363

    
2364
    public static void showMemory() {
2365
        Runtime r = Runtime.getRuntime();
2366
        long mem = r.totalMemory() - r.freeMemory();
2367
        logger.info("Total memory : " + mem);
2368
    }
2369
    
2370

    
2371
    
2372
    private static double[] getIndDoublesModule(double[] input, int ind, int n) {
2373
        int size = input.length / n;
2374
        double[] resp = new double[size];
2375

    
2376
        for (int i = 0; i < size; i++) {
2377
            resp[i] = input[(i * n) + ind];
2378
        }
2379

    
2380
        return resp;
2381
    }
2382
    
2383
    private static double[] getIndBigDecimalModule(double[] input, int ind, int n) {
2384
        int size = input.length / n;
2385
        double[] resp = new double[size];
2386

    
2387
        for (int i = 0; i < size; i++) {
2388
            resp[i] = input[(i * n) + ind];
2389
        }
2390

    
2391
        return resp;
2392
    }
2393
    
2394
    public static IGeometry getFMapGeometryMultipolygon(Datum[] the_data, int dim) {
2395
        IGeometry ig = null;
2396

    
2397
        if (OracleSpatialUtils.isCircle(the_data)) {
2398
            ig = getCircleFromStruct(the_data);
2399
        }
2400
        else {
2401
            GeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
2402

    
2403
            if (dim == 2) {
2404
                ig = ShapeFactory.createPolygon2D(gpx);
2405
            }
2406
            else {
2407
                double[] ords = null;
2408

    
2409
                try {
2410
                    ords = ((ARRAY) the_data[4]).getDoubleArray();
2411
                }
2412
                catch (SQLException se) {
2413
                    logger.error("While getting ordinates: " + se.getMessage(),
2414
                        se);
2415
                }
2416

    
2417
                double[] z = getIndBigDecimalModule(ords, 2, dim);
2418
                ig = ShapeFactory.createPolygon3D(gpx, z);
2419
            }
2420
        }
2421

    
2422
        return ig;
2423
    }
2424
    
2425
    private static IGeometry getCircleFromStruct(Datum[] the_data) {
2426
        double[] threep = null;
2427

    
2428
        try {
2429
            threep = ((ARRAY) the_data[4]).getDoubleArray();
2430
        }
2431
        catch (SQLException se) {
2432
            logger.error("While getting ords from struct: " + se.getMessage(),
2433
                se);
2434

    
2435
            return new FNullGeometry();
2436
        }
2437

    
2438
        Point2D[] three = new Point2D.Double[3];
2439
        three[0] = new Point2D.Double(threep[0], threep[1]);
2440
        three[1] = new Point2D.Double(threep[2], threep[3]);
2441
        three[2] = new Point2D.Double(threep[4], threep[5]);
2442

    
2443
        Object[] cent_rad = OracleSpatialUtils.getCenterAndRadiousOfCirc(three);
2444

    
2445
        Point2D cent = (Point2D) cent_rad[0];
2446
        double radius = ((Double) cent_rad[1]).doubleValue();
2447

    
2448
        IGeometry circ = ShapeFactory.createCircle(cent, radius);
2449

    
2450
        return circ;
2451
    }
2452
    
2453
    public static Geometry getFMapGeometryMultiLineString(Datum[] the_data, int dim) {
2454
            
2455
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
2456
        GeneralPathX gpx = OracleSpatialUtils.structToGPX(the_data);
2457
        Geometry ig = null;
2458
        double[] ords = null;
2459

    
2460
        if (dim == 2) {
2461
            ig = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM2D);
2462
        }
2463
        else {
2464
            ords = OracleSpatialUtils.getOrds(the_data);
2465

    
2466
            double[] z = getIndBigDecimalModule(ords, 2, dim);
2467
            ig = ShapeFactory.createPolyline3D(gpx, z);
2468
        }
2469

    
2470
        return ig;
2471
    }
2472

    
2473
    
2474
    public static Geometry getFMapGeometryPoint(Datum[] the_data, int dim) {
2475
        double[] ords = OracleSpatialUtils.getOrds(the_data);
2476

    
2477
        if (ords == null) { // sdo_point
2478

    
2479
            return getFMapGeometrySdoPoint(the_data, dim);
2480
        }
2481

    
2482
        Geometry ig = null;
2483
        int total_size = ords.length;
2484
        int no_po = total_size / dim;
2485
        double[] x = new double[no_po];
2486
        double[] y = new double[no_po];
2487
        double[] z = new double[no_po];
2488

    
2489
        for (int i = 0; i < no_po; i++) {
2490
            x[i] = ords[i * dim]; // pp[i].getX();
2491
            y[i] = ords[(i * dim) + 1];
2492

    
2493
            if (dim >= 3) {
2494
                z[i] = ords[(i * dim) + 2];
2495
            }
2496
        }
2497

    
2498
        if (dim == 2) {
2499
            if (no_po == 1) {
2500
                ig = ShapeFactory.createPoint2D(x[0], y[0]);
2501
            }
2502
            else {
2503
                ig = ShapeFactory.createMultipoint2D(x, y);
2504
            }
2505
        }
2506
        else {
2507
            if (no_po == 1) {
2508
                ig = ShapeFactory.createPoint3D(x[0], y[0], z[0]);
2509
            }
2510
            else {
2511
                ig = ShapeFactory.createMultipoint3D(x, y, z);
2512
            }
2513
        }
2514

    
2515
        return ig;
2516
    }
2517
    
2518
    public static Geometry getFMapGeometrySdoPoint(Datum[] the_data, int d) throws CreateGeometryException {
2519
            
2520
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
2521
            
2522
        double x = 0;
2523
        double y = 0;
2524
        double z = 0;
2525

    
2526
        try {
2527
            Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
2528
            x = ((NUMBER) aux[0]).doubleValue();
2529
            y = ((NUMBER) aux[1]).doubleValue();
2530

    
2531
            if (d > 2) {
2532
                z = ((NUMBER) aux[2]).doubleValue();
2533
            }
2534
        }
2535
        catch (SQLException se) {
2536
            logger.error("While getting sdo point ordinates: " +
2537
                se.getMessage(), se);
2538
        }
2539

    
2540
        Geometry geom = null;
2541

    
2542
        if (d == 2) {
2543
                geom = geomManager.createPoint(x, y, Geometry.SUBTYPES.GEOM2D);
2544
        }
2545
        else {
2546
                
2547
                Point2DZ point = (Point2DZ)geomManager.create(Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DZ);
2548
                point.setX(x);
2549
                point.setY(y);
2550
                point.setCoordinateAt(3, z);
2551
                geom = point;
2552
        }
2553

    
2554
        return geom;
2555
    }
2556

    
2557
    
2558
    public static boolean isActuallyACollection(Datum[] the_data) {
2559
        int[] info = null;
2560

    
2561
        try {
2562
            ARRAY aux = (ARRAY) the_data[3];
2563

    
2564
            if (aux == null) {
2565
                return false;
2566
            }
2567

    
2568
            info = aux.getIntArray();
2569
        }
2570
        catch (SQLException se) {
2571
            logger.error("While checking collection: " + se.getMessage());
2572
            return false;
2573
        }
2574

    
2575
        if (info == null) {
2576
            return false; // sdo_point
2577
        }
2578

    
2579
        int size = info.length / 3;
2580

    
2581
        if (size == 1) {
2582
            return false;
2583
        }
2584

    
2585
        if (size == 2) {
2586
            return ((info[1] % 1000) != (info[4] % 1000)) &&
2587
            ( ! ((info[1] == 1005) && (info[4] == 2)) );
2588
        }
2589

    
2590
        int second = info[4] % 1000;
2591
        int item = 0;
2592

    
2593
        for (int i = 2; i < size; i++) {
2594
                item = info[(i * 3) + 1] % 1000;
2595
            if ((item != second) &&
2596
                            ( ! ((item == 5) && (second == 2)) )
2597
                            ) {
2598
                return true;
2599
            }
2600
        }
2601

    
2602
        return false;
2603
    }
2604

    
2605
    
2606
    public static Datum[] updateIndexes(Datum[] info) {
2607
        int size = info.length / 3;
2608
        NUMBER[] resp = new NUMBER[3 * size];
2609

    
2610
        try {
2611
            int rest = info[0].intValue() - 1;
2612

    
2613
            for (int i = 0; i < size; i++) {
2614
                resp[3 * i] = new NUMBER(info[3 * i].intValue() - rest);
2615
                resp[(3 * i) + 1] = new NUMBER(info[(3 * i) + 1].intValue());
2616
                resp[(3 * i) + 2] = new NUMBER(info[(3 * i) + 2].intValue());
2617
            }
2618
        }
2619
        catch (SQLException se) {
2620
            logger.error("Unexpected error: " + se.getMessage());
2621
        }
2622

    
2623
        return resp;
2624
    }
2625
    
2626
    public static double[] getSubSet(double[] all, int first_inc, int last_inc) {
2627
        double[] resp = new double[last_inc - first_inc + 1];
2628

    
2629
        for (int i = first_inc; i <= last_inc; i++) {
2630
            resp[i - first_inc] = all[i];
2631
        }
2632

    
2633
        return resp;
2634
    }
2635
    
2636
    public static Object[] getOrdOfGroups(Datum[] all, Object[] groups) throws SQLException {
2637
        Object[] resp = new Object[groups.length];
2638

    
2639
        if (resp.length == 1) {
2640
            resp[0] = all;
2641

    
2642
            return resp;
2643
        }
2644

    
2645
        int ind = 0;
2646
        Datum[] aux = (Datum[]) groups[1];
2647
        int _end = aux[0].intValue() - 2;
2648
        Datum[] ord_aux = getSubSet(all, 0, _end);
2649

    
2650
        int _start = _end + 1;
2651
        resp[ind] = ord_aux;
2652
        ind++;
2653

    
2654
        for (int i = 2; i < groups.length; i++) {
2655
            aux = (Datum[]) groups[i];
2656
            _end = aux[0].intValue() - 2;
2657
            ord_aux = getSubSet(all, _start, _end);
2658
            resp[ind] = ord_aux;
2659
            ind++;
2660
            _start = _end + 1;
2661
        }
2662

    
2663
        // last
2664
        _end = all.length - 1;
2665
        ord_aux = getSubSet(all, _start, _end);
2666
        resp[groups.length - 1] = ord_aux;
2667

    
2668
        return resp;
2669
    }
2670
    
2671
    
2672
    
2673
    public static Object[] getOrdOfGroups(double[] all, Object[] groups) {
2674
        Object[] resp = new Object[groups.length];
2675

    
2676
        if (resp.length == 1) {
2677
            resp[0] = all;
2678

    
2679
            return resp;
2680
        }
2681

    
2682
        int ind = 0;
2683
        int[] aux = (int[]) groups[1];
2684
        int _end = aux[0] - 2;
2685
        double[] ord_aux = getSubSet(all, 0, _end);
2686

    
2687
        int _start = _end + 1;
2688
        resp[ind] = ord_aux;
2689
        ind++;
2690

    
2691
        for (int i = 2; i < groups.length; i++) {
2692
            aux = (int[]) groups[i];
2693
            _end = aux[0] - 2;
2694
            ord_aux = getSubSet(all, _start, _end);
2695
            resp[ind] = ord_aux;
2696
            ind++;
2697
            _start = _end + 1;
2698
        }
2699

    
2700
        // last
2701
        _end = all.length - 1;
2702
        ord_aux = getSubSet(all, _start, _end);
2703
        resp[groups.length - 1] = ord_aux;
2704

    
2705
        return resp;
2706
    }
2707
    
2708
    
2709
    public static Object[] groupByElement(int[] all_elem) {
2710
        ArrayList resp = new ArrayList();
2711

    
2712
        int size = all_elem.length / 3;
2713

    
2714
        int[] aux = getNthGroupOfThree(all_elem, 0);
2715

    
2716
        int[] newaux;
2717
        int i = 1;
2718

    
2719
        while (i < size) {
2720
            newaux = getNthGroupOfThree(all_elem, i);
2721

    
2722
            if (newaux[0] == aux[0]) {
2723
                // aux[2] says how many components
2724
                for (int j = 0; j < aux[2]; j++) {
2725
                    aux = appendIntArrays(aux,
2726
                            getNthGroupOfThree(all_elem, j + i));
2727
                }
2728

    
2729
                resp.add(aux);
2730
                i = i + aux[2];
2731
                aux = getNthGroupOfThree(all_elem, i);
2732
            }
2733
            else {
2734
                if (newaux[1] == 2003) {
2735
                    aux = appendIntArrays(aux, newaux);
2736
                }
2737
                else {
2738
                    resp.add(aux);
2739
                    aux = getNthGroupOfThree(all_elem, i);
2740
                }
2741
            }
2742

    
2743
            i++;
2744
        }
2745

    
2746
        resp.add(aux);
2747

    
2748
        return resp.toArray();
2749
    }
2750
    
2751
    public static boolean isSimpleCollectionOfLines(Datum[] all_elem) {
2752
            
2753
            try {
2754
                int size = all_elem.length;
2755
                if (all_elem[1].intValue() != 4) return false;
2756
                int size3 = size / 3;
2757
                
2758
                for (int i=1; i<size3; i++) {
2759
                        if (all_elem[3 * i + 1].intValue() != 2) return false; 
2760
                }
2761
                return true;
2762
                
2763
            } catch (SQLException ex) {
2764
                    logger.error("While is simple line collection: " + ex.getMessage());
2765
            }
2766
            
2767
            return false;
2768
    }
2769
    
2770
    public static Datum[] removeThreeFirst(Datum[] elem) {
2771
            int sz = elem.length;
2772
            Datum[] resp = new Datum[sz - 3];
2773
            for (int i=3; i<sz; i++) resp[i - 3] = elem[i];
2774
            return resp;
2775
    }
2776
    
2777
    public static Object[] groupByElement(Datum[] all_elem) {
2778
            
2779
            if (isSimpleCollectionOfLines(all_elem)) {
2780
                    Object[] r = new Object[1];
2781
                    r[0] = removeThreeFirst(all_elem);
2782
                    return r;
2783
            }
2784
            
2785
        ArrayList resp = new ArrayList();
2786

    
2787
        int size = all_elem.length / 3;
2788

    
2789
        Datum[] aux = getNthGroupOfThree(all_elem, 0);
2790

    
2791
        Datum[] newaux;
2792
        int i = 1;
2793
        boolean add_last_time = true;
2794

    
2795
        try {
2796
            while (i < size) {
2797
                newaux = getNthGroupOfThree(all_elem, i);
2798

    
2799
                if (newaux[0].intValue() == aux[0].intValue()) {
2800
                    // aux[2] says how many components
2801
                    for (int j = 0; j < ((NUMBER) aux[2]).intValue(); j++) {
2802
                        aux = appendDatArrays(aux,
2803
                                getNthGroupOfThree(all_elem, j + i));
2804
                    }
2805

    
2806
                    resp.add(aux);
2807
                    i = i + ((NUMBER) aux[2]).intValue();
2808
                    if (i < size) { // in some cases (line collection, 4)
2809
                            aux = getNthGroupOfThree(all_elem, i);
2810
                    } else {
2811
                            add_last_time = false;
2812
                    }
2813
                }
2814
                else {
2815
                    if (((NUMBER) newaux[1]).intValue() == 2003) {
2816
                        aux = appendDatArrays(aux, newaux);
2817
                    } else {
2818
                        resp.add(aux);
2819
                        aux = getNthGroupOfThree(all_elem, i);
2820
                    }
2821
                }
2822

    
2823
                i++;
2824
            }
2825
        }
2826
        catch (SQLException se) {
2827
            logger.error("Unexpected error: " + se.getMessage());
2828
        }
2829

    
2830
        if (add_last_time) {
2831
                resp.add(aux);
2832
        }
2833

    
2834
        return resp.toArray();
2835
    }
2836
    
2837
    
2838
    
2839
    
2840
    
2841
    public static STRUCT rectangleToStruct(Rectangle2D r, boolean hasSrid,
2842
            boolean isView, boolean _isGeogCS, String _oracleSRID, IConnection __conn) {
2843
            Point2D c1 = new Point2D.Double(r.getMinX(), r.getMinY());
2844
            Point2D c2 = new Point2D.Double(r.getMaxX(), r.getMaxY());
2845

    
2846
            if ((_isGeogCS) && (isView)) {
2847
                c1.setLocation(Math.max(c1.getX(), -180), Math.max(c1.getY(), -90));
2848
                c2.setLocation(Math.min(c2.getX(), 180), Math.min(c2.getY(), 90));
2849
            }
2850

    
2851
            STRUCT resp = null;
2852

    
2853
            try {
2854
                // System.out.println("ABIERTA: " + (!conn.isClosed()));
2855
                // resp = structCreator.toSTRUCT(rect_wkt.getBytes(), conn);
2856
                // Object[] old_obj = resp.getAttributes();
2857
                int size = 5;
2858
                Object[] new_obj = new Object[size];
2859

    
2860
                // for (int i=0; i<size; i++) new_obj[i] = old_obj[i];
2861
                new_obj[0] = new NUMBER(2003);
2862

    
2863
                if (hasSrid) {
2864
                    new_obj[1] = new NUMBER(_oracleSRID);
2865
                }
2866
                else {
2867
                    new_obj[1] = null;
2868
                }
2869

    
2870
                new_obj[2] = null;
2871

    
2872
                NUMBER[] elem_info = new NUMBER[3];
2873
                elem_info[0] = new NUMBER(1);
2874
                elem_info[1] = new NUMBER(1003);
2875
                elem_info[2] = new NUMBER(3);
2876
                new_obj[3] = elem_info;
2877

    
2878
                NUMBER[] ords = null;
2879
                ords = new NUMBER[4];
2880
                ords[0] = new NUMBER(c1.getX());
2881
                ords[1] = new NUMBER(c1.getY());
2882
                ords[2] = new NUMBER(c2.getX());
2883
                ords[3] = new NUMBER(c2.getY());
2884
                new_obj[4] = ords;
2885

    
2886
                // StructDescriptor dsc = StructDescriptor.createDescriptor("STRUCT", conn);
2887
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY",
2888
                                ((ConnectionJDBC)__conn).getConnection());
2889

    
2890
                resp = new STRUCT(dsc,((ConnectionJDBC)__conn).getConnection(), new_obj);
2891
            }
2892
            catch (Exception ex) {
2893
                logger.error("Error while creating rect struct: " +
2894
                    ex.getMessage(), ex);
2895
            }
2896

    
2897
            return resp;
2898
        }
2899
    
2900
    
2901
    public static Rectangle2D doIntersect(Rectangle2D r1, Rectangle2D r2) {
2902
        if (r1.getMaxX() <= r2.getMinX()) {
2903
            return null;
2904
        }
2905

    
2906
        if (r2.getMaxX() <= r1.getMinX()) {
2907
            return null;
2908
        }
2909

    
2910
        if (r1.getMaxY() <= r2.getMinY()) {
2911
            return null;
2912
        }
2913

    
2914
        if (r2.getMaxY() <= r1.getMinY()) {
2915
            return null;
2916
        }
2917

    
2918
        double minx = Math.max(r1.getMinX(), r2.getMinX());
2919
        double miny = Math.max(r1.getMinY(), r2.getMinY());
2920
        double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
2921
        double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
2922

    
2923
        double w = maxx - minx;
2924
        double h = maxy - miny;
2925

    
2926
        return new Rectangle2D.Double(minx, miny, w, h);
2927
    }
2928
    
2929
    
2930
    /**
2931
     * Utility method to find out if a coordinate system is geodetic or not.
2932
     *
2933
     * @param oracleSRID2 the coordinate system's oracle code
2934
     * @param thas whether the table has a coordinate system set.
2935
     * if not, the method returns false.
2936
     * @return whether the coordinate system is geodetic or not.
2937
     */
2938
    public static boolean getIsGCS(String oracleSRID2, boolean thas) {
2939

    
2940
        if (!thas) return false;
2941
        if (oracleSRID2 == null) return false;
2942
        
2943
        int ora_cs = 0;
2944

    
2945
        try {
2946
            ora_cs = Integer.parseInt(oracleSRID2);
2947
        }
2948
        catch (Exception ex) {
2949
            return false;
2950
        }
2951

    
2952
        if (((ora_cs >= 8000) && (ora_cs <= 8999)) || (ora_cs == 524288)) {
2953
            return true;
2954
        } else {
2955
                return false;
2956
        }
2957
    }
2958
    
2959
    
2960
    public static int getShapeTypeOfStruct(STRUCT sample) throws SQLException {
2961

    
2962
        int code = ((NUMBER) sample.getOracleAttributes()[0]).intValue();
2963
        
2964
        int type_part = code % 10;
2965
        int dim_part = code / 1000;
2966

    
2967
        int z_added = 0;
2968
        if (dim_part == 3) {
2969
                z_added = FShape.Z;
2970
        } else {
2971
            if (dim_part == 4) {
2972
                    z_added = FShape.Z | FShape.M;
2973
            }
2974
        }
2975

    
2976
        switch (type_part) {
2977
        case 1:
2978
            return z_added + FShape.POINT;
2979

    
2980
        case 2:
2981
            return z_added + FShape.LINE;
2982

    
2983
        case 3:
2984
            return z_added + FShape.POLYGON;
2985

    
2986
        case 4:
2987
            return z_added + FShape.MULTI;
2988

    
2989
        case 5:
2990
            return z_added + FShape.MULTIPOINT;
2991

    
2992
        case 6:
2993
            return z_added + FShape.LINE;
2994

    
2995
        case 7:
2996
            return z_added + FShape.POLYGON;
2997
        }
2998

    
2999
        logger.error("Unknown geometry type: " + code);
3000

    
3001
        return FShape.NULL;
3002
    }
3003
    
3004

    
3005
    
3006
    
3007
    public static int[] updateIndexes(int[] info) {
3008
        int size = info.length / 3;
3009
        int[] resp = new int[3 * size];
3010
        int rest = info[0] - 1;
3011

    
3012
        for (int i = 0; i < size; i++) {
3013
            resp[3 * i] = info[3 * i] - rest;
3014
            resp[(3 * i) + 1] = info[(3 * i) + 1];
3015
            resp[(3 * i) + 2] = info[(3 * i) + 2];
3016
        }
3017

    
3018
        return resp;
3019
    }
3020
    
3021
    
3022

    
3023
    public static int[] appendIntArrays(int[] head, int[] tail) {
3024
        int[] resp = new int[head.length + tail.length];
3025
        int hsize = head.length;
3026

    
3027
        for (int i = 0; i < hsize; i++) {
3028
            resp[i] = head[i];
3029
        }
3030

    
3031
        for (int i = 0; i < tail.length; i++) {
3032
            resp[hsize + i] = tail[i];
3033
        }
3034

    
3035
        return resp;
3036
    }
3037
    
3038
    
3039
    public static Datum[] appendDatArrays(Datum[] head, Datum[] tail) {
3040
        Datum[] resp = new Datum[head.length + tail.length];
3041
        int hsize = head.length;
3042

    
3043
        for (int i = 0; i < hsize; i++) {
3044
            resp[i] = head[i];
3045
        }
3046

    
3047
        for (int i = 0; i < tail.length; i++) {
3048
            resp[hsize + i] = tail[i];
3049
        }
3050

    
3051
        return resp;
3052
    }
3053

    
3054
    public static int[] getNthGroupOfThree(int[] list, int n) {
3055
        int[] resp = new int[3];
3056
        resp[0] = list[3 * n];
3057
        resp[1] = list[(3 * n) + 1];
3058
        resp[2] = list[(3 * n) + 2];
3059

    
3060
        return resp;
3061
    }
3062

    
3063
    public static Datum[] getNthGroupOfThree(Datum[] list, int n) {
3064
        Datum[] resp = new Datum[3];
3065
        resp[0] = list[3 * n];
3066
        resp[1] = list[(3 * n) + 1];
3067
        resp[2] = list[(3 * n) + 2];
3068

    
3069
        return resp;
3070
    }
3071

    
3072
    public static Datum[] getSubSet(Datum[] all, int first_inc, int last_inc) {
3073
        Datum[] resp = new Datum[last_inc - first_inc + 1];
3074

    
3075
        for (int i = first_inc; i <= last_inc; i++) {
3076
            resp[i - first_inc] = all[i];
3077
        }
3078

    
3079
        return resp;
3080
    }
3081
    
3082
    
3083
    public static int maxSizeForFieldType(int _type) {
3084
            switch (_type) {
3085
                case Types.VARCHAR:
3086
                        return OracleValues.VARCHAR2_STANDARD_SIZE;
3087

    
3088
                case Types.LONGVARCHAR:
3089
                        return OracleValues.VARCHAR2_LONG_SIZE;
3090
                }
3091

    
3092
                return -1;
3093
    }
3094
    
3095
        /**
3096
         * 
3097
         * @param tname
3098
         * @param suffix
3099
         * @return
3100
         */
3101
        public static String getDerivedName(String tname, String suffix) {
3102

    
3103
                int ind = tname.lastIndexOf(".");
3104
                if (ind == -1) {
3105

    
3106
                        int l = Math.min(28, tname.length());
3107
                        return tname.substring(0, l) + "_" + suffix;
3108

    
3109
                } else {
3110

    
3111
                        String pre = tname.substring(0, ind);
3112
                        String post = tname.substring(ind + 1, tname.length());
3113
                        int lpost = Math.min(24, post.length());
3114
                        int lpre = Math.min(3, pre.length());
3115
                        return pre.substring(0, lpre) + "_" + post.substring(0, lpost)
3116
                                        + "_" + suffix;
3117
                }
3118

    
3119
        }
3120

    
3121

    
3122

    
3123

    
3124
}