Statistics
| Revision:

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

History | View | Annotate | Download (87.5 KB)

1
/* gvSIG. Geographic Information System of the Valencian Government
2
 *
3
 * Copyright (C) 2007-2008 Infrastructures and Transports Department
4
 * of the Valencian Government (CIT)
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 */
22

    
23
/*
24
 * AUTHORS (In addition to CIT):
25
 * 2009 Prodevelop S.L. main development
26
 */
27
package org.gvsig.fmap.dal.store.oracle;
28

    
29
import java.awt.Shape;
30
import java.awt.geom.PathIterator;
31
import java.awt.geom.Point2D;
32
import java.awt.geom.Rectangle2D;
33
import java.io.BufferedReader;
34
import java.io.File;
35
import java.io.FileReader;
36
import java.lang.reflect.Array;
37
import java.net.URL;
38
import java.sql.Connection;
39
import java.sql.PreparedStatement;
40
import java.sql.ResultSet;
41
import java.sql.SQLException;
42
import java.sql.Types;
43
import java.text.DecimalFormat;
44
import java.text.DecimalFormatSymbols;
45
import java.util.ArrayList;
46
import java.util.HashMap;
47
import java.util.Iterator;
48
import java.util.List;
49
import java.util.Random;
50

    
51
import oracle.sql.ARRAY;
52
import oracle.sql.Datum;
53
import oracle.sql.NUMBER;
54
import oracle.sql.STRUCT;
55
import oracle.sql.StructDescriptor;
56

    
57
import org.gvsig.fmap.geom.Geometry;
58
import org.gvsig.fmap.geom.GeometryLocator;
59
import org.gvsig.fmap.geom.GeometryManager;
60
import org.gvsig.fmap.geom.aggregate.Aggregate;
61
import org.gvsig.fmap.geom.aggregate.MultiSurface;
62
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2D;
63
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2DZ;
64
import org.gvsig.fmap.geom.aggregate.impl.MultiSurface2D;
65
import org.gvsig.fmap.geom.exception.CreateGeometryException;
66
import org.gvsig.fmap.geom.primitive.GeneralPathX;
67
import org.gvsig.fmap.geom.primitive.Point;
68
import org.gvsig.fmap.geom.primitive.impl.Circle2D;
69
import org.gvsig.fmap.geom.primitive.impl.Curve2D;
70
import org.gvsig.fmap.geom.primitive.impl.Curve2DZ;
71
import org.gvsig.fmap.geom.primitive.impl.Point2DZ;
72
import org.gvsig.fmap.geom.primitive.impl.Surface2D;
73
import org.gvsig.fmap.geom.primitive.impl.Surface2DZ;
74
import org.gvsig.oracle.utils.LineString3D;
75
import org.slf4j.Logger;
76
import org.slf4j.LoggerFactory;
77

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

    
87

    
88

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

    
115
        public static final int ORACLE_GTYPE_COMPLEX_VOIDED_POLYON = 3;
116
        public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_LINE = 4;
117
        public static final int ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON = 5;
118

    
119
        /**
120
         * COnstructs a geometry from a file that contains a vertex per line:
121
         * 
122
         * x1 y1 z1 x2 y2 z2 ...
123
         * 
124
         * @param filepath
125
         *            vertices text file path
126
         * @param polygon
127
         *            whether it is a polygon or not
128
         * @return the created geometry
129
         */
130
        public static Geometry readGeometry3D(URL filepath, boolean polygon) {
131

    
132
                GeometryManager gManager = GeometryLocator.getGeometryManager();
133

    
134
                GeneralPathX resp = new GeneralPathX();
135
                File file = new File(filepath.getFile());
136
                List<Double> z = new ArrayList<Double>();
137

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

    
143
                        boolean move = true;
144

    
145
                        String line = br.readLine();
146

    
147
                        while (line != null) {
148
                                coords = parseLine(line);
149

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

    
161
                                        move = false;
162
                                }
163

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

    
169
                        return null;
170
                }
171

    
172
                double[] zz = new double[z.size()];
173

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

    
178
                if (polygon) {
179
                        try {
180
                                return gManager.createSurface(resp, Geometry.SUBTYPES.GEOM3D);
181
                        } catch (CreateGeometryException e) {
182
                                e.printStackTrace();
183
                                return null;
184
                        }
185
                } else {
186
                        try {
187
                                return gManager
188
                                                .createMultiCurve(resp, Geometry.SUBTYPES.GEOM3D);
189
                        } catch (CreateGeometryException e) {
190
                                e.printStackTrace();
191
                                return null;
192
                        }
193
                }
194
        }
195

    
196
        private static double[] parseLine(String line) {
197
                String[] sep = line.split(" ");
198
                double[] resp = new double[3];
199

    
200
                for (int i = 0; i < 3; i++)
201
                        resp[i] = 0.0;
202

    
203
                try {
204
                        resp[0] = Double.parseDouble(sep[0]);
205
                } catch (Exception ex) {
206
                }
207

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

    
214
                        if (sep.length > 2) {
215
                                try {
216
                                        resp[2] = Double.parseDouble(sep[2]);
217
                                } catch (Exception ex) {
218
                                }
219
                        }
220
                }
221

    
222
                return resp;
223
        }
224

    
225
        /**
226
         * Utility method to convert a gvSIG FShape into a oracle struct
227
         * 
228
         * @param fshp
229
         *            the FShape object
230
         * @param c
231
         *            the connection
232
         * @param srid
233
         *            the SRS (oracle code)
234
         * @param agu_b
235
         *            whether to check holes validity
236
         * @param hasSrid
237
         *            whether the SRS is non-NULL
238
         * @return a oracle struct representing the geometry
239
         * 
240
         * @throws SQLException
241
         */
242
        public static STRUCT fShapeToSTRUCT(Object fshp, Connection c, int srid,
243
                        boolean agu_b, boolean hasSrid) throws SQLException {
244
                boolean three = false;
245

    
246
                GeometryManager gManager = GeometryLocator.getGeometryManager();
247

    
248
                if (fshp instanceof Surface2DZ) {
249
                        three = true;
250
                }
251

    
252
                STRUCT resp = null;
253

    
254
                if (fshp instanceof MultiPoint2D) {
255
                        resp = multiPoint2DToStruct((MultiPoint2D) fshp, c, srid, hasSrid);
256

    
257
                        return resp;
258
                }
259

    
260
                if (!(fshp instanceof Shape)) {
261
                        logger.error("Unknown geometry: " + fshp.toString());
262

    
263
                        return null;
264
                }
265

    
266
                if (fshp instanceof Point2D) { // point 2/3d
267

    
268
                        Coordinate p = getSingleCoordinate((Point2D) fshp);
269
                        resp = getMultiPointAsStruct(p, srid, three, c, hasSrid);
270
                } else {
271
                        if (fshp instanceof Surface2D) { // polygon 2/3d
272

    
273
                                if (fshp instanceof Circle2D) {
274
                                        resp = getCircleAsStruct((Circle2D) fshp, srid, c, hasSrid);
275
                                } else {
276
                                        // also FEllipse2D
277
                                        resp = getMultiPolygonAsStruct((MultiSurface) fshp, srid,
278
                                                        three, c, agu_b, hasSrid);
279

    
280
                                
281
                                }
282
                        } else { // line 2/3d
283

    
284
                                List<LineString3D> _lines = getLineStrings((Shape) fshp);
285
                                resp = getMultiLineAsStruct(_lines, srid, three, c, hasSrid);
286
                        }
287
                }
288

    
289
                return resp;
290
        }
291

    
292
        private static STRUCT multiPoint2DToStruct(MultiPoint2D mp2d, Connection c,
293
                        int srid, boolean hasSrid) throws SQLException {
294
                int np = mp2d.getPrimitivesNumber();
295
                boolean threed = (mp2d instanceof MultiPoint2DZ);
296
                int gtype = 2005;
297
                int dim = 2;
298
                MultiPoint2DZ mp3d = null;
299

    
300
                if (threed) {
301
                        gtype = 3005;
302
                        dim = 3;
303
                        mp3d = (MultiPoint2DZ) mp2d;
304
                }
305

    
306
                NUMBER[] indices = new NUMBER[3];
307
                indices[0] = new NUMBER(1);
308
                indices[1] = new NUMBER(1);
309
                indices[2] = new NUMBER(np);
310

    
311
                NUMBER[] ords = new NUMBER[dim * np];
312

    
313
                for (int i = 0; i < np; i++) {
314
                        ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
315
                        ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY());
316

    
317
                        if (threed) {
318
                                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
319
                        }
320
                }
321

    
322
                STRUCT resp;
323
                StructDescriptor dsc = StructDescriptor.createDescriptor(
324
                                "MDSYS.SDO_GEOMETRY", c);
325
                Object[] obj = new Object[5];
326
                obj[0] = new NUMBER(gtype);
327

    
328
                if (hasSrid) {
329
                        obj[1] = new NUMBER(srid);
330
                } else { // , boolean hasSrid
331
                        obj[1] = null;
332
                }
333

    
334
                obj[2] = null;
335
                obj[3] = indices;
336
                obj[4] = ords;
337
                resp = new STRUCT(dsc, c, obj);
338

    
339
                return resp;
340
        }
341

    
342
        private static STRUCT getCircleAsStruct(Circle2D fcirc, int srid,
343
                        Connection _conn, boolean hasSrid) throws SQLException {
344
                int geotype = 2003;
345
                NUMBER[] indices = new NUMBER[3];
346
                indices[0] = new NUMBER(1);
347
                indices[1] = new NUMBER(1003);
348
                indices[2] = new NUMBER(4);
349

    
350
                NUMBER[] ords = new NUMBER[6];
351
                Coordinate[] three_points = getThreePointsOfCircumference(
352
                                (Point2D) fcirc.getCenter(), fcirc.getRadious());
353

    
354
                for (int i = 0; i < three_points.length; i++) {
355
                        ords[i * 2] = new NUMBER(three_points[i].x);
356
                        ords[(i * 2) + 1] = new NUMBER(three_points[i].y);
357
                }
358

    
359
                STRUCT resp;
360
                StructDescriptor dsc = StructDescriptor.createDescriptor(
361
                                "MDSYS.SDO_GEOMETRY", _conn);
362
                Object[] obj = new Object[5];
363
                obj[0] = new NUMBER(geotype);
364

    
365
                if (hasSrid) {
366
                        obj[1] = new NUMBER(srid);
367
                } else {
368
                        obj[1] = null;
369
                }
370

    
371
                obj[2] = null;
372
                obj[3] = indices;
373
                obj[4] = ords;
374
                resp = new STRUCT(dsc, _conn, obj);
375

    
376
                return resp;
377
        }
378

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

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

    
393
                return resp;
394
        }
395

    
396
        private static Coordinate getSingleCoordinate(Point2D p2d) {
397
                // TODO Auto-generated method stub
398
                Coordinate resp = new Coordinate();
399
                resp.x = p2d.getX();
400
                resp.y = p2d.getY();
401
                return resp;
402
        }
403

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

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

    
415
                                return resp;
416
                        }
417
                }
418

    
419
                return cc;
420
        }
421

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

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

    
431
                return true;
432
        }
433

    
434
        private static List<Coordinate> getClosedRelevantPolygon(List<Coordinate> cc) {
435
                if (cc.size() == 2) {
436
                        return getMinClosedCoords((Coordinate) cc.get(0));
437
                }
438

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

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

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

    
452
                        cc.add(cc.get(0));
453

    
454
                        return cc;
455
                }
456

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

    
462
                return cc;
463
        }
464

    
465
        private static List<Coordinate> getMinClosedCoords(Coordinate c) {
466
                List<Coordinate> resp = new ArrayList<Coordinate>();
467
                resp.add(c);
468

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

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

    
477
                resp.add(new Coordinate(c));
478

    
479
                return resp;
480
        }
481

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

    
486
                Coordinate nc = new Coordinate(c);
487
                nc.x = nc.x + IRRELEVANT_DISTANCE;
488

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

    
495
                CoordinateArraySequence cs = new CoordinateArraySequence(p);
496
                LinearRing ls = new LinearRing(cs, geomFactory);
497

    
498
                return ls;
499
        }
500

    
501
        private static double[] getMinLinearRingZ() {
502
                double[] resp = new double[4];
503

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

    
507
                return resp;
508
        }
509

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

    
516
                numpoints = Array.getLength(pointList);
517

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

    
521
                        if ((testPoint.x == p.x)
522
                                        && (testPoint.y == p.y)
523
                                        && ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z)))                         
524
                        ) {
525
                                return true;
526
                        }
527
                }
528

    
529
                return false;
530
        }
531

    
532
        private static List<LineString3D> getPolygonsEasily(Geometry mpolygon) {
533
                boolean threed = false;
534

    
535
                if (mpolygon instanceof Surface2DZ) {
536
                        threed = true;
537
                }
538

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

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

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

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

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

    
566
                                if (arrayCoords == null) {
567
                                        arrayCoords = new ArrayList<Coordinate>();
568
                                } else {
569
                                        end_ind = ind - 1;
570

    
571
                                        arrayCoords = getClosedRelevantPolygon(arrayCoords);
572
                                        new_size = arrayCoords.size();
573

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

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

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

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

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

    
599
                                                        return null;
600
                                                }
601
                                        }
602

    
603
                                        arrayCoords = new ArrayList<Coordinate>();
604

    
605
                                        start_ind = ind;
606
                                }
607

    
608
                                numParts++;
609

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

    
613
                                break;
614

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

    
619
                                break;
620

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

    
628
                                break;
629

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

    
639
                                break;
640

    
641
                        case PathIterator.SEG_CLOSE:
642

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

    
648
                        theIterator.next();
649
                } // end while loop
650

    
651
                end_ind = ind - 1;
652

    
653
                // null shape:
654
                if (arrayCoords == null) {
655
                        arrayCoords = new ArrayList<Coordinate>();
656

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

    
662
                // --------------------------------------------
663
                arrayCoords = getClosedRelevantPolygon(arrayCoords);
664
                new_size = arrayCoords.size();
665

    
666
                if (arrayCoords != null) {
667
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
668

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

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

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

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

    
688
                                return null;
689
                        }
690
                }
691

    
692
                if (resp.size() == 0) {
693
                        resp.add(new LineString3D(getMinLinearRing(onlyCoord),
694
                                        getMinLinearRingZ()));
695
                }
696

    
697
                return resp;
698
        }
699

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

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

    
716
                return resp;
717
        }
718

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

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

    
735
                return resp;
736
        }
737

    
738
        private static double[] getZ(Geometry geom3d, int _str, int _end, int size) {
739
                double[] resp = new double[size];
740
                
741
                if(geom3d instanceof )
742
                double[] allz = p3d.getZs();
743

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

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

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

    
756
                return resp;
757
        }
758

    
759
        private static List<LineString3D> getLineStrings(Shape mlines) {
760
                boolean threed = false;
761

    
762
                if (mlines instanceof Curve2DZ) {
763
                        threed = true;
764
                }
765

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

    
771
                LineString3D lin;
772

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

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

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

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

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

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

    
804
                                        lin = new LineString3D(aux, z);
805
                                        arrayLines.add(lin);
806
                                        arrayCoords = new ArrayList<Coordinate>();
807

    
808
                                        start_ind = ind;
809
                                }
810

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

    
814
                                break;
815

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

    
819
                                break;
820

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

    
824
                                break;
825

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

    
829
                                break;
830

    
831
                        case PathIterator.SEG_CLOSE:
832

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

    
836
                                break;
837
                        } // end switch
838

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

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

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

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

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

    
857
                return arrayLines;
858
        }
859

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

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

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

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

    
882
                return resp;
883
        }
884

    
885
        private static String multiLineStringToWKT(List<LineString3D> ml, boolean threed) {
886
                String resp = "MULTILINESTRING(";
887

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

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

    
895
                return resp;
896
        }
897

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

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

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

    
909
                return resp;
910
        }
911

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

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

    
924
                resp = resp + ")";
925

    
926
                return resp;
927
        }
928

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

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

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

    
943
                return resp;
944
        }
945

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

    
949
                if ((threed) && (point instanceof Point2DZ)) {
950
                        resp = resp + " " + ((Point2DZ) point).getCoordinateAt(3);
951
                }
952

    
953
                resp = resp + ")";
954

    
955
                return resp;
956
        }
957

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

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

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

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

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

    
979
                return resp;
980
        }
981

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

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

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

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

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

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

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

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

    
1020
                        return true;
1021
                }
1022
        }
1023

    
1024
        private static STRUCT getMultiPolygonAsStruct(List<LineString3D> pols, int srid,
1025
                        boolean threed, Connection _conn, boolean agu_bien, boolean hasSrid)
1026
                        throws SQLException {
1027
                int size = pols.size();
1028
                int geotype = 2007;
1029
                int dim = 2;
1030
                int acum = 0;
1031

    
1032
                if (threed) {
1033
                        geotype = 3007;
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(1003);
1042
                        indices[(3 * i) + 2] = new NUMBER(1);
1043
                        acum = acum
1044
                                        + (dim * ((LineString3D) pols.get(i)).getLs()
1045
                                                        .getNumPoints());
1046
                }
1047

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

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

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

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

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

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

    
1073
                if (hasSrid) {
1074
                        obj[1] = new NUMBER(srid);
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, _conn, obj);
1083

    
1084
                return resp;
1085
        }
1086

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

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

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

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

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

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

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

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

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

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

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

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

    
1152
                return resp;
1153
        }
1154

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

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

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

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

    
1175
                STRUCT resp;
1176

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

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

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

    
1189
                obj[2] = ords_st;
1190
                obj[3] = null;
1191
                obj[4] = null;
1192
                resp = new STRUCT(dsc, _conn, obj);
1193

    
1194
                return resp;
1195
        }
1196

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

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

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

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

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

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

    
1232
                m11 = determinant(a, 3);
1233

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

    
1241
                m12 = determinant(a, 3);
1242

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

    
1251
                m13 = determinant(a, 3);
1252

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

    
1260
                m14 = determinant(a, 3);
1261

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

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

    
1278
                return resp;
1279
        }
1280

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

    
1294
                if (n == 2) { // terminate recursion
1295
                        resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1296
                } else {
1297
                        resp = 0;
1298

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

    
1301
                                for (int i = 1; i < n; i++) { // create minor
1302

    
1303
                                        int j2 = 0;
1304

    
1305
                                        for (int j = 0; j < n; j++) {
1306
                                                if (j == j1) {
1307
                                                        continue;
1308
                                                }
1309

    
1310
                                                m[i - 1][j2] = a[i][j];
1311
                                                j2++;
1312
                                        }
1313
                                }
1314

    
1315
                                // sum (+/-)cofactor * minor
1316
                                resp = resp
1317
                                                + (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1318
                        }
1319
                }
1320

    
1321
                return resp;
1322
        }
1323

    
1324
        private static int getSmallestContainerExcept(LineString3D ls,
1325
                        List<LineString3D> list, int self) {
1326
                int resp = -1;
1327
                List<Integer> provList = new ArrayList<Integer>();
1328

    
1329
                int size = list.size();
1330

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

    
1337
                for (int i = (self + 1); i < size; i++) {
1338
                        if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1339
                                provList.add(new Integer(i));
1340
                        }
1341
                }
1342

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

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

    
1367
                return resp;
1368
        }
1369

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

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

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

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

    
1386
                return _resp;
1387
        }
1388

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

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

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

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

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

    
1407
                return _resp;
1408
        }
1409

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

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

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

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

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

    
1430
                return _resp;
1431
        }
1432

    
1433
        private static List getHolesOf(int ind, int[] final_contn,
1434
                        List all) {
1435
                List<Integer> resp_ind = new ArrayList<Integer>();
1436

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

    
1443
                List resp = new ArrayList();
1444

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

    
1450
                return resp;
1451
        }
1452

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

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

    
1462
                List resp = new ArrayList();
1463

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

    
1469
                return resp;
1470
        }
1471

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

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

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

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

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

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

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

    
1517
                return _resp;
1518
        }
1519

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

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

    
1527
                return resp;
1528
        }
1529

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

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

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

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

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

    
1557
                        resp.add(newitem);
1558
                }
1559

    
1560
                return resp;
1561
        }
1562

    
1563
        private static STRUCT getMultiPolygonAsStruct(List<LineString3D> shells,
1564
                        List<List<LineString3D>> holes, int srid, boolean threed, Connection _conn,
1565
                        boolean explicito, boolean hasSrid) throws SQLException {
1566
                int t = 1003;
1567

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

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

    
1577
                int dim = 2;
1578

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

    
1584
                NUMBER[] indices = new NUMBER[3 * size];
1585

    
1586
                int acum = 0;
1587
                int start_ind = 0;
1588

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

    
1598
                        List<LineString3D> item_holes = (List<LineString3D>) holes.get(i);
1599

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

    
1611
                int _ind = 0;
1612
                NUMBER[] ords = new NUMBER[acum];
1613

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

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

    
1623
                                if (threed) {
1624
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1625
                                }
1626

    
1627
                                _ind = _ind + dim;
1628
                        }
1629

    
1630
                        // -------------------------------
1631
                        List<LineString3D> item_holes = (List<LineString3D>) holes.get(i);
1632

    
1633
                        for (int j = 0; j < item_holes.size(); j++) {
1634
                                ls = (LineString3D) item_holes.get(j);
1635
                                num_p = ls.getLs().getNumPoints();
1636

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

    
1641
                                        if (threed) {
1642
                                                ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1643
                                        }
1644

    
1645
                                        _ind = _ind + dim;
1646
                                }
1647
                        }
1648
                }
1649

    
1650
                STRUCT resp;
1651
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1652
                                "MDSYS.SDO_GEOMETRY", _conn);
1653
                Object[] obj = new Object[5];
1654
                obj[0] = new NUMBER(geotype);
1655

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

    
1662
                obj[2] = null;
1663
                obj[3] = indices;
1664
                obj[4] = ords;
1665

    
1666
                // String ind_str = printArray(indices);
1667
                // String ord_str = printArray(ords);
1668
                resp = new STRUCT(dsc, _conn, obj);
1669

    
1670
                return resp;
1671
        }
1672

    
1673
        /**
1674
         * 
1675
         * @param array
1676
         * @return
1677
         */
1678
        public static String printArray(NUMBER[] array) {
1679
                String resp = "[ ";
1680

    
1681
                for (int i = 0; i < array.length; i++) {
1682
                        resp = resp + " " + array[i].doubleValue() + " , ";
1683
                }
1684

    
1685
                resp = resp.substring(0, resp.length() - 2) + "]";
1686

    
1687
                return resp;
1688
        }
1689

    
1690
        /**
1691
         * 
1692
         * @param ind
1693
         * @param list
1694
         * @return
1695
         */
1696
        private static boolean isOneOf(int ind, int[] list) {
1697
                for (int i = 0; i < list.length; i++) {
1698
                        if (list[i] == ind) {
1699
                                return true;
1700
                        }
1701
                }
1702

    
1703
                return false;
1704
        }
1705

    
1706
        /**
1707
         * This method appends the geometries from a geometry collection in one
1708
         * STRUCT.
1709
         * 
1710
         * @param co
1711
         *            the geometry collection
1712
         * @param _forced_type
1713
         *            a type that has to be used as the struct's main type
1714
         * @param _conn
1715
         *            the connection
1716
         * @param _o_srid
1717
         *            the geometry's SRS (oracle code)
1718
         * @param withSrid
1719
         *            whether the SRS is non-NULL
1720
         * @param agu_bien
1721
         *            whether to check holes' validity
1722
         * @param _isGeoCS
1723
         *            whether the SRS is geodetic
1724
         * @return the STRUCT with the appended geometries
1725
         */
1726
        public static STRUCT appendGeometriesInStruct(Aggregate co,
1727
                        int _forced_type, Connection _conn, String _o_srid,
1728
                        boolean withSrid, boolean agu_bien, boolean _isGeoCS) {
1729
                
1730
                Geometry[] geoms = new Geometry[co.getPrimitivesNumber()];
1731
                for (int i = 0; i < co.getPrimitivesNumber(); i++) {
1732
                        geoms[i]= co.getPrimitiveAt(i);
1733
                }
1734
                
1735
                
1736
                
1737
                STRUCT[] sts = new STRUCT[co.getPrimitivesNumber()];
1738

    
1739
                for (int i = 0; i < co.getPrimitivesNumber(); i++) {
1740
                        sts[i] = geometryToSTRUCT(geoms[i],
1741
                                        _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS);
1742
                }
1743

    
1744
                if (co.getPrimitivesNumber() == 1) {
1745
                        return sts[0];
1746
                }
1747

    
1748
                STRUCT aux = sts[0];
1749

    
1750
                for (int i = 1; i < co.getPrimitivesNumber(); i++) {
1751
                        aux = appendStructs(aux, sts[i], _conn);
1752
                }
1753

    
1754
                return aux;
1755
        }
1756

    
1757
        /**
1758
         * 
1759
         * @param st1
1760
         * @param st2
1761
         * @param _conn
1762
         * @return
1763
         */
1764
        private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection _conn) {
1765
                try {
1766
                        ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1767
                        int length_of_head_ords = _ords.getOracleArray().length;
1768

    
1769
                        NUMBER gtype = new NUMBER(
1770
                                        4 + (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1771
                        NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1772
                        NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1773

    
1774
                        ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1775
                        ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1776
                        ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1777
                        ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1778

    
1779
                        Datum[] info = appendDatumArrays(info1.getOracleArray(), info2
1780
                                        .getOracleArray(), length_of_head_ords);
1781

    
1782
                        Datum[] ords = appendDatumArrays(ords1.getOracleArray(), ords2
1783
                                        .getOracleArray(), 0);
1784

    
1785
                        StructDescriptor dsc = st1.getDescriptor();
1786

    
1787
                        Object[] atts = new Object[5];
1788
                        atts[0] = gtype;
1789
                        atts[1] = srid;
1790
                        atts[2] = middle;
1791
                        atts[3] = info;
1792
                        atts[4] = ords;
1793

    
1794
                        STRUCT resp = new STRUCT(dsc, _conn, atts);
1795

    
1796
                        return resp;
1797
                } catch (SQLException sqle) {
1798
                        logger.error("While appending structs: " + sqle.getMessage(), sqle);
1799
                }
1800

    
1801
                return null;
1802
        }
1803

    
1804
        /**
1805
         * 
1806
         * @param head
1807
         * @param tail
1808
         * @param offset
1809
         * @return
1810
         */
1811
        private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
1812
                        int offset) {
1813
                int head_l = head.length;
1814
                int tail_l = tail.length;
1815
                Datum[] resp = new Datum[head_l + tail_l];
1816

    
1817
                for (int i = 0; i < head_l; i++)
1818
                        resp[i] = head[i];
1819

    
1820
                if (offset == 0) {
1821
                        for (int i = 0; i < tail_l; i++)
1822
                                resp[head_l + i] = tail[i];
1823
                } else {
1824
                        try {
1825
                                for (int i = 0; i < tail_l; i++) {
1826
                                        if ((i % 3) == 0) {
1827
                                                resp[head_l + i] = new NUMBER(tail[i].intValue()
1828
                                                                + offset);
1829
                                        } else {
1830
                                                resp[head_l + i] = tail[i];
1831
                                        }
1832
                                }
1833
                        } catch (SQLException se) {
1834
                                logger.error("Unexpected error: " + se.getMessage());
1835
                        }
1836
                }
1837

    
1838
                return resp;
1839
        }
1840

    
1841
        /**
1842
         * Utility method to get an ineteger as a formatted string.
1843
         * 
1844
         * @param n
1845
         *            the integer
1846
         * @return the formatted string
1847
         */
1848
        public static String getFormattedInteger(int n) {
1849
                df.setGroupingUsed(true);
1850
                df.setGroupingSize(3);
1851
                dfs.setGroupingSeparator('.');
1852
                df.setDecimalFormatSymbols(dfs);
1853

    
1854
                return df.format(n);
1855
        }
1856

    
1857
        /**
1858
         * Tells whether these arrays belong to a rectangle polygon.
1859
         * 
1860
         * @param info
1861
         *            the struct's element info array
1862
         * @param ords
1863
         *            the struct's coordinate array
1864
         * @return true if it is a rectangle polygon. false otherwise.
1865
         */
1866
        public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
1867
                try {
1868
                        int[] infos = info.getIntArray();
1869

    
1870
                        return ((infos[2] == 3) && (infos.length == 3));
1871
                } catch (SQLException se) {
1872
                        logger.error("While ckecking rectangle: " + se.getMessage(), se);
1873
                }
1874

    
1875
                return false;
1876
        }
1877

    
1878
        /**
1879
         * Utility method to deal with oracle info arrays.
1880
         */
1881
        public static ARRAY getDevelopedInfoArray(ARRAY info) {
1882
                ARRAY _resp = null;
1883

    
1884
                try {
1885
                        Datum[] resp = new Datum[3];
1886
                        Datum[] in = info.getOracleArray();
1887
                        resp[0] = in[0];
1888
                        resp[1] = in[1];
1889
                        resp[2] = new NUMBER(1);
1890
                        _resp = new ARRAY(info.getDescriptor(), info
1891
                                        .getInternalConnection(), resp);
1892
                } catch (SQLException se) {
1893
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
1894
                }
1895

    
1896
                return _resp;
1897
        }
1898

    
1899
        /**
1900
         * Utility method to deal with oracle coordinate arrays.
1901
         */
1902
        public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
1903
                ARRAY _resp = null;
1904

    
1905
                try {
1906
                        Datum[] resp = new Datum[10];
1907
                        Datum[] corners = ords.getOracleArray();
1908

    
1909
                        // x
1910
                        resp[0] = corners[0];
1911
                        resp[2] = corners[2];
1912
                        resp[4] = corners[2];
1913
                        resp[6] = corners[0];
1914
                        resp[8] = corners[0];
1915

    
1916
                        // y
1917
                        resp[1] = corners[1];
1918
                        resp[3] = corners[1];
1919
                        resp[5] = corners[3];
1920
                        resp[7] = corners[3];
1921
                        resp[9] = corners[1];
1922
                        _resp = new ARRAY(ords.getDescriptor(), ords
1923
                                        .getInternalConnection(), resp);
1924
                } catch (SQLException se) {
1925
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
1926
                }
1927

    
1928
                return _resp;
1929
        }
1930

    
1931
        /**
1932
         * utility method to convert a STRUCT into a GeneralPathX
1933
         * 
1934
         * @param aux
1935
         *            the struct's datum array
1936
         * @return the GeneralPathX instance created
1937
         */
1938
        public static GeneralPathX structToGPX(Datum[] aux) {
1939
                GeneralPathX resp = new GeneralPathX();
1940
                ARRAY infoARRAY = null;
1941
                ARRAY ordsARRAY = null;
1942
                Datum[] info_array = null;
1943
                Datum[] ords_array = null;
1944
                int info_array_size = 0;
1945
                int[] start_ind;
1946
                int[] end_ind;
1947
                int dims = 0;
1948
                boolean next_must_do_first = true;
1949

    
1950
                try {
1951
                        infoARRAY = (ARRAY) aux[3];
1952
                        ordsARRAY = (ARRAY) aux[4];
1953

    
1954
                        if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
1955
                                infoARRAY = getDevelopedInfoArray(infoARRAY);
1956
                                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
1957
                        }
1958

    
1959
                        dims = ((NUMBER) aux[0]).intValue() / 1000;
1960

    
1961
                        if (dims == 0) {
1962
                                dims = 2;
1963
                        }
1964

    
1965
                        info_array = (Datum[]) infoARRAY.getOracleArray();
1966
                        ords_array = (Datum[]) ordsARRAY.getOracleArray();
1967
                        info_array_size = info_array.length / 3;
1968

    
1969
                        int last_index = ords_array.length - dims + 1;
1970

    
1971
                        // set indices:
1972
                        start_ind = new int[info_array_size];
1973
                        end_ind = new int[info_array_size];
1974

    
1975
                        for (int i = 0; i < info_array_size; i++)
1976
                                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
1977

    
1978
                        for (int i = 0; i < (info_array_size - 1); i++)
1979
                                end_ind[i] = start_ind[i + 1] - 1;
1980

    
1981
                        end_ind[info_array_size - 1] = last_index;
1982

    
1983
                        int lineType = PathIterator.SEG_LINETO;
1984

    
1985
                        if (end_ind[0] == 0) { // collection of paths
1986

    
1987
                                for (int i = 1; i < info_array_size; i++) {
1988
                                        lineType = getLineToType(info_array, i);
1989

    
1990
                                        // -----------------------
1991
                                        if (end_ind[i] == (start_ind[i] - 1))
1992
                                                lineType = PathIterator.SEG_MOVETO;
1993
                                        // -----------------------
1994

    
1995
                                        next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
1996
                                                        end_ind[i] - 1, ords_array, dims, lineType,
1997
                                                        (i == 1) || (lineType == PathIterator.SEG_MOVETO),
1998
                                                        next_must_do_first);
1999
                                }
2000
                        } else {
2001
                                // standard case, do the moveto always
2002
                                for (int i = 0; i < info_array_size; i++) {
2003
                                        lineType = getLineToType(info_array, i);
2004
                                        addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1,
2005
                                                        ords_array, dims, lineType, true, true);
2006
                                }
2007
                        }
2008

    
2009
                        // boolean do_the_moves = true;
2010
                } catch (SQLException se) {
2011
                        logger.error("While creating GPX: " + se.getMessage(), se);
2012
                }
2013

    
2014
                return resp;
2015
        }
2016

    
2017
        /**
2018
         * 
2019
         * @param infos
2020
         * @param i
2021
         * @return
2022
         */
2023
        private static int getLineToType(Datum[] infos, int i) {
2024
                int resp = PathIterator.SEG_LINETO;
2025

    
2026
                try {
2027
                        if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) {
2028
                                resp = PathIterator.SEG_QUADTO;
2029
                        }
2030
                } catch (SQLException e) {
2031
                        logger.error("While getting line-to type: " + e.getMessage()
2032
                                        + " (returned SEG_LINETO)");
2033
                }
2034

    
2035
                return resp;
2036
        }
2037

    
2038
        /**
2039
         * 
2040
         * @param gpx
2041
         * @param zero_based_start
2042
         * @param zero_based_include_end
2043
         * @param ords
2044
         * @param d
2045
         * @param ltype
2046
         * @param do_the_move
2047
         * @param must_do_first
2048
         * @return
2049
         */
2050
        private static boolean addOrdsToGPX(GeneralPathX gpx, int zero_based_start,
2051
                        int zero_based_include_end, Datum[] ords, int d, int ltype,
2052
                        boolean do_the_move, boolean must_do_first) {
2053
                int length = ords.length;
2054
                boolean return_following_must_do_first = true;
2055

    
2056
                double x = ((NUMBER) ords[zero_based_start]).doubleValue();
2057
                double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
2058

    
2059
                if (must_do_first) {
2060
                        if (do_the_move) {
2061
                                gpx.moveTo(x, y);
2062
                        } else {
2063
                                gpx.lineTo(x, y);
2064
                        }
2065
                }
2066

    
2067
                int ind = 1;
2068

    
2069
                int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2070
                int indx;
2071
                int indx2;
2072

    
2073
                if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2074

    
2075
                        double x2;
2076
                        double y2;
2077

    
2078
                        while (ind < size) {
2079
                                indx = zero_based_start + (ind * d);
2080
                                x = ((NUMBER) ords[indx]).doubleValue();
2081
                                y = ((NUMBER) ords[indx + 1]).doubleValue();
2082

    
2083
                                indx2 = zero_based_start + ((ind + 1) * d);
2084

    
2085
                                if (indx >= length) {
2086
                                        indx2 = zero_based_start;
2087
                                }
2088

    
2089
                                x2 = ((NUMBER) ords[indx2]).doubleValue();
2090
                                y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
2091
                                gpx.quadTo(x, y, x2, y2);
2092
                                ind++;
2093
                                ind++;
2094
                        }
2095

    
2096
                        return_following_must_do_first = false;
2097
                } else { // PathIterator.SEG_LINETO (interpretation = 1)
2098

    
2099
                        while (ind < size) {
2100
                                indx = zero_based_start + (ind * d);
2101
                                x = ((NUMBER) ords[indx]).doubleValue();
2102
                                y = ((NUMBER) ords[indx + 1]).doubleValue();
2103
                                gpx.lineTo(x, y);
2104
                                ind++;
2105
                        }
2106
                }
2107

    
2108
                return return_following_must_do_first;
2109
        }
2110

    
2111
        /**
2112
         * Utility method. Gets FShape type from oracle geometry type.
2113
         * 
2114
         * @param otype
2115
         * @return FShape type
2116
         */
2117
        public static int oracleGTypeToFShapeType(int otype) {
2118
                switch (otype) {
2119
                case ORACLE_GTYPE_UNKNOWN:
2120
                        return Geometry.TYPES.NULL;
2121

    
2122
                case ORACLE_GTYPE_POINT:
2123
                case ORACLE_GTYPE_MULTIPOINT:
2124
                        return Geometry.TYPES.POINT;
2125

    
2126
                case ORACLE_GTYPE_LINE:
2127
                case ORACLE_GTYPE_MULTILINE:
2128
                        return Geometry.TYPES.CURVE;
2129

    
2130
                case ORACLE_GTYPE_POLYGON:
2131
                case ORACLE_GTYPE_MULTIPOLYGON:
2132
                        return Geometry.TYPES.SURFACE;
2133

    
2134
                case ORACLE_GTYPE_COLLECTION:
2135
                        return Geometry.TYPES.AGGREGATE;
2136
                }
2137

    
2138
                logger.warn("Unknown oracle geometry type: " + otype);
2139

    
2140
                return Geometry.TYPES.NULL;
2141
        }
2142

    
2143
        /**
2144
         * Utility method to get struct's type.
2145
         * 
2146
         * @param the_data
2147
         *            the struct's datum array
2148
         * @return the struct type
2149
         */
2150
        public static int getStructType(Datum[] the_data) {
2151
                int resp = -1;
2152

    
2153
                try {
2154
                        resp = ((NUMBER) the_data[0]).intValue() % 1000;
2155
                } catch (SQLException se) {
2156
                        logger.error("Error: " + se.getMessage(), se);
2157
                }
2158

    
2159
                return resp;
2160
        }
2161

    
2162
        /**
2163
         * Utility method to get struct's SRID.
2164
         * 
2165
         * @param the_data
2166
         *            the struct's datum array
2167
         * @return the struct0's SRID
2168
         */
2169
        public static int getStructSRID(Datum[] the_data) {
2170
                int resp = -1;
2171

    
2172
                try {
2173
                        resp = ((NUMBER) the_data[1]).intValue();
2174
                } catch (SQLException se) {
2175
                        logger.error("Error: " + se.getMessage(), se);
2176
                }
2177

    
2178
                return resp;
2179
        }
2180

    
2181
        /**
2182
         * Utility method to find out if a struct is a circle.
2183
         * 
2184
         * @param the_data
2185
         *            the struct's datum array
2186
         * @return whether it is a circle
2187
         */
2188
        public static boolean isCircle(Datum[] the_data) {
2189
                int[] info = null;
2190

    
2191
                try {
2192
                        info = ((ARRAY) the_data[3]).getIntArray();
2193
                } catch (SQLException se) {
2194
                        logger.error("While cheking circle: " + se.getMessage(), se);
2195

    
2196
                        return false;
2197
                }
2198

    
2199
                if (info == null) {
2200
                        return false;
2201
                }
2202

    
2203
                boolean resp = ((info.length == 3) && (info[2] == 4));
2204

    
2205
                return resp;
2206
        }
2207

    
2208
        /**
2209
         * Gets the struct's dimension size.
2210
         * 
2211
         * @param st
2212
         *            the struct
2213
         * @return the structs dimension
2214
         */
2215
        public static int getStructDimensions(STRUCT st) {
2216
                int resp = -1;
2217

    
2218
                try {
2219
                        resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2220
                } catch (SQLException se) {
2221
                        logger.error("Error: " + se.getMessage(), se);
2222
                }
2223

    
2224
                if (resp < 2) {
2225
                        resp = 2;
2226
                }
2227

    
2228
                return resp;
2229
        }
2230

    
2231
        /**
2232
         * Gets a struct's coordinates array.
2233
         * 
2234
         * @param the_data
2235
         *            the struct's datum array
2236
         * @return the coordinates array
2237
         */
2238
        public static double[] getOrds(Datum[] the_data) {
2239
                double[] resp = null;
2240

    
2241
                try {
2242
                        ARRAY aux = (ARRAY) the_data[4];
2243

    
2244
                        if (aux == null) {
2245
                                return null;
2246
                        }
2247

    
2248
                        resp = aux.getDoubleArray();
2249
                } catch (SQLException se) {
2250
                        logger.error("While getting ordinates: " + se.getMessage(), se);
2251
                }
2252

    
2253
                return resp;
2254
        }
2255

    
2256
        /**
2257
         * Utility method to create a struct with the given data.
2258
         * 
2259
         * @param type
2260
         *            struct type
2261
         * @param srid
2262
         *            coordinate system
2263
         * @param info
2264
         *            element info array
2265
         * @param ords
2266
         *            coordinates array
2267
         * @param conn
2268
         *            connection
2269
         * @return the created struct
2270
         */
2271
        public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info,
2272
                        Datum[] ords, Connection conn) {
2273
                try {
2274
                        StructDescriptor dsc = StructDescriptor.createDescriptor(
2275
                                        "MDSYS.SDO_GEOMETRY", conn);
2276
                        Object[] obj = new Object[5];
2277
                        obj[0] = type;
2278
                        obj[1] = srid;
2279
                        obj[2] = null;
2280
                        obj[3] = info;
2281
                        obj[4] = ords;
2282

    
2283
                        return new STRUCT(dsc, conn, obj);
2284
                } catch (SQLException se) {
2285
                        logger.error("While creating STRUCT: " + se.getMessage(), se);
2286
                }
2287

    
2288
                return null;
2289
        }
2290

    
2291
        /**
2292
         * 
2293
         * @param dim_info
2294
         * @return
2295
         */
2296
        public static String getDimInfoAsString(ARRAY dim_info) {
2297
                String resp = "DIMENSIONS: ";
2298

    
2299
                if (dim_info == null) {
2300
                        return "NULL" + "\n";
2301
                } else {
2302
                        try {
2303
                                Datum[] da = dim_info.getOracleArray();
2304
                                int size = da.length;
2305
                                resp = resp + size + "\n";
2306
                                for (int i = 0; i < size; i++) {
2307
                                        STRUCT dim_itemx = (STRUCT) da[i];
2308
                                        Object[] dim_desc = dim_itemx.getAttributes();
2309
                                        resp = resp + "DIMENSION " + i + ": " + ", NAME: "
2310
                                                        + dim_desc[0].toString() + ", MIN: "
2311
                                                        + dim_desc[1].toString() + ", MAX: "
2312
                                                        + dim_desc[2].toString() + ", TOL: "
2313
                                                        + dim_desc[3].toString();
2314
                                        if (i != (size - 1)) {
2315
                                                resp = resp + "\n";
2316
                                        }
2317
                                }
2318
                        } catch (Exception ex) {
2319
                                return "ERROR: " + ex.getMessage() + "\n";
2320
                        }
2321
                }
2322
                return resp;
2323
        }
2324

    
2325
        /**
2326
         * 
2327
         * @param conn
2328
         * @param fromStruct
2329
         * @param toSrid
2330
         * @return
2331
         */
2332
        public static STRUCT reprojectGeometry(Connection conn, STRUCT fromStruct,
2333
                        String toSrid) {
2334

    
2335
                String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2336
                STRUCT resp = null;
2337

    
2338
                try {
2339
                        PreparedStatement _st = conn.prepareStatement(qry);
2340
                        _st.setObject(1, fromStruct);
2341
                        ResultSet _rs = _st.executeQuery();
2342

    
2343
                        if (_rs.next()) {
2344
                                resp = (STRUCT) _rs.getObject(1);
2345
                        } else {
2346
                                logger
2347
                                                .error("While executing reprojection: empty resultset (?)");
2348
                                return fromStruct;
2349
                        }
2350
                } catch (Exception ex) {
2351
                        logger.error("While reprojecting: " + ex.getMessage());
2352
                        return fromStruct;
2353
                }
2354

    
2355
                if (resp == null) {
2356
                        return fromStruct;
2357
                } else {
2358
                        return resp;
2359
                }
2360
        }
2361

    
2362
        /**
2363
         * 
2364
         * @param st
2365
         */
2366
        public static void printStruct(STRUCT st) {
2367

    
2368
                logger.debug("----------------------------------------------");
2369
                logger.debug("-- 16 FEBRERO 2009 ---------------------------");
2370
                logger.debug("----------------------------------------------");
2371

    
2372
                try {
2373
                        Object[] att = st.getAttributes();
2374
                        int l = att.length;
2375

    
2376
                        for (int i = 0; i < l; i++) {
2377
                                if (att[i] != null) {
2378
                                        if (att[i] instanceof ARRAY) {
2379
                                                ARRAY arr = (ARRAY) att[i];
2380
                                                logger.debug("ATT " + i + ": ");
2381
                                                printARRAY(arr);
2382
                                        } else {
2383
                                                logger.debug("ATT " + i + ": " + att[i].toString());
2384
                                        }
2385
                                        logger
2386
                                                        .debug("----------------------------------------------");
2387
                                }
2388
                        }
2389
                } catch (Exception ex) {
2390
                        logger.debug("-- Error: " + ex.getMessage());
2391
                }
2392

    
2393
        }
2394

    
2395
        /**
2396
         * 
2397
         * @param arr
2398
         * @throws Exception
2399
         */
2400
        private static void printARRAY(ARRAY arr) throws Exception {
2401

    
2402
                int[] intarr = arr.getIntArray();
2403
                if (intarr == null) {
2404
                        float[] floarr = arr.getFloatArray();
2405
                        if (floarr == null) {
2406
                                logger.debug("INT NULL y FLOAT NULL (?)");
2407
                        } else {
2408
                                int len = floarr.length;
2409
                                for (int i = 0; i < len; i++) {
2410
                                        if (Math.min(i, (len - i)) < 20) {
2411
                                                logger.debug("" + floarr[i]);
2412
                                        }
2413
                                }
2414
                        }
2415

    
2416
                } else {
2417
                        int len = intarr.length;
2418
                        for (int i = 0; i < len; i++) {
2419
                                if (Math.min(i, (len - i)) < 20) {
2420
                                        logger.debug("" + intarr[i]);
2421
                                }
2422
                        }
2423
                }
2424
        }
2425

    
2426
        /**
2427
         * Utility method. Gets FShape type from oracle geometry type.
2428
         * 
2429
         * @param otype
2430
         * @return FShape type
2431
         */
2432
        public static int oracleGTypeToFShapeType(int otype, boolean complex) {
2433

    
2434
                int resp = Geometry.TYPES.NULL;
2435

    
2436
                if (complex) {
2437

    
2438
                        switch (otype) {
2439
                        case ORACLE_GTYPE_COMPLEX_VOIDED_POLYON:
2440
                        case ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON:
2441
                                resp = Geometry.TYPES.SURFACE;
2442
                                break;
2443
                        case ORACLE_GTYPE_COMPLEX_COMPOUND_LINE:
2444
                                resp = Geometry.TYPES.CURVE;
2445
                                break;
2446
                        }
2447

    
2448
                } else {
2449

    
2450
                        // =========== not complex =================
2451
                        switch (otype) {
2452
                        case ORACLE_GTYPE_UNKNOWN:
2453
                                resp = Geometry.TYPES.NULL;
2454
                                break;
2455

    
2456
                        case ORACLE_GTYPE_POINT:
2457
                        case ORACLE_GTYPE_MULTIPOINT:
2458
                                resp = Geometry.TYPES.POINT;
2459
                                break;
2460

    
2461
                        case ORACLE_GTYPE_LINE:
2462
                        case ORACLE_GTYPE_MULTILINE:
2463
                                resp = Geometry.TYPES.CURVE;
2464
                                break;
2465

    
2466
                        case ORACLE_GTYPE_POLYGON:
2467
                        case ORACLE_GTYPE_MULTIPOLYGON:
2468
                                resp = Geometry.TYPES.SURFACE;
2469
                                break;
2470

    
2471
                        case ORACLE_GTYPE_COLLECTION:
2472
                                resp = Geometry.TYPES.AGGREGATE;
2473
                                break;
2474
                        }
2475
                        // =========== not complex =================
2476
                }
2477

    
2478
                if (resp == Geometry.TYPES.NULL) {
2479
                        logger.error("Unknown oracle geometry type: " + otype);
2480
                }
2481
                return resp;
2482
        }
2483

    
2484
        /**
2485
         * 
2486
         * @param name
2487
         * @param arr
2488
         * @return
2489
         */
2490
        private static boolean isOneOfThese(String name, String[] arr) {
2491

    
2492
                for (int i = 0; i < arr.length; i++) {
2493
                        if (arr[i].compareToIgnoreCase(name) == 0)
2494
                                return true;
2495
                }
2496
                return false;
2497
        }
2498

    
2499
        /**
2500
         * 
2501
         * @param tt
2502
         * @param are_dims
2503
         * @return
2504
         */
2505
        public static boolean hasSeveralGeometryTypes(ArrayList tt, boolean are_dims) {
2506
                if (tt.size() == 0) {
2507
                        return false;
2508
                }
2509

    
2510
                HashMap m = new HashMap();
2511

    
2512
                for (int i = 0; i < tt.size(); i++) {
2513
                        Integer integ = (Integer) tt.get(i);
2514
                        int val = integ.intValue();
2515

    
2516
                        if ((val == 4) && (!are_dims)) {
2517
                                return true;
2518
                        }
2519

    
2520
                        m.put("" + (val % 4), "a type");
2521
                }
2522

    
2523
                Iterator iter = m.keySet().iterator();
2524
                iter.next();
2525

    
2526
                return iter.hasNext();
2527
        }
2528

    
2529
        /**
2530
         * 
2531
         */
2532
        public static void showMemory() {
2533
                Runtime r = Runtime.getRuntime();
2534
                long mem = r.totalMemory() - r.freeMemory();
2535
                logger.info("Total memory : " + mem);
2536
        }
2537

    
2538
        /**
2539
         * 
2540
         * @param input
2541
         * @param ind
2542
         * @param n
2543
         * @return
2544
         */
2545
        private static double[] getIndDoublesModule(double[] input, int ind, int n) {
2546
                int size = input.length / n;
2547
                double[] resp = new double[size];
2548

    
2549
                for (int i = 0; i < size; i++) {
2550
                        resp[i] = input[(i * n) + ind];
2551
                }
2552

    
2553
                return resp;
2554
        }
2555

    
2556
        /**
2557
         * 
2558
         * @param input
2559
         * @param ind
2560
         * @param n
2561
         * @return
2562
         */
2563
        private static double[] getIndBigDecimalModule(double[] input, int ind,
2564
                        int n) {
2565
                int size = input.length / n;
2566
                double[] resp = new double[size];
2567

    
2568
                for (int i = 0; i < size; i++) {
2569
                        resp[i] = input[(i * n) + ind];
2570
                }
2571

    
2572
                return resp;
2573
        }
2574

    
2575
        /**
2576
         * 
2577
         * @param the_data
2578
         * @param dim
2579
         * @return
2580
         */
2581
        public static Geometry getFMapGeometryMultipolygon(Datum[] the_data, int dim) {
2582
                Geometry ig = null;
2583

    
2584
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2585

    
2586
                if (OracleUtils.isCircle(the_data)) {
2587
                        ig = getCircleFromStruct(the_data);
2588
                } else {
2589
                        GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2590

    
2591
                        try {
2592
                                if (dim == 2) {
2593
                                        ig = geomManager.createSurface(gpx,
2594
                                                        Geometry.SUBTYPES.GEOM2D);
2595
                                } else {
2596
                                        double[] ords = null;
2597

    
2598
                                        try {
2599
                                                ords = ((ARRAY) the_data[4]).getDoubleArray();
2600
                                        } catch (SQLException se) {
2601
                                                logger.error("While getting ordinates: "
2602
                                                                + se.getMessage(), se);
2603
                                        }
2604

    
2605
                                        double[] z = getIndBigDecimalModule(ords, 2, dim);
2606

    
2607
                                        ig = geomManager.createSurface(gpx,
2608
                                                        Geometry.SUBTYPES.GEOM2DZ);
2609
                                        for (int i = 0; i < z.length; i++) {
2610
                                                ((Surface2DZ) ig).setCoordinateAt(i, dim, z[i]);
2611
                                        }
2612

    
2613
                                }
2614

    
2615
                        } catch (CreateGeometryException e) {
2616
                                e.printStackTrace();
2617
                                return null;
2618
                        }
2619
                }
2620

    
2621
                return ig;
2622
        }
2623

    
2624
        /**
2625
         * 
2626
         * @param the_data
2627
         * @return
2628
         */
2629
        private static Geometry getCircleFromStruct(Datum[] the_data) {
2630
                double[] threep = null;
2631
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2632

    
2633
                try {
2634
                        threep = ((ARRAY) the_data[4]).getDoubleArray();
2635
                } catch (SQLException se) {
2636
                        logger.error("While getting ords from struct: " + se.getMessage(),
2637
                                        se);
2638

    
2639
                        try {
2640
                                return geomManager
2641
                                                .createNullGeometry(Geometry.SUBTYPES.UNKNOWN);
2642
                        } catch (CreateGeometryException e) {
2643
                                // TODO Auto-generated catch block
2644
                                e.printStackTrace();
2645
                        }
2646
                }
2647

    
2648
                Point2D[] three = new Point2D.Double[3];
2649
                three[0] = new Point2D.Double(threep[0], threep[1]);
2650
                three[1] = new Point2D.Double(threep[2], threep[3]);
2651
                three[2] = new Point2D.Double(threep[4], threep[5]);
2652

    
2653
                Object[] cent_rad = OracleUtils.getCenterAndRadiousOfCirc(three);
2654

    
2655
                Point2D cent = (Point2D) cent_rad[0];
2656
                double radius = ((Double) cent_rad[1]).doubleValue();
2657

    
2658
                Geometry circ = null;
2659
                try {
2660
                        circ = geomManager.create(Geometry.TYPES.CIRCLE,
2661
                                        Geometry.SUBTYPES.GEOM2D);
2662
                        ((Circle2D) circ).setPoints(cent, radius);
2663
                } catch (CreateGeometryException e) {
2664
                        e.printStackTrace();
2665
                        return null;
2666
                }
2667
                return circ;
2668
        }
2669

    
2670
        /**
2671
         * 
2672
         * @param the_data
2673
         * @param dim
2674
         * @return
2675
         */
2676
        public static Geometry getFMapGeometryMultiLineString(Datum[] the_data,
2677
                        int dim) {
2678
                GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2679
                Geometry ig = null;
2680
                double[] ords = null;
2681

    
2682
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2683

    
2684
                try {
2685
                        if (dim == 2) {
2686
                                ig = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM2D);
2687
                        } else {
2688
                                ords = OracleUtils.getOrds(the_data);
2689

    
2690
                                double[] z = getIndBigDecimalModule(ords, 2, dim);
2691
                                ig = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM2DZ);
2692
                                ((Curve2DZ) ig).setGeneralPath(gpx);
2693
                                for (int i = 0; i < z.length; i++) {
2694
                                        ((Curve2DZ) ig).setCoordinateAt(i, dim, z[i]);
2695
                                }
2696
                        }
2697
                } catch (Exception e) {
2698
                        e.printStackTrace();
2699
                        return null;
2700
                }
2701

    
2702
                return ig;
2703
        }
2704

    
2705
        /**
2706
         * 
2707
         * @param the_data
2708
         * @param dim
2709
         * @return
2710
         */
2711
        public static Geometry getFMapGeometryPoint(Datum[] the_data, int dim) {
2712

    
2713
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2714

    
2715
                double[] ords = OracleUtils.getOrds(the_data);
2716

    
2717
                if (ords == null) { // sdo_point
2718

    
2719
                        return getFMapGeometrySdoPoint(the_data, dim);
2720
                }
2721

    
2722
                Geometry ig = null;
2723
                int total_size = ords.length;
2724
                int no_po = total_size / dim;
2725
                double[] x = new double[no_po];
2726
                double[] y = new double[no_po];
2727
                double[] z = new double[no_po];
2728

    
2729
                for (int i = 0; i < no_po; i++) {
2730
                        x[i] = ords[i * dim]; // pp[i].getX();
2731
                        y[i] = ords[(i * dim) + 1];
2732

    
2733
                        if (dim >= 3) {
2734
                                z[i] = ords[(i * dim) + 2];
2735
                        }
2736
                }
2737
                try {
2738
                        if (dim == 2) {
2739
                                if (no_po == 1) {
2740

    
2741
                                        ig = geomManager.create(Geometry.TYPES.POINT,
2742
                                                        Geometry.SUBTYPES.GEOM2D);
2743

    
2744
                                        ((Point2D) ig).setLocation(x[0], y[0]);
2745
                                } else {
2746
                                        ig = geomManager.create(Geometry.TYPES.MULTIPOINT,
2747
                                                        Geometry.SUBTYPES.GEOM2D);
2748
                                        Point pto = null;
2749
                                        for (int i = 0; i < x.length; i++) {
2750
                                                pto = geomManager.createPoint(x[i], y[i],
2751
                                                                Geometry.SUBTYPES.GEOM2D);
2752
                                                ((MultiPoint2D) ig).addPoint(pto);
2753
                                        }
2754
                                }
2755
                        } else {
2756
                                if (no_po == 1) {
2757
                                        ig = geomManager.create(Geometry.TYPES.POINT,
2758
                                                        Geometry.SUBTYPES.GEOM2DZ);
2759
                                        double[] values = { x[0], y[0], z[0] };
2760
                                        ((Point2DZ) ig).setCoordinates(values);
2761
                                } else {
2762
                                        ig = geomManager.create(Geometry.TYPES.MULTIPOINT,
2763
                                                        Geometry.SUBTYPES.GEOM2DZ);
2764
                                        Point pto = null;
2765
                                        for (int i = 0; i < x.length; i++) {
2766
                                                pto = (Point) geomManager.create(Geometry.TYPES.POINT,
2767
                                                                Geometry.SUBTYPES.GEOM2DZ);
2768
                                                double[] valu = { x[i], y[i], z[i] };
2769
                                                ((Point2DZ) pto).setCoordinates(valu);
2770
                                                ((MultiPoint2D) ig).addPoint(pto);
2771
                                        }
2772
                                }
2773
                        }
2774
                } catch (CreateGeometryException e) {
2775
                        e.printStackTrace();
2776
                        return null;
2777
                }
2778

    
2779
                return ig;
2780
        }
2781

    
2782
        /**
2783
         * 
2784
         * @param the_data
2785
         * @param d
2786
         * @return
2787
         */
2788
        public static Geometry getFMapGeometrySdoPoint(Datum[] the_data, int d) {
2789
                double x = 0;
2790
                double y = 0;
2791
                double z = 0;
2792

    
2793
                try {
2794
                        Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
2795
                        x = ((NUMBER) aux[0]).doubleValue();
2796
                        y = ((NUMBER) aux[1]).doubleValue();
2797

    
2798
                        if (d > 2) {
2799
                                z = ((NUMBER) aux[2]).doubleValue();
2800
                        }
2801
                } catch (SQLException se) {
2802
                        logger.error("While getting sdo point ordinates: "
2803
                                        + se.getMessage(), se);
2804
                }
2805

    
2806
                Geometry ig = null;
2807

    
2808
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2809
                if (d == 2) {
2810
                        try {
2811
                                ig = geomManager.create(Geometry.TYPES.POINT,
2812
                                                Geometry.SUBTYPES.GEOM2D);
2813
                                ((Point2D) ig).setLocation(x, y);
2814
                        } catch (CreateGeometryException e) {
2815
                                e.printStackTrace();
2816
                        }
2817
                } else {
2818
                        try {
2819
                                ig = geomManager.create(Geometry.TYPES.POINT,
2820
                                                Geometry.SUBTYPES.GEOM3D);
2821
                                double[] values = { x, y, z };
2822
                                ((Point2DZ) ig).setCoordinates(values);
2823
                        } catch (CreateGeometryException e) {
2824
                                e.printStackTrace();
2825
                        }
2826
                }
2827

    
2828
                return ig;
2829
        }
2830

    
2831
        /**
2832
         * 
2833
         * @param the_data
2834
         * @return
2835
         */
2836
        public static boolean isActuallyACollection(Datum[] the_data) {
2837
                int[] info = null;
2838

    
2839
                try {
2840
                        ARRAY aux = (ARRAY) the_data[3];
2841

    
2842
                        if (aux == null) {
2843
                                return false;
2844
                        }
2845

    
2846
                        info = aux.getIntArray();
2847
                } catch (SQLException se) {
2848
                        logger.error("While checking collection: " + se.getMessage());
2849
                        return false;
2850
                }
2851

    
2852
                if (info == null) {
2853
                        return false; // sdo_point
2854
                }
2855

    
2856
                int size = info.length / 3;
2857

    
2858
                if (size == 1) {
2859
                        return false;
2860
                }
2861

    
2862
                if (size == 2) {
2863
                        return ((info[1] % 1000) != (info[4] % 1000))
2864
                                        && (!((info[1] == 1005) && (info[4] == 2)));
2865
                }
2866

    
2867
                int second = info[4] % 1000;
2868
                int item = 0;
2869

    
2870
                for (int i = 2; i < size; i++) {
2871
                        item = info[(i * 3) + 1] % 1000;
2872
                        if ((item != second) && (!((item == 5) && (second == 2)))) {
2873
                                return true;
2874
                        }
2875
                }
2876

    
2877
                return false;
2878
        }
2879

    
2880
        /**
2881
         * 
2882
         * @param info
2883
         * @return
2884
         */
2885
        public static Datum[] updateIndexes(Datum[] info) {
2886
                int size = info.length / 3;
2887
                NUMBER[] resp = new NUMBER[3 * size];
2888

    
2889
                try {
2890
                        int rest = info[0].intValue() - 1;
2891

    
2892
                        for (int i = 0; i < size; i++) {
2893
                                resp[3 * i] = new NUMBER(info[3 * i].intValue() - rest);
2894
                                resp[(3 * i) + 1] = new NUMBER(info[(3 * i) + 1].intValue());
2895
                                resp[(3 * i) + 2] = new NUMBER(info[(3 * i) + 2].intValue());
2896
                        }
2897
                } catch (SQLException se) {
2898
                        logger.error("Unexpected error: " + se.getMessage());
2899
                }
2900

    
2901
                return resp;
2902
        }
2903

    
2904
        /**
2905
         * 
2906
         * @param all
2907
         * @param first_inc
2908
         * @param last_inc
2909
         * @return
2910
         */
2911
        public static double[] getSubSet(double[] all, int first_inc, int last_inc) {
2912
                double[] resp = new double[last_inc - first_inc + 1];
2913

    
2914
                for (int i = first_inc; i <= last_inc; i++) {
2915
                        resp[i - first_inc] = all[i];
2916
                }
2917

    
2918
                return resp;
2919
        }
2920

    
2921
        /**
2922
         * 
2923
         * @param all
2924
         * @param groups
2925
         * @return
2926
         * @throws SQLException
2927
         */
2928
        public static Object[] getOrdOfGroups(Datum[] all, Object[] groups)
2929
                        throws SQLException {
2930
                Object[] resp = new Object[groups.length];
2931

    
2932
                if (resp.length == 1) {
2933
                        resp[0] = all;
2934

    
2935
                        return resp;
2936
                }
2937

    
2938
                int ind = 0;
2939
                Datum[] aux = (Datum[]) groups[1];
2940
                int _end = aux[0].intValue() - 2;
2941
                Datum[] ord_aux = getSubSet(all, 0, _end);
2942

    
2943
                int _start = _end + 1;
2944
                resp[ind] = ord_aux;
2945
                ind++;
2946

    
2947
                for (int i = 2; i < groups.length; i++) {
2948
                        aux = (Datum[]) groups[i];
2949
                        _end = aux[0].intValue() - 2;
2950
                        ord_aux = getSubSet(all, _start, _end);
2951
                        resp[ind] = ord_aux;
2952
                        ind++;
2953
                        _start = _end + 1;
2954
                }
2955

    
2956
                // last
2957
                _end = all.length - 1;
2958
                ord_aux = getSubSet(all, _start, _end);
2959
                resp[groups.length - 1] = ord_aux;
2960

    
2961
                return resp;
2962
        }
2963

    
2964
        /**
2965
         * 
2966
         * @param all
2967
         * @param groups
2968
         * @return
2969
         */
2970
        public static Object[] getOrdOfGroups(double[] all, Object[] groups) {
2971
                Object[] resp = new Object[groups.length];
2972

    
2973
                if (resp.length == 1) {
2974
                        resp[0] = all;
2975

    
2976
                        return resp;
2977
                }
2978

    
2979
                int ind = 0;
2980
                int[] aux = (int[]) groups[1];
2981
                int _end = aux[0] - 2;
2982
                double[] ord_aux = getSubSet(all, 0, _end);
2983

    
2984
                int _start = _end + 1;
2985
                resp[ind] = ord_aux;
2986
                ind++;
2987

    
2988
                for (int i = 2; i < groups.length; i++) {
2989
                        aux = (int[]) groups[i];
2990
                        _end = aux[0] - 2;
2991
                        ord_aux = getSubSet(all, _start, _end);
2992
                        resp[ind] = ord_aux;
2993
                        ind++;
2994
                        _start = _end + 1;
2995
                }
2996

    
2997
                // last
2998
                _end = all.length - 1;
2999
                ord_aux = getSubSet(all, _start, _end);
3000
                resp[groups.length - 1] = ord_aux;
3001

    
3002
                return resp;
3003
        }
3004

    
3005
        /**
3006
         * 
3007
         * @param all_elem
3008
         * @return
3009
         */
3010
        public static Object[] groupByElement(int[] all_elem) {
3011
                List<int[]> resp = new ArrayList<int[]>();
3012

    
3013
                int size = all_elem.length / 3;
3014

    
3015
                int[] aux = getNthGroupOfThree(all_elem, 0);
3016

    
3017
                int[] newaux;
3018
                int i = 1;
3019

    
3020
                while (i < size) {
3021
                        newaux = getNthGroupOfThree(all_elem, i);
3022

    
3023
                        if (newaux[0] == aux[0]) {
3024
                                // aux[2] says how many components
3025
                                for (int j = 0; j < aux[2]; j++) {
3026
                                        aux = appendIntArrays(aux, getNthGroupOfThree(all_elem, j
3027
                                                        + i));
3028
                                }
3029

    
3030
                                resp.add(aux);
3031
                                i = i + aux[2];
3032
                                aux = getNthGroupOfThree(all_elem, i);
3033
                        } else {
3034
                                if (newaux[1] == 2003) {
3035
                                        aux = appendIntArrays(aux, newaux);
3036
                                } else {
3037
                                        resp.add(aux);
3038
                                        aux = getNthGroupOfThree(all_elem, i);
3039
                                }
3040
                        }
3041

    
3042
                        i++;
3043
                }
3044

    
3045
                resp.add(aux);
3046

    
3047
                return resp.toArray();
3048
        }
3049

    
3050
        /**
3051
         * 
3052
         * @param all_elem
3053
         * @return
3054
         */
3055
        public static boolean isSimpleCollectionOfLines(Datum[] all_elem) {
3056

    
3057
                try {
3058
                        int size = all_elem.length;
3059
                        if (all_elem[1].intValue() != 4)
3060
                                return false;
3061
                        int size3 = size / 3;
3062

    
3063
                        for (int i = 1; i < size3; i++) {
3064
                                if (all_elem[3 * i + 1].intValue() != 2)
3065
                                        return false;
3066
                        }
3067
                        return true;
3068

    
3069
                } catch (SQLException ex) {
3070
                        logger.error("While is simple line collection: " + ex.getMessage());
3071
                }
3072

    
3073
                return false;
3074
        }
3075

    
3076
        /**
3077
         * 
3078
         * @param elem
3079
         * @return
3080
         */
3081
        public static Datum[] removeThreeFirst(Datum[] elem) {
3082
                int sz = elem.length;
3083
                Datum[] resp = new Datum[sz - 3];
3084
                for (int i = 3; i < sz; i++)
3085
                        resp[i - 3] = elem[i];
3086
                return resp;
3087
        }
3088

    
3089
        /**
3090
         * 
3091
         * @param all_elem
3092
         * @return
3093
         */
3094
        public static Object[] groupByElement(Datum[] all_elem) {
3095

    
3096
                if (isSimpleCollectionOfLines(all_elem)) {
3097
                        Object[] r = new Object[1];
3098
                        r[0] = removeThreeFirst(all_elem);
3099
                        return r;
3100
                }
3101

    
3102
                List<Datum[]> resp = new ArrayList<Datum[]>();
3103

    
3104
                int size = all_elem.length / 3;
3105

    
3106
                Datum[] aux = getNthGroupOfThree(all_elem, 0);
3107

    
3108
                Datum[] newaux;
3109
                int i = 1;
3110
                boolean add_last_time = true;
3111

    
3112
                try {
3113
                        while (i < size) {
3114
                                newaux = getNthGroupOfThree(all_elem, i);
3115

    
3116
                                if (newaux[0].intValue() == aux[0].intValue()) {
3117
                                        // aux[2] says how many components
3118
                                        for (int j = 0; j < ((NUMBER) aux[2]).intValue(); j++) {
3119
                                                aux = appendDatArrays(aux, getNthGroupOfThree(all_elem,
3120
                                                                j + i));
3121
                                        }
3122

    
3123
                                        resp.add(aux);
3124
                                        i = i + ((NUMBER) aux[2]).intValue();
3125
                                        if (i < size) { // in some cases (line collection, 4)
3126
                                                aux = getNthGroupOfThree(all_elem, i);
3127
                                        } else {
3128
                                                add_last_time = false;
3129
                                        }
3130
                                } else {
3131
                                        if (((NUMBER) newaux[1]).intValue() == 2003) {
3132
                                                aux = appendDatArrays(aux, newaux);
3133
                                        } else {
3134
                                                resp.add(aux);
3135
                                                aux = getNthGroupOfThree(all_elem, i);
3136
                                        }
3137
                                }
3138

    
3139
                                i++;
3140
                        }
3141
                } catch (SQLException se) {
3142
                        logger.error("Unexpected error: " + se.getMessage());
3143
                }
3144

    
3145
                if (add_last_time) {
3146
                        resp.add(aux);
3147
                }
3148

    
3149
                return resp.toArray();
3150
        }
3151

    
3152
        /**
3153
         * 
3154
         * @param shp
3155
         * @return
3156
         */
3157
        public static Geometry shapeToGeometry(Shape shp) {
3158
                
3159
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
3160
                
3161
                if (shp == null) {
3162
                        return null;
3163
                }
3164
                
3165
                Geometry geom = null;
3166

    
3167
                int type = Geometry.TYPES.SURFACE;
3168

    
3169
                if ((shp instanceof Curve2D) && (!(shp instanceof Surface2D))) {
3170
                        type = Geometry.TYPES.CURVE;
3171
                        geom = geomManager.create(type, Geometry.SUBTYPES.GEOM2D);
3172
                        GeneralPathX gpx = new GeneralPathX(shp);
3173
                        ((Curve2D)geom).setGeneralPath(gpx);
3174
                        return geom;
3175
                }
3176

    
3177
                if (shp instanceof Point2D) {
3178
                        type = Geometry.TYPES.POINT;
3179
                        geom = geomManager.create(type, Geometry.SUBTYPES.GEOM2D);
3180
                        ((Point2D)geom).setGeneralPath(gpx.);
3181
                }
3182

    
3183
                if (shp instanceof MultiPoint2D) {
3184
                        type = Geometry.TYPES.MULTIPOINT;
3185
                }                
3186

    
3187
                return geom;
3188
        }
3189

    
3190
        /**
3191
         * 
3192
         * @param r
3193
         * @param hasSrid
3194
         * @param isView
3195
         * @param _isGeogCS
3196
         * @param _oracleSRID
3197
         * @param __conn
3198
         * @return
3199
         */
3200
        public static STRUCT rectangleToStruct(Rectangle2D r, boolean hasSrid,
3201
                        boolean isView, boolean _isGeogCS, String _oracleSRID,
3202
                        Connection __conn) {
3203
                Point2D c1 = new Point2D.Double(r.getMinX(), r.getMinY());
3204
                Point2D c2 = new Point2D.Double(r.getMaxX(), r.getMaxY());
3205

    
3206
                if ((_isGeogCS) && (isView)) {
3207
                        c1.setLocation(Math.max(c1.getX(), -180), Math.max(c1.getY(), -90));
3208
                        c2.setLocation(Math.min(c2.getX(), 180), Math.min(c2.getY(), 90));
3209
                }
3210

    
3211
                STRUCT resp = null;
3212

    
3213
                try {
3214
                        // System.out.println("ABIERTA: " + (!conn.isClosed()));
3215
                        // resp = structCreator.toSTRUCT(rect_wkt.getBytes(), conn);
3216
                        // Object[] old_obj = resp.getAttributes();
3217
                        int size = 5;
3218
                        Object[] new_obj = new Object[size];
3219

    
3220
                        // for (int i=0; i<size; i++) new_obj[i] = old_obj[i];
3221
                        new_obj[0] = new NUMBER(2003);
3222

    
3223
                        if (hasSrid) {
3224
                                new_obj[1] = new NUMBER(_oracleSRID);
3225
                        } else {
3226
                                new_obj[1] = null;
3227
                        }
3228

    
3229
                        new_obj[2] = null;
3230

    
3231
                        NUMBER[] elem_info = new NUMBER[3];
3232
                        elem_info[0] = new NUMBER(1);
3233
                        elem_info[1] = new NUMBER(1003);
3234
                        elem_info[2] = new NUMBER(3);
3235
                        new_obj[3] = elem_info;
3236

    
3237
                        NUMBER[] ords = null;
3238
                        ords = new NUMBER[4];
3239
                        ords[0] = new NUMBER(c1.getX());
3240
                        ords[1] = new NUMBER(c1.getY());
3241
                        ords[2] = new NUMBER(c2.getX());
3242
                        ords[3] = new NUMBER(c2.getY());
3243
                        new_obj[4] = ords;
3244

    
3245
                        StructDescriptor dsc = StructDescriptor.createDescriptor(
3246
                                        "MDSYS.SDO_GEOMETRY", __conn);
3247

    
3248
                        resp = new STRUCT(dsc, __conn, new_obj);
3249
                } catch (Exception ex) {
3250
                        logger.error(
3251
                                        "Error while creating rect struct: " + ex.getMessage(), ex);
3252
                }
3253

    
3254
                return resp;
3255
        }
3256

    
3257
        /**
3258
         * 
3259
         * @param r1
3260
         * @param r2
3261
         * @return
3262
         */
3263
        public static Rectangle2D doIntersect(Rectangle2D r1, Rectangle2D r2) {
3264
                if (r1.getMaxX() <= r2.getMinX()) {
3265
                        return null;
3266
                }
3267

    
3268
                if (r2.getMaxX() <= r1.getMinX()) {
3269
                        return null;
3270
                }
3271

    
3272
                if (r1.getMaxY() <= r2.getMinY()) {
3273
                        return null;
3274
                }
3275

    
3276
                if (r2.getMaxY() <= r1.getMinY()) {
3277
                        return null;
3278
                }
3279

    
3280
                double minx = Math.max(r1.getMinX(), r2.getMinX());
3281
                double miny = Math.max(r1.getMinY(), r2.getMinY());
3282
                double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
3283
                double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
3284

    
3285
                double w = maxx - minx;
3286
                double h = maxy - miny;
3287

    
3288
                return new Rectangle2D.Double(minx, miny, w, h);
3289
        }
3290

    
3291
        /**
3292
         * Utility method to find out if a coordinate system is geodetic or not.
3293
         * 
3294
         * @param oracleSRID2
3295
         *            the coordinate system's oracle code
3296
         * @param thas
3297
         *            whether the table has a coordinate system set. if not, the
3298
         *            method returns false.
3299
         * @return whether the coordinate system is geodetic or not.
3300
         */
3301
        public static boolean getIsGCS(String oracleSRID2, boolean thas) {
3302

    
3303
                if (!thas)
3304
                        return false;
3305
                if (oracleSRID2 == null)
3306
                        return false;
3307

    
3308
                int ora_cs = 0;
3309

    
3310
                try {
3311
                        ora_cs = Integer.parseInt(oracleSRID2);
3312
                } catch (Exception ex) {
3313
                        return false;
3314
                }
3315

    
3316
                if (((ora_cs >= 8000) && (ora_cs <= 8999)) || (ora_cs == 524288)) {
3317
                        return true;
3318
                } else {
3319
                        return false;
3320
                }
3321
        }
3322

    
3323
        /**
3324
         * 
3325
         * @param sample
3326
         * @return
3327
         * @throws SQLException
3328
         */
3329
        public static int getShapeTypeOfStruct(STRUCT sample) throws SQLException {
3330

    
3331
                int code = ((NUMBER) sample.getOracleAttributes()[0]).intValue();
3332

    
3333
                int type_part = code % 10;
3334
                int dim_part = code / 1000;
3335

    
3336
                int z_added = 0;
3337
                if (dim_part == 3) {
3338
                        z_added = Geometry.SUBTYPES.GEOM3D;
3339
                } else {
3340
                        if (dim_part == 4) {
3341
                                z_added = Geometry.SUBTYPES.GEOM3DM;
3342
                        }
3343
                }
3344

    
3345
                switch (type_part) {
3346
                case 1:
3347
                        return z_added + Geometry.TYPES.POINT;
3348

    
3349
                case 2:
3350
                        return z_added + Geometry.TYPES.CURVE;
3351

    
3352
                case 3:
3353
                        return z_added + Geometry.TYPES.SURFACE;
3354

    
3355
                case 4:
3356
                        return z_added + Geometry.TYPES.AGGREGATE;
3357

    
3358
                case 5:
3359
                        return z_added + Geometry.TYPES.MULTIPOINT;
3360

    
3361
                case 6:
3362
                        return z_added + Geometry.TYPES.MULTICURVE;
3363

    
3364
                case 7:
3365
                        return z_added + Geometry.TYPES.MULTISURFACE;
3366
                }
3367

    
3368
                logger.error("Unknown geometry type: " + code);
3369

    
3370
                return Geometry.TYPES.NULL;
3371
        }
3372

    
3373
        /**
3374
         * 
3375
         * @param info
3376
         * @return
3377
         */
3378
        public static int[] updateIndexes(int[] info) {
3379
                int size = info.length / 3;
3380
                int[] resp = new int[3 * size];
3381
                int rest = info[0] - 1;
3382

    
3383
                for (int i = 0; i < size; i++) {
3384
                        resp[3 * i] = info[3 * i] - rest;
3385
                        resp[(3 * i) + 1] = info[(3 * i) + 1];
3386
                        resp[(3 * i) + 2] = info[(3 * i) + 2];
3387
                }
3388

    
3389
                return resp;
3390
        }
3391

    
3392
        /**
3393
         * 
3394
         * @param head
3395
         * @param tail
3396
         * @return
3397
         */
3398
        public static int[] appendIntArrays(int[] head, int[] tail) {
3399
                int[] resp = new int[head.length + tail.length];
3400
                int hsize = head.length;
3401

    
3402
                for (int i = 0; i < hsize; i++) {
3403
                        resp[i] = head[i];
3404
                }
3405

    
3406
                for (int i = 0; i < tail.length; i++) {
3407
                        resp[hsize + i] = tail[i];
3408
                }
3409

    
3410
                return resp;
3411
        }
3412

    
3413
        /**
3414
         * 
3415
         * @param head
3416
         * @param tail
3417
         * @return
3418
         */
3419
        public static Datum[] appendDatArrays(Datum[] head, Datum[] tail) {
3420
                Datum[] resp = new Datum[head.length + tail.length];
3421
                int hsize = head.length;
3422

    
3423
                for (int i = 0; i < hsize; i++) {
3424
                        resp[i] = head[i];
3425
                }
3426

    
3427
                for (int i = 0; i < tail.length; i++) {
3428
                        resp[hsize + i] = tail[i];
3429
                }
3430

    
3431
                return resp;
3432
        }
3433

    
3434
        /**
3435
         * 
3436
         * @param list
3437
         * @param n
3438
         * @return
3439
         */
3440
        public static int[] getNthGroupOfThree(int[] list, int n) {
3441
                int[] resp = new int[3];
3442
                resp[0] = list[3 * n];
3443
                resp[1] = list[(3 * n) + 1];
3444
                resp[2] = list[(3 * n) + 2];
3445

    
3446
                return resp;
3447
        }
3448

    
3449
        /**
3450
         * 
3451
         * @param list
3452
         * @param n
3453
         * @return
3454
         */
3455
        public static Datum[] getNthGroupOfThree(Datum[] list, int n) {
3456
                Datum[] resp = new Datum[3];
3457
                resp[0] = list[3 * n];
3458
                resp[1] = list[(3 * n) + 1];
3459
                resp[2] = list[(3 * n) + 2];
3460

    
3461
                return resp;
3462
        }
3463

    
3464
        /**
3465
         * 
3466
         * @param all
3467
         * @param first_inc
3468
         * @param last_inc
3469
         * @return
3470
         */
3471
        public static Datum[] getSubSet(Datum[] all, int first_inc, int last_inc) {
3472
                Datum[] resp = new Datum[last_inc - first_inc + 1];
3473

    
3474
                for (int i = first_inc; i <= last_inc; i++) {
3475
                        resp[i - first_inc] = all[i];
3476
                }
3477

    
3478
                return resp;
3479
        }
3480

    
3481
        /**
3482
         * 
3483
         * @param _type
3484
         * @return
3485
         */
3486
        public static int maxSizeForFieldType(int _type) {
3487
                switch (_type) {
3488
                case Types.VARCHAR:
3489
                        return OracleSpatialValues.VARCHAR2_STANDARD_SIZE;
3490

    
3491
                case Types.LONGVARCHAR:
3492
                        return OracleSpatialValues.VARCHAR2_LONG_SIZE;
3493
                }
3494

    
3495
                return -1;
3496
        }
3497

    
3498
        /**
3499
         * 
3500
         * @param ig
3501
         * @param _forced_type
3502
         * @param _conn
3503
         * @param _o_srid
3504
         * @param withSrid
3505
         * @param agu_bien
3506
         * @param _isGeoCS
3507
         * @return
3508
         */
3509
        public static STRUCT geometryToSTRUCT(Geometry ig, int _forced_type,
3510
                        Connection _conn, String _o_srid, boolean withSrid,
3511
                        boolean agu_bien, boolean _isGeoCS) {
3512
                if (ig instanceof Aggregate) {
3513
                        Aggregate coll = (Aggregate) ig;
3514

    
3515
                        return OracleSpatialUtils.appendGeometriesInStruct(coll,
3516
                                        _forced_type, _conn, _o_srid, withSrid, agu_bien, _isGeoCS);
3517

    
3518
                } else {
3519
                        Shape shp = ig.getInternalShape();
3520

    
3521
                        return shapeToStruct(shp, _forced_type, _conn, _o_srid, withSrid,
3522
                                        agu_bien, false, _isGeoCS);
3523
                }
3524
        }
3525

    
3526
        /**
3527
         * 
3528
         * @param shp
3529
         * @param forced_type
3530
         * @param _conn
3531
         * @param o_srid
3532
         * @param hasSrid
3533
         * @param agu_bien
3534
         * @param isView
3535
         * @param _isGeoCS
3536
         * @return
3537
         */
3538
        public static STRUCT shapeToStruct(Shape shp, int forced_type,
3539
                        Connection _conn, String o_srid, boolean hasSrid, boolean agu_bien,
3540
                        boolean isView, boolean _isGeoCS) {
3541
                int _srid = -1;
3542

    
3543
                if ((o_srid != null) && (o_srid.length() > 0)) {
3544
                        _srid = Integer.parseInt(o_srid);
3545
                }
3546

    
3547
                if (shp == null) {
3548
                        logger.info("Shape is null. shapeToStruct(Shape) returned null.");
3549

    
3550
                        return null;
3551
                }
3552

    
3553
                if (shp instanceof Rectangle2D) {
3554
                        return OracleUtils.rectangleToStruct((Rectangle2D) shp,
3555
                                        hasSrid, isView, _isGeoCS, o_srid, _conn);
3556
                }
3557

    
3558
                try {
3559
                        STRUCT the_struct = OracleUtils.fShapeToSTRUCT(shp, _conn,
3560
                                        _srid, agu_bien, hasSrid);
3561

    
3562
                        return the_struct;
3563
                } catch (SQLException ex) {
3564
                        logger.error("While creating STRUCT: " + ex.getMessage());
3565

    
3566
                        return null;
3567
                }
3568
        }
3569
        
3570
         /**
3571
     * Utility method to transform a struct into a IGeometry.
3572
     *
3573
     * @param st the struct to be converted
3574
     * @param complex comes from a complex sdo geometry
3575
     * @return the IGeometry
3576
     */
3577
    private Geometry getFMapGeometry(STRUCT st, boolean complex) {
3578

    
3579
            GeometryManager geomManager = GeometryLocator.getGeometryManager();
3580
            
3581
            if (st == null) {
3582
                    return geomManager.createNullGeometry(Geometry.SUBTYPES.UNKNOWN);
3583
            }
3584
            
3585

    
3586
        Datum[] the_data = null;
3587

    
3588
        try {
3589
            the_data = st.getOracleAttributes();
3590

    
3591
            int jgtype = ((NUMBER) the_data[0]).intValue() % 1000;
3592
            jgtype = OracleUtils.oracleGTypeToFShapeType(jgtype, complex);
3593

    
3594
            int dim = ((NUMBER) the_data[0]).intValue() / 1000;
3595

    
3596
            if (dim < 2) {
3597
                dim = 2;
3598
            }
3599

    
3600
            Geometry ig = null;
3601

    
3602
            if (OracleUtils.isActuallyACollection(the_data)) {
3603
                jgtype = Geometry.TYPES.AGGREGATE;
3604
            }
3605

    
3606
            switch (jgtype) {
3607
            case Geometry.TYPES.AGGREGATE:
3608

    
3609
                // int srid = ((NUMBER) the_data[1]).intValue();
3610
                ig = getFMapGeometryCollection(the_data, dim);
3611

    
3612
                break;
3613

    
3614
            case Geometry.TYPES.POINT:
3615
                ig = OracleUtils.getFMapGeometryPoint(the_data, dim);
3616

    
3617
                break;
3618

    
3619
            case Geometry.TYPES.CURVE:
3620
                ig = OracleUtils.getFMapGeometryMultiLineString(the_data, dim);
3621

    
3622
                break;
3623

    
3624
            case Geometry.TYPES.SURFACE:
3625
                ig = OracleUtils.getFMapGeometryMultipolygon(the_data, dim);
3626

    
3627
                break;
3628
            }
3629

    
3630
            return ig;
3631
        }
3632
        catch (SQLException e) {
3633
            logger.error(e);
3634
        }
3635

    
3636
        return null;
3637
    }
3638
    
3639
    private Geometry getFMapGeometryCollection(Datum[] the_data, int dim) {
3640
        // int __srid) {
3641

    
3642
            NUMBER _srid = new NUMBER(0);
3643
        NUMBER main_type = new NUMBER((dim * 1000) +
3644
                        OracleUtils.getStructType(the_data));
3645

    
3646

    
3647
        Datum[] all_info_array = null;
3648
        Object[] elems_info_aray = null;
3649
        Datum[] all_ords = null;
3650

    
3651
        Object[] ords_of_groups = null;
3652
        Object[] _elems_info_aray = null;
3653
        try {
3654
            all_info_array = ((ARRAY) the_data[3]).getOracleArray();
3655
            elems_info_aray = OracleUtils.groupByElement(all_info_array);
3656
            all_ords = ((ARRAY) the_data[4]).getOracleArray();
3657

    
3658
            ords_of_groups = OracleUtils.getOrdOfGroups(all_ords, elems_info_aray);
3659
            _elems_info_aray = new Object[elems_info_aray.length];
3660
        }
3661
        catch (SQLException e) {
3662
            logger.error("Unexpected error: " + e.getMessage());
3663
        }
3664

    
3665

    
3666
        for (int i = 0; i < elems_info_aray.length; i++) {
3667
            _elems_info_aray[i] = OracleUtils.updateIndexes((Datum[]) elems_info_aray[i]);
3668
        }
3669

    
3670
        // _elems_info_aray, ords_of_groups
3671
        int no_of_elems = ords_of_groups.length;
3672
        Geometry[] geoms = new Geometry[no_of_elems];
3673

    
3674
        for (int i = 0; i < no_of_elems; i++) {
3675
            Datum[] item_info_array = null;
3676
            Datum[] item_ords = null;
3677
            NUMBER gtype = null;
3678

    
3679
            try {
3680
                item_info_array = (Datum[]) _elems_info_aray[i];
3681
                item_ords = (Datum[]) ords_of_groups[i];
3682

    
3683
                gtype = new NUMBER((dim * 1000) +
3684
                        (item_info_array[1].intValue() % 1000));
3685

    
3686
                if (tableHasSrid) {
3687
                        _srid = new NUMBER(Integer.parseInt(oracleSRID));
3688
                }
3689
            }
3690
            catch (SQLException se) {
3691
                logger.error("Unexpected error: " + se.getMessage());
3692
            }
3693

    
3694
            // if it's the first geometry, the type is the collection's main type (no?) - no
3695
            // if (i == 0) gtype = main_type;
3696

    
3697
            STRUCT itemst = null;
3698

    
3699
            if (tableHasSrid) {
3700

    
3701
                itemst = OracleSpatialUtils.createStruct(gtype, _srid,
3702
                        item_info_array, item_ords, conn);
3703
            }
3704
            else {
3705
                itemst = OracleSpatialUtils.createStruct(gtype, null,
3706
                        item_info_array, item_ords, conn);
3707
            }
3708

    
3709
            geoms[i] = getFMapGeometry(itemst, true);
3710
        }
3711

    
3712
        return new FGeometryCollection(geoms);
3713
    }
3714

    
3715
}