Statistics
| Revision:

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

History | View | Annotate | Download (84.7 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.MultiCurve;
62
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
63
import org.gvsig.fmap.geom.aggregate.MultiSolid;
64
import org.gvsig.fmap.geom.aggregate.MultiSurface;
65
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2D;
66
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2DZ;
67
import org.gvsig.fmap.geom.aggregate.impl.MultiSurface2D;
68
import org.gvsig.fmap.geom.exception.CreateGeometryException;
69
import org.gvsig.fmap.geom.primitive.Curve;
70
import org.gvsig.fmap.geom.primitive.GeneralPathX;
71
import org.gvsig.fmap.geom.primitive.Point;
72
import org.gvsig.fmap.geom.primitive.Primitive;
73
import org.gvsig.fmap.geom.primitive.Surface;
74
import org.gvsig.fmap.geom.primitive.impl.Circle2D;
75
import org.gvsig.fmap.geom.primitive.impl.Curve2D;
76
import org.gvsig.fmap.geom.primitive.impl.Curve2DZ;
77
import org.gvsig.fmap.geom.primitive.impl.Point2DZ;
78
import org.gvsig.fmap.geom.primitive.impl.Surface2D;
79
import org.gvsig.fmap.geom.primitive.impl.Surface2DZ;
80
import org.gvsig.oracle.utils.LineString3D;
81
import org.slf4j.Logger;
82
import org.slf4j.LoggerFactory;
83

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

    
93
/**
94
 * Utility class with static methods.
95
 * 
96
 * @author jldominguez, vsanjaime
97
 * 
98
 */
99
public class OracleUtils1 {
100

    
101
        private static Logger logger = LoggerFactory.getLogger(OracleUtils.class
102
                        .getName());
103

    
104
        private static Random rnd = new Random();
105
        private static DecimalFormat df = new DecimalFormat();
106
        private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
107

    
108
        /**
109
         * Constructs a geometry from a file that contains a vertex per line:
110
         * 
111
         * x1 y1 z1 x2 y2 z2 ...
112
         * 
113
         * @param filepath
114
         *            vertices text file path
115
         * @param polygon
116
         *            whether it is a polygon or not
117
         * @return the created geometry
118
         */
119
        public static Geometry readGeometry3D(URL filepath, boolean polygon) {
120

    
121
                GeometryManager gManager = GeometryLocator.getGeometryManager();
122

    
123
                GeneralPathX gpath = new GeneralPathX();
124
                File file = new File(filepath.getFile());
125
                List<Double> z = new ArrayList<Double>();
126

    
127
                try {
128
                        FileReader fr = new FileReader(file);
129
                        BufferedReader br = new BufferedReader(fr);
130
                        double[] coords = new double[3];
131

    
132
                        boolean move = true;
133

    
134
                        String line = br.readLine();
135

    
136
                        while (line != null) {
137
                                coords = parseLine(line);
138

    
139
                                if (line.length() == 0) {
140
                                        move = true;
141
                                } else {
142
                                        if (move) {
143
                                                gpath.moveTo(coords[0], coords[1]);
144
                                                z.add(new Double(coords[2]));
145
                                        } else {
146
                                                gpath.lineTo(coords[0], coords[1]);
147
                                                z.add(new Double(coords[2]));
148
                                        }
149

    
150
                                        move = false;
151
                                }
152

    
153
                                line = br.readLine();
154
                        }
155
                } catch (Exception ex) {
156
                        logger.error("While creating GeneralPathX: " + ex.getMessage());
157

    
158
                        return null;
159
                }
160

    
161
                double[] zz = new double[z.size()];
162

    
163
                for (int i = 0; i < z.size(); i++) {
164
                        zz[i] = ((Double) z.get(i)).doubleValue();
165
                }
166

    
167
                if (polygon) {
168
                        try {
169
                                return gManager.createSurface(gpath, Geometry.SUBTYPES.GEOM3D);
170
                        } catch (CreateGeometryException e) {
171
                                e.printStackTrace();
172
                                return null;
173
                        }
174
                } else {
175
                        try {
176
                                return gManager.createCurve(gpath, Geometry.SUBTYPES.GEOM3D);
177
                        } catch (CreateGeometryException e) {
178
                                e.printStackTrace();
179
                                return null;
180
                        }
181
                }
182
        }
183

    
184
        /**
185
         * Parse line
186
         * 
187
         * @param line
188
         * @return
189
         */
190
        private static double[] parseLine(String line) {
191
                String[] sep = line.split(" ");
192
                double[] resp = new double[3];
193

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

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

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

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

    
216
                return resp;
217
        }
218

    
219
        /**
220
         * Utility method to convert a gvSIG Geometry into a oracle struct
221
         * 
222
         * @param geom
223
         *            the FShape object
224
         * @param c
225
         *            the connection
226
         * @param srid
227
         *            the SRS (oracle code)
228
         * @param agu_b
229
         *            whether to check holes validity
230
         * @param hasSrid
231
         *            whether the SRS is non-NULL
232
         * @return a oracle struct representing the geometry
233
         * 
234
         * @throws SQLException
235
         */
236
        public static STRUCT GeometryToSTRUCT(Geometry geom, Connection c,
237
                        int srid, boolean agu_b, boolean hasSrid) throws SQLException {
238

    
239
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
240

    
241
                STRUCT resp = null;
242

    
243
                // PRIMITIVES
244
                if (geom instanceof Primitive) {
245
                        // POINT
246
                        if (geom instanceof Point) {
247
                                // POINT 2D
248
                                if (geom instanceof Point2D) {
249
                                        Coordinate p = getSingleCoordinate((Point) geom);
250
                                        resp = getPointAsStruct(p, srid, false, c, hasSrid);
251
                                        return resp;
252
                                }
253
                                // POINT 2DZ
254
                                if (geom instanceof Point2DZ) {
255
                                        Coordinate p = getSingleCoordinate((Point) geom);
256
                                        resp = getPointAsStruct(p, srid, true, c, hasSrid);
257
                                        return resp;
258
                                }
259
                        }
260
                        // CURVE
261
                        if (geom instanceof Curve) {
262
                                // CURVE 2D
263
                                if (geom instanceof Curve2D) {
264

    
265
                                        return resp;
266
                                }
267
                                // CURVE 2DZ
268
                                if (geom instanceof Curve2DZ) {
269

    
270
                                        return resp;
271
                                }
272
                        }
273
                        // SURFACE
274
                        if (geom instanceof Surface) {
275
                                // SURFACE 2D
276
                                if (geom instanceof Surface2D) {
277

    
278
                                        return resp;
279
                                }
280
                                // SURFACE 2DZ
281
                                if (geom instanceof Surface2DZ) {
282

    
283
                                        return resp;
284
                                }
285
                        }
286
                }
287

    
288
                // AGGREGATE
289
                if (geom instanceof Aggregate) {
290
                        // MULTIPRIMITIVE
291
                        if (geom instanceof MultiPrimitive) {
292
                                return null;
293
                        }
294
                        // MULTIPOINT
295
                        if (geom instanceof MultiPoint) {
296
                                // MULTIPOINT 2D
297
                                if (geom instanceof MultiPoint2D) {
298
                                        resp = multiPointToStruct((MultiPoint2D) geom, c, srid,
299
                                                        hasSrid);
300
                                        return resp;
301
                                }
302
                                // MULTIPOINT 2DZ
303
                                if (geom instanceof MultiPoint2DZ) {
304
                                        resp = multiPointToStruct((MultiPoint2DZ) geom, c, srid,
305
                                                        hasSrid);
306
                                        return resp;
307
                                }
308
                        }
309
                        // MULTICURVE
310
                        if (geom instanceof MultiCurve) {
311

    
312
                        }
313
                        // MULTISURFACE
314
                        if (geom instanceof MultiSurface) {
315

    
316
                        }
317
                        // MULTISOLID
318
                        if (geom instanceof MultiSolid) {
319
                                return null;
320
                        }
321
                }
322

    
323
                // POINT
324
                if (geom instanceof Point2D) {
325

    
326
                        Coordinate p = getSingleCoordinate((Point2D) geom);
327
                        resp = getMultiPointAsStruct(p, srid, three, c, hasSrid);
328
                } else {
329
                        if (geom instanceof Surface2D) { // polygon 2/3d
330

    
331
                                if (geom instanceof Circle2D) {
332
                                        resp = getCircleAsStruct((Circle2D) geom, srid, c, hasSrid);
333
                                } else {
334
                                        // also FEllipse2D
335
                                        resp = getMultiPolygonAsStruct((MultiSurface) geom, srid,
336
                                                        three, c, agu_b, hasSrid);
337

    
338
                                }
339
                        }
340
                        // LINE
341
                        else { // line 2/3d
342

    
343
                                List<LineString3D> _lines = getLineStrings((Shape) geom);
344
                                resp = getMultiLineAsStruct(_lines, srid, three, c, hasSrid);
345
                        }
346
                }
347

    
348
                return resp;
349
        }
350

    
351
        /**
352
         * Build a Oracle STRUCT from gvSIG multiPoint
353
         * 
354
         * @param mpto
355
         * @param c
356
         * @param srid
357
         * @param hasSrid
358
         * @return
359
         * @throws SQLException
360
         */
361
        private static STRUCT multiPointToStruct(MultiPoint2D mpto, Connection c,
362
                        int srid, boolean hasSrid) throws SQLException {
363
                int np = mpto.getPrimitivesNumber();
364
                boolean threed = (mpto instanceof MultiPoint2DZ);
365
                int gtype = 2005;
366
                int dim = 2;
367
                MultiPoint2DZ mp3d = null;
368

    
369
                if (threed) {
370
                        gtype = 3005;
371
                        dim = 3;
372
                        mp3d = (MultiPoint2DZ) mpto;
373
                }
374

    
375
                NUMBER[] indices = new NUMBER[3];
376
                indices[0] = new NUMBER(1);
377
                indices[1] = new NUMBER(1);
378
                indices[2] = new NUMBER(np);
379

    
380
                NUMBER[] ords = new NUMBER[dim * np];
381

    
382
                for (int i = 0; i < np; i++) {
383
                        ords[dim * i] = new NUMBER(mpto.getPoint(i).getX());
384
                        ords[(dim * i) + 1] = new NUMBER(mpto.getPoint(i).getY());
385

    
386
                        if (threed) {
387
                                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
388
                        }
389
                }
390

    
391
                STRUCT resp;
392
                StructDescriptor dsc = StructDescriptor.createDescriptor(
393
                                "MDSYS.SDO_GEOMETRY", c);
394
                Object[] obj = new Object[5];
395
                obj[0] = new NUMBER(gtype);
396

    
397
                if (hasSrid) {
398
                        obj[1] = new NUMBER(srid);
399
                } else { // , boolean hasSrid
400
                        obj[1] = null;
401
                }
402

    
403
                obj[2] = null;
404
                obj[3] = indices;
405
                obj[4] = ords;
406
                resp = new STRUCT(dsc, c, obj);
407

    
408
                return resp;
409
        }
410

    
411
        /**
412
         * Get coordinate of a 2d or 2DZ point
413
         * 
414
         * @param pto
415
         * @return
416
         */
417
        private static Coordinate getSingleCoordinate(Point pto) {
418
                Coordinate resp = new Coordinate();
419
                resp.x = pto.getX();
420
                resp.y = pto.getY();
421

    
422
                if (pto instanceof Point2DZ) {
423
                        resp.z = pto.getCoordinateAt(3);
424
                }
425
                return resp;
426
        }
427

    
428
        /**
429
         * tolerance
430
         * 
431
         * @param cc
432
         * @return
433
         */
434
        private static List<Coordinate> ensureSensibleLineString(List<Coordinate> cc) {
435
                if (cc.size() == 2) {
436
                        if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(cc
437
                                        .size() - 1))) {
438
                                List<Coordinate> resp = new ArrayList<Coordinate>();
439
                                resp.add(cc.get(0));
440

    
441
                                Coordinate newc = new Coordinate((Coordinate) cc.get(0));
442
                                newc.x = newc.x + OracleValues.IRRELEVANT_DISTANCE;
443
                                resp.add(newc);
444

    
445
                                return resp;
446
                        }
447
                }
448

    
449
                return cc;
450
        }
451

    
452
        /**
453
         * Validate if two coordinates are equal
454
         * 
455
         * @param c1
456
         * @param c2
457
         * @return
458
         */
459
        private static boolean sameCoordinate(Coordinate c1, Coordinate c2) {
460
                if (c1.x != c2.x) {
461
                        return false;
462
                }
463

    
464
                if (c1.y != c2.y) {
465
                        return false;
466
                }
467

    
468
                return true;
469
        }
470

    
471
        private static List<Coordinate> getClosedRelevantPolygon(List<Coordinate> cc) {
472
                if (cc.size() == 2) {
473
                        return getMinClosedCoords((Coordinate) cc.get(0));
474
                }
475

    
476
                if (cc.size() == 3) {
477
                        if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(1))) {
478
                                return getMinClosedCoords((Coordinate) cc.get(0));
479
                        }
480

    
481
                        if (sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(2))) {
482
                                return getMinClosedCoords((Coordinate) cc.get(0));
483
                        }
484

    
485
                        if (sameCoordinate((Coordinate) cc.get(1), (Coordinate) cc.get(2))) {
486
                                return getMinClosedCoords((Coordinate) cc.get(1));
487
                        }
488

    
489
                        cc.add(cc.get(0));
490

    
491
                        return cc;
492
                }
493

    
494
                if (!sameCoordinate((Coordinate) cc.get(0), (Coordinate) cc.get(cc
495
                                .size() - 1))) {
496
                        cc.add(cc.get(0));
497
                }
498

    
499
                return cc;
500
        }
501

    
502
        private static List<Coordinate> getMinClosedCoords(Coordinate c) {
503
                List<Coordinate> resp = new ArrayList<Coordinate>();
504
                resp.add(c);
505

    
506
                Coordinate nc = new Coordinate(c);
507
                nc.x = nc.x + OracleValues.IRRELEVANT_DISTANCE;
508
                resp.add(nc);
509

    
510
                Coordinate nc2 = new Coordinate(nc);
511
                nc2.y = nc2.y + OracleValues.IRRELEVANT_DISTANCE;
512
                resp.add(nc2);
513

    
514
                resp.add(new Coordinate(c));
515

    
516
                return resp;
517
        }
518

    
519
        private static LinearRing getMinLinearRing(Coordinate c) {
520
                Coordinate[] p = new Coordinate[4];
521
                p[0] = c;
522

    
523
                Coordinate nc = new Coordinate(c);
524
                nc.x = nc.x + OracleValues.IRRELEVANT_DISTANCE;
525

    
526
                Coordinate nc2 = new Coordinate(nc);
527
                nc2.y = nc2.y - OracleValues.IRRELEVANT_DISTANCE;
528
                p[1] = nc;
529
                p[2] = nc2;
530
                p[3] = new Coordinate(c);
531

    
532
                CoordinateArraySequence cs = new CoordinateArraySequence(p);
533
                LinearRing ls = new LinearRing(cs, geomFactory);
534

    
535
                return ls;
536
        }
537

    
538
        private static double[] getMinLinearRingZ() {
539
                double[] resp = new double[4];
540

    
541
                for (int i = 0; i < 4; i++)
542
                        resp[i] = 0.0;
543

    
544
                return resp;
545
        }
546

    
547
        private static boolean pointInList(Coordinate testPoint,
548
                        Coordinate[] pointList) {
549
                int t;
550
                int numpoints;
551
                Coordinate p;
552

    
553
                numpoints = Array.getLength(pointList);
554

    
555
                for (t = 0; t < numpoints; t++) {
556
                        p = pointList[t];
557

    
558
                        if ((testPoint.x == p.x)
559
                                        && (testPoint.y == p.y)
560
                                        && ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z)))) {
561
                                return true;
562
                        }
563
                }
564

    
565
                return false;
566
        }
567

    
568
        private static double[] getZ(Geometry p3d, int _str, int _end, int size) {
569
                double[] resp = new double[size];
570
                double[] allz = p3d.getZs();
571

    
572
                for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) {
573
                        resp[i - _str] = allz[i];
574
                }
575

    
576
                if ((_end - _str + 1) < size) {
577
                        double repe = allz[_end];
578

    
579
                        for (int i = (_end - _str + 1); i < size; i++) {
580
                                resp[i] = repe;
581
                        }
582
                }
583

    
584
                return resp;
585
        }
586

    
587
        private static List<LineString3D> getPolygonsEasily(Geometry mpolygon) {
588
                
589
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
590
                
591
                boolean threed = false;
592

    
593
                if (mpolygon instanceof Surface2DZ) {
594
                        threed = true;
595
                }
596

    
597
                int start_ind = 0;
598
                int end_ind = 0;
599
                int ind = 0;
600
                int new_size;
601
                List<Coordinate> arrayCoords = null;
602
                List<LineString3D> resp = new ArrayList<LineString3D>();
603
                Coordinate[] points = null;
604
                int theType = -99;
605
                double[] theData = new double[6];
606
                Coordinate onlyCoord = null;
607
                int numParts = 0;
608

    
609
                PathIterator theIterator = mpolygon.getPathIterator(null, OracleValues.FLATNESS);
610

    
611
                while (!theIterator.isDone()) {
612
                        // while not done
613
                        theType = theIterator.currentSegment(theData);
614

    
615
                        if (onlyCoord == null) {
616
                                onlyCoord = new Coordinate();
617
                                onlyCoord.x = theData[0];
618
                                onlyCoord.y = theData[1];
619
                        }
620

    
621
                        switch (theType) {
622
                        case PathIterator.SEG_MOVETO:
623

    
624
                                if (arrayCoords == null) {
625
                                        arrayCoords = new ArrayList<Coordinate>();
626
                                } else {
627
                                        end_ind = ind - 1;
628

    
629
                                        arrayCoords = getClosedRelevantPolygon(arrayCoords);
630
                                        new_size = arrayCoords.size();
631

    
632
                                        if (arrayCoords != null) {
633
                                                points = CoordinateArrays
634
                                                                .toCoordinateArray(arrayCoords);
635

    
636
                                                try {
637
                                                        LinearRing aux = geomManager.
638
                                                                        .createLinearRing(points);
639
                                                        double[] z = null;
640

    
641
                                                        if (threed) {
642
                                                                z = getZ((Surface2DZ) mpolygon, start_ind,
643
                                                                                end_ind, new_size);
644
                                                        }
645

    
646
                                                        LineString3D ring = new LineString3D(aux, z);
647

    
648
                                                        if (CGAlgorithms.isCCW(points)) {
649
                                                                resp.add(ring);
650
                                                        } else {
651
                                                                resp.add(ring.createReverse());
652
                                                        }
653
                                                } catch (Exception e) {
654
                                                        logger.error("Topology exception: "
655
                                                                        + e.getMessage());
656

    
657
                                                        return null;
658
                                                }
659
                                        }
660

    
661
                                        arrayCoords = new ArrayList<Coordinate>();
662

    
663
                                        start_ind = ind;
664
                                }
665

    
666
                                numParts++;
667

    
668
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
669
                                ind++;
670

    
671
                                break;
672

    
673
                        case PathIterator.SEG_LINETO:
674
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
675
                                ind++;
676

    
677
                                break;
678

    
679
                        case PathIterator.SEG_QUADTO:
680
                                logger.info("SEG_QUADTO Not supported here");
681
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
682
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
683
                                ind++;
684
                                ind++;
685

    
686
                                break;
687

    
688
                        case PathIterator.SEG_CUBICTO:
689
                                logger.info("SEG_CUBICTO Not supported here");
690
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
691
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
692
                                arrayCoords.add(new Coordinate(theData[4], theData[5]));
693
                                ind++;
694
                                ind++;
695
                                ind++;
696

    
697
                                break;
698

    
699
                        case PathIterator.SEG_CLOSE:
700

    
701
                                // Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
702
                                // arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
703
                                break;
704
                        } // end switch
705

    
706
                        theIterator.next();
707
                } // end while loop
708

    
709
                end_ind = ind - 1;
710

    
711
                // null shape:
712
                if (arrayCoords == null) {
713
                        arrayCoords = new ArrayList<Coordinate>();
714

    
715
                        Coordinate _c = new Coordinate(0, 0, 0);
716
                        arrayCoords.add(new Coordinate(_c));
717
                        arrayCoords.add(new Coordinate(_c));
718
                }
719

    
720
                // --------------------------------------------
721
                arrayCoords = getClosedRelevantPolygon(arrayCoords);
722
                new_size = arrayCoords.size();
723

    
724
                if (arrayCoords != null) {
725
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
726

    
727
                        try {
728
                                LinearRing aux = geomFactory.createLinearRing(points);
729
                                double[] z = null;
730

    
731
                                if (threed) {
732
                                        z = getZ(mpolygon, start_ind, end_ind, new_size);
733
                                }
734

    
735
                                LineString3D ring = new LineString3D(aux, z);
736

    
737
                                if (CGAlgorithms.isCCW(points)) {
738
                                        resp.add(ring);
739
                                } else {
740
                                        resp.add(ring.createReverse());
741
                                }
742
                        } catch (Exception e) {
743
                                logger.error("Topology exception: " + e.getMessage());
744

    
745
                                return null;
746
                        }
747
                }
748

    
749
                if (resp.size() == 0) {
750
                        resp.add(new LineString3D(getMinLinearRing(onlyCoord),
751
                                        getMinLinearRingZ()));
752
                }
753

    
754
                return resp;
755
        }
756

    
757
        /**
758
         * Utility method to reverse an array of doubles.
759
         * 
760
         * @param _z
761
         *            an array of doubles to be reversed.
762
         * 
763
         * @return the reversed array of doubles
764
         */
765
        public static double[] reverseArray(double[] _z) {
766
                int size = _z.length;
767
                double[] resp = new double[size];
768

    
769
                for (int i = 0; i < size; i++) {
770
                        resp[i] = _z[size - 1 - i];
771
                }
772

    
773
                return resp;
774
        }
775

    
776
        /**
777
         * Utility method to reverse an array of coordinates
778
         * 
779
         * @param _z
780
         *            an array of coordinaes to be reversed.
781
         * 
782
         * @return the reversed array of coordinates
783
         */
784
        public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) {
785
                int size = _z.length;
786
                Coordinate[] resp = new Coordinate[size];
787

    
788
                for (int i = 0; i < size; i++) {
789
                        resp[i] = _z[size - 1 - i];
790
                }
791

    
792
                return resp;
793
        }
794

    
795
        private static List<LineString3D> getLineStrings(Shape mlines) {
796
                boolean threed = false;
797

    
798
                if (mlines instanceof Curve2DZ) {
799
                        threed = true;
800
                }
801

    
802
                int start_ind = 0;
803
                int end_ind = 0;
804
                int ind = 0;
805
                int new_size = 0;
806

    
807
                LineString3D lin;
808

    
809
                List<LineString3D> arrayLines = new ArrayList<LineString3D>();
810
                PathIterator theIterator = mlines.getPathIterator(null,
811
                                OracleValues.FLATNESS);
812
                int theType = -99;
813
                double[] theData = new double[6];
814
                List<Coordinate> arrayCoords = null;
815
                int numParts = 0;
816

    
817
                while (!theIterator.isDone()) {
818
                        // while not done
819
                        theType = theIterator.currentSegment(theData);
820

    
821
                        switch (theType) {
822
                        case PathIterator.SEG_MOVETO:
823

    
824
                                if (arrayCoords == null) {
825
                                        arrayCoords = new ArrayList<Coordinate>();
826
                                } else {
827
                                        end_ind = ind - 1;
828
                                        arrayCoords = ensureSensibleLineString(arrayCoords);
829
                                        new_size = arrayCoords.size();
830

    
831
                                        LineString aux = geomFactory
832
                                                        .createLineString(CoordinateArrays
833
                                                                        .toCoordinateArray(arrayCoords));
834
                                        double[] z = null;
835

    
836
                                        if (threed) {
837
                                                z = getZ((Curve2DZ) mlines, start_ind, end_ind,
838
                                                                new_size);
839
                                        }
840

    
841
                                        lin = new LineString3D(aux, z);
842
                                        arrayLines.add(lin);
843
                                        arrayCoords = new ArrayList<Coordinate>();
844

    
845
                                        start_ind = ind;
846
                                }
847

    
848
                                numParts++;
849
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
850

    
851
                                break;
852

    
853
                        case PathIterator.SEG_LINETO:
854
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
855

    
856
                                break;
857

    
858
                        case PathIterator.SEG_QUADTO:
859
                                logger.info("Not supported here: SEG_QUADTO");
860

    
861
                                break;
862

    
863
                        case PathIterator.SEG_CUBICTO:
864
                                logger.info("Not supported here: SEG_CUBICTO");
865

    
866
                                break;
867

    
868
                        case PathIterator.SEG_CLOSE:
869

    
870
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
871
                                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
872

    
873
                                break;
874
                        } // end switch
875

    
876
                        theIterator.next();
877
                        ind++;
878
                } // end while loop
879

    
880
                arrayCoords = ensureSensibleLineString(arrayCoords);
881
                new_size = arrayCoords.size();
882

    
883
                LineString aux = geomFactory.createLineString(CoordinateArrays
884
                                .toCoordinateArray(arrayCoords));
885
                double[] z = null;
886

    
887
                if (threed) {
888
                        z = getZ((Curve2DZ) mlines, start_ind, end_ind, new_size);
889
                }
890

    
891
                lin = new LineString3D(aux, z);
892
                arrayLines.add(lin);
893

    
894
                return arrayLines;
895
        }
896

    
897
        private static String lineStringToWKT(LineString3D ls, boolean threed) {
898
                String resp = "(";
899
                Coordinate[] cc = ls.getLs().getCoordinates();
900
                double[] z = ls.getZc();
901
                int size = cc.length;
902

    
903
                if (threed) {
904
                        for (int i = 0; i < size; i++) {
905
                                resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", ";
906
                        }
907

    
908
                        resp = resp.substring(0, resp.length() - 2);
909
                        resp = resp + ")";
910
                } else {
911
                        for (int i = 0; i < size; i++) {
912
                                resp = resp + cc[i].x + " " + cc[i].y + ", ";
913
                        }
914

    
915
                        resp = resp.substring(0, resp.length() - 2);
916
                        resp = resp + ")";
917
                }
918

    
919
                return resp;
920
        }
921

    
922
        private static String multiLineStringToWKT(List<LineString3D> ml,
923
                        boolean threed) {
924
                String resp = "MULTILINESTRING(";
925

    
926
                for (int i = 0; i < ml.size(); i++) {
927
                        LineString3D ls = ml.get(i);
928
                        resp = resp + lineStringToWKT(ls, threed) + ", ";
929
                }
930

    
931
                resp = resp.substring(0, resp.length() - 2) + ")";
932

    
933
                return resp;
934
        }
935

    
936
        private static String polygonsToWKT(List<LineString3D> pols, boolean threed) {
937
                String resp = "MULTIPOLYGON(";
938
                LineString3D ls = null;
939

    
940
                for (int i = 0; i < pols.size(); i++) {
941
                        ls = (LineString3D) pols.get(i);
942
                        resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
943
                }
944

    
945
                resp = resp.substring(0, resp.length() - 2) + ")";
946

    
947
                return resp;
948
        }
949

    
950
        private static String shellAndHolesToWKT(LineString3D shell,
951
                        List<LineString3D> holes, boolean threed) {
952
                String resp = "(";
953
                resp = resp + lineStringToWKT(shell, threed);
954

    
955
                if (holes.size() > 0) {
956
                        for (int i = 0; i < holes.size(); i++) {
957
                                LineString3D ls = (LineString3D) holes.get(i);
958
                                resp = resp + ", " + lineStringToWKT(ls, threed);
959
                        }
960
                }
961

    
962
                resp = resp + ")";
963

    
964
                return resp;
965
        }
966

    
967
        private static String multiPolygonToWKT(List<LineString3D> shells,
968
                        List<List<LineString3D>> hFs, boolean threed) {
969
                String resp = "MULTIPOLYGON(";
970
                LineString3D ls = null;
971
                List<LineString3D> holes;
972

    
973
                for (int i = 0; i < shells.size(); i++) {
974
                        ls = (LineString3D) shells.get(i);
975
                        holes = (List<LineString3D>) hFs.get(i);
976
                        resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
977
                }
978

    
979
                resp = resp.substring(0, resp.length() - 2) + ")";
980

    
981
                return resp;
982
        }
983

    
984
        private static String pointToWKT(Point point, boolean threed) {
985
                String resp = "POINT(" + point.getX() + " " + point.getY();
986

    
987
                if ((threed) && (point instanceof Point2DZ)) {
988
                        resp = resp + " " + ((Point2DZ) point).getCoordinateAt(3);
989
                }
990

    
991
                resp = resp + ")";
992

    
993
                return resp;
994
        }
995

    
996
        private static int twoDIndexToDimsIndex(int n, int d) {
997
                return ((d * (n - 1)) / 2) + 1;
998
        }
999

    
1000
        private static ARRAY setSubelementsToDim(ARRAY old, int d)
1001
                        throws SQLException {
1002
                Datum[] infos = (Datum[]) old.getOracleArray();
1003

    
1004
                for (int i = 3; i < infos.length; i = i + 3) {
1005
                        int oldind = infos[i].intValue();
1006
                        oldind = twoDIndexToDimsIndex(oldind, d);
1007
                        infos[i] = new NUMBER(oldind);
1008

    
1009
                        //
1010
                        oldind = infos[i + 1].intValue();
1011
                        infos[i + 1] = new NUMBER(infos[1].intValue());
1012
                }
1013

    
1014
                ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
1015
                                infos);
1016

    
1017
                return resp;
1018
        }
1019

    
1020
        private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
1021
                Envelope env = ls.getEnvelopeInternal();
1022

    
1023
                if (!env.contains(p)) {
1024
                        return false;
1025
                }
1026

    
1027
                return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
1028
        }
1029

    
1030
        private static boolean lineString3DIsContainedBy(LineString3D contained,
1031
                        LineString3D container) {
1032
                int samples = 10;
1033
                LineString _in = contained.getLs();
1034
                LineString _out = container.getLs();
1035
                Coordinate[] inc = _in.getCoordinates();
1036
                Coordinate aux;
1037
                int size = inc.length;
1038

    
1039
                if (size <= 10) {
1040
                        for (int i = 0; i < size; i++) {
1041
                                aux = inc[i];
1042

    
1043
                                if (!isPointInsideLineString(aux, _out)) {
1044
                                        return false;
1045
                                }
1046
                        }
1047

    
1048
                        return true;
1049
                } else {
1050
                        for (int i = 0; i < samples; i++) {
1051
                                aux = inc[rnd.nextInt(size)];
1052

    
1053
                                if (!isPointInsideLineString(aux, _out)) {
1054
                                        return false;
1055
                                }
1056
                        }
1057

    
1058
                        return true;
1059
                }
1060
        }
1061

    
1062
        private static STRUCT getMultiPolygonAsStruct(List<LineString3D> pols,
1063
                        int srid, boolean threed, Connection _conn, boolean agu_bien,
1064
                        boolean hasSrid) throws SQLException {
1065
                int size = pols.size();
1066
                int geotype = 2007;
1067
                int dim = 2;
1068
                int acum = 0;
1069

    
1070
                if (threed) {
1071
                        geotype = 3007;
1072
                        dim = 3;
1073
                }
1074

    
1075
                NUMBER[] indices = new NUMBER[3 * size];
1076

    
1077
                for (int i = 0; i < size; i++) {
1078
                        indices[3 * i] = new NUMBER(acum + 1);
1079
                        indices[(3 * i) + 1] = new NUMBER(1003);
1080
                        indices[(3 * i) + 2] = new NUMBER(1);
1081
                        acum = acum
1082
                                        + (dim * ((LineString3D) pols.get(i)).getLs()
1083
                                                        .getNumPoints());
1084
                }
1085

    
1086
                int _ind = 0;
1087
                NUMBER[] ords = new NUMBER[acum];
1088

    
1089
                for (int i = 0; i < size; i++) {
1090
                        LineString3D ls = (LineString3D) pols.get(i);
1091
                        int num_p = ls.getLs().getNumPoints();
1092

    
1093
                        for (int j = 0; j < num_p; j++) {
1094
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1095
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1096

    
1097
                                if (threed) {
1098
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1099
                                }
1100

    
1101
                                _ind = _ind + dim;
1102
                        }
1103
                }
1104

    
1105
                STRUCT resp;
1106
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1107
                                "MDSYS.SDO_GEOMETRY", _conn);
1108
                Object[] obj = new Object[5];
1109
                obj[0] = new NUMBER(geotype);
1110

    
1111
                if (hasSrid) {
1112
                        obj[1] = new NUMBER(srid);
1113
                } else {
1114
                        obj[1] = null;
1115
                }
1116

    
1117
                obj[2] = null;
1118
                obj[3] = indices;
1119
                obj[4] = ords;
1120
                resp = new STRUCT(dsc, _conn, obj);
1121

    
1122
                return resp;
1123
        }
1124

    
1125
        private static STRUCT getMultiLineAsStruct(List<LineString3D> lines,
1126
                        int srid, boolean threed, Connection _conn, boolean hasSrid)
1127
                        throws SQLException {
1128

    
1129
                int size = lines.size();
1130
                int geotype = 2006;
1131
                int dim = 2;
1132
                int acum = 0;
1133

    
1134
                if (threed) {
1135
                        geotype = 3006;
1136
                        dim = 3;
1137
                }
1138

    
1139
                NUMBER[] indices = new NUMBER[3 * size];
1140

    
1141
                for (int i = 0; i < size; i++) {
1142
                        indices[3 * i] = new NUMBER(acum + 1);
1143
                        indices[(3 * i) + 1] = new NUMBER(2);
1144
                        indices[(3 * i) + 2] = new NUMBER(1);
1145
                        acum = acum
1146
                                        + (dim * ((LineString3D) lines.get(i)).getLs()
1147
                                                        .getNumPoints());
1148
                }
1149

    
1150
                int _ind = 0;
1151
                NUMBER[] ords = new NUMBER[acum];
1152

    
1153
                for (int i = 0; i < size; i++) {
1154
                        LineString3D ls = (LineString3D) lines.get(i);
1155
                        int num_p = ls.getLs().getNumPoints();
1156

    
1157
                        for (int j = 0; j < num_p; j++) {
1158
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1159
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1160

    
1161
                                if (threed) {
1162
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1163
                                }
1164

    
1165
                                _ind = _ind + dim;
1166
                        }
1167
                }
1168

    
1169
                STRUCT resp;
1170
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1171
                                "MDSYS.SDO_GEOMETRY", _conn);
1172
                Object[] obj = new Object[5];
1173
                obj[0] = new NUMBER(geotype);
1174

    
1175
                if (hasSrid) {
1176
                        obj[1] = new NUMBER(srid);
1177
                } else {
1178
                        obj[1] = null;
1179
                }
1180

    
1181
                obj[2] = null;
1182
                obj[3] = indices;
1183
                obj[4] = ords;
1184
                resp = new STRUCT(dsc, _conn, obj);
1185

    
1186
                return resp;
1187
        }
1188

    
1189
        private static STRUCT getLineAsStruct(List<LineString3D> lines, int srid,
1190
                        boolean threed, Connection _conn, boolean hasSrid)
1191
                        throws SQLException {
1192

    
1193
                int size = lines.size();
1194
                int geotype = 2006;
1195
                int dim = 2;
1196
                int acum = 0;
1197

    
1198
                if (threed) {
1199
                        geotype = 3006;
1200
                        dim = 3;
1201
                }
1202

    
1203
                NUMBER[] indices = new NUMBER[3 * size];
1204

    
1205
                for (int i = 0; i < size; i++) {
1206
                        indices[3 * i] = new NUMBER(acum + 1);
1207
                        indices[(3 * i) + 1] = new NUMBER(2);
1208
                        indices[(3 * i) + 2] = new NUMBER(1);
1209
                        acum = acum
1210
                                        + (dim * ((LineString3D) lines.get(i)).getLs()
1211
                                                        .getNumPoints());
1212
                }
1213

    
1214
                int _ind = 0;
1215
                NUMBER[] ords = new NUMBER[acum];
1216

    
1217
                for (int i = 0; i < size; i++) {
1218
                        LineString3D ls = (LineString3D) lines.get(i);
1219
                        int num_p = ls.getLs().getNumPoints();
1220

    
1221
                        for (int j = 0; j < num_p; j++) {
1222
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1223
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1224

    
1225
                                if (threed) {
1226
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1227
                                }
1228

    
1229
                                _ind = _ind + dim;
1230
                        }
1231
                }
1232

    
1233
                STRUCT resp;
1234
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1235
                                "MDSYS.SDO_GEOMETRY", _conn);
1236
                Object[] obj = new Object[5];
1237
                obj[0] = new NUMBER(geotype);
1238

    
1239
                if (hasSrid) {
1240
                        obj[1] = new NUMBER(srid);
1241
                } else {
1242
                        obj[1] = null;
1243
                }
1244

    
1245
                obj[2] = null;
1246
                obj[3] = indices;
1247
                obj[4] = ords;
1248
                resp = new STRUCT(dsc, _conn, obj);
1249

    
1250
                return resp;
1251
        }
1252

    
1253
        /**
1254
         * Get point as STRUCT
1255
         * 
1256
         * @param pnt
1257
         * @param srid
1258
         * @param threed
1259
         * @param _conn
1260
         * @param hasSrid
1261
         * @return
1262
         * @throws SQLException
1263
         */
1264
        private static STRUCT getPointAsStruct(Coordinate pnt, int srid,
1265
                        boolean threed, Connection _conn, boolean hasSrid)
1266
                        throws SQLException {
1267

    
1268
                int geotype = 2001;
1269
                int dim = 2;
1270

    
1271
                if (threed) {
1272
                        geotype = 3001;
1273
                        dim = 3;
1274
                }
1275

    
1276
                Object[] ords = new Object[3];
1277
                ords[0] = new NUMBER(pnt.x);
1278
                ords[1] = new NUMBER(pnt.y);
1279
                ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null;
1280

    
1281
                StructDescriptor ord_dsc = StructDescriptor.createDescriptor(
1282
                                "MDSYS.SDO_POINT_TYPE", _conn);
1283
                STRUCT ords_st = new STRUCT(ord_dsc, _conn, ords);
1284

    
1285
                STRUCT resp;
1286

    
1287
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1288
                                "MDSYS.SDO_GEOMETRY", _conn);
1289
                Object[] obj = new Object[5];
1290

    
1291
                obj[0] = new NUMBER(geotype);
1292

    
1293
                if (hasSrid) {
1294
                        obj[1] = new NUMBER(srid);
1295
                } else {
1296
                        obj[1] = null;
1297
                }
1298

    
1299
                obj[2] = ords_st;
1300
                obj[3] = null;
1301
                obj[4] = null;
1302
                resp = new STRUCT(dsc, _conn, obj);
1303

    
1304
                return resp;
1305
        }
1306

    
1307
        /**
1308
         * Utility method to compute a circle's center and radius from three given
1309
         * points.
1310
         * 
1311
         * @param points
1312
         *            three points of a circumference
1313
         * @return a 2-item array with the circumference's center (Point2D) and
1314
         *         radius (Double)
1315
         */
1316
        public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1317
                Object[] resp = new Object[2];
1318
                resp[0] = new Point2D.Double(0, 0);
1319
                resp[1] = new Double(0);
1320

    
1321
                double m11;
1322
                double m12;
1323
                double m13;
1324
                double m14;
1325

    
1326
                if (points.length != 3) {
1327
                        logger.error("Needs 3 points (found " + points.length
1328
                                        + ") - circle cannot be computed.");
1329

    
1330
                        // not a circle
1331
                        return resp;
1332
                }
1333

    
1334
                double[][] a = new double[3][3];
1335

    
1336
                for (int i = 0; i < 3; i++) { // find minor 11
1337
                        a[i][0] = points[i].getX();
1338
                        a[i][1] = points[i].getY();
1339
                        a[i][2] = 1;
1340
                }
1341

    
1342
                m11 = determinant(a, 3);
1343

    
1344
                for (int i = 0; i < 3; i++) { // find minor 12
1345
                        a[i][0] = (points[i].getX() * points[i].getX())
1346
                                        + (points[i].getY() * points[i].getY());
1347
                        a[i][1] = points[i].getY();
1348
                        a[i][2] = 1;
1349
                }
1350

    
1351
                m12 = determinant(a, 3);
1352

    
1353
                for (int i = 0; i < 3; i++) // find minor 13
1354
                {
1355
                        a[i][0] = (points[i].getX() * points[i].getX())
1356
                                        + (points[i].getY() * points[i].getY());
1357
                        a[i][1] = points[i].getX();
1358
                        a[i][2] = 1;
1359
                }
1360

    
1361
                m13 = determinant(a, 3);
1362

    
1363
                for (int i = 0; i < 3; i++) { // find minor 14
1364
                        a[i][0] = (points[i].getX() * points[i].getX())
1365
                                        + (points[i].getY() * points[i].getY());
1366
                        a[i][1] = points[i].getX();
1367
                        a[i][2] = points[i].getY();
1368
                }
1369

    
1370
                m14 = determinant(a, 3);
1371

    
1372
                Double resp_radius = new Double(0);
1373
                Point2D resp_center = new Point2D.Double(0, 0);
1374

    
1375
                if (m11 == 0) {
1376
                        logger.error("Three points aligned - circle cannot be computed."); // not
1377
                        // a
1378
                        // circle
1379
                } else {
1380
                        double x = (0.5 * m12) / m11;
1381
                        double y = (-0.5 * m13) / m11;
1382
                        resp_center.setLocation(x, y);
1383
                        resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11)));
1384
                        resp[0] = resp_center;
1385
                        resp[1] = resp_radius;
1386
                }
1387

    
1388
                return resp;
1389
        }
1390

    
1391
        /**
1392
         * Utility method to compute a matrix determinant
1393
         * 
1394
         * @param a
1395
         *            the matrix
1396
         * @param n
1397
         *            matrix size
1398
         * @return the matrix's determinant
1399
         */
1400
        public static double determinant(double[][] a, int n) {
1401
                double resp = 0;
1402
                double[][] m = new double[3][3];
1403

    
1404
                if (n == 2) { // terminate recursion
1405
                        resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1406
                } else {
1407
                        resp = 0;
1408

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

    
1411
                                for (int i = 1; i < n; i++) { // create minor
1412

    
1413
                                        int j2 = 0;
1414

    
1415
                                        for (int j = 0; j < n; j++) {
1416
                                                if (j == j1) {
1417
                                                        continue;
1418
                                                }
1419

    
1420
                                                m[i - 1][j2] = a[i][j];
1421
                                                j2++;
1422
                                        }
1423
                                }
1424

    
1425
                                // sum (+/-)cofactor * minor
1426
                                resp = resp
1427
                                                + (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1428
                        }
1429
                }
1430

    
1431
                return resp;
1432
        }
1433

    
1434
        private static int getSmallestContainerExcept(LineString3D ls,
1435
                        List<LineString3D> list, int self) {
1436
                int resp = -1;
1437
                List<Integer> provList = new ArrayList<Integer>();
1438

    
1439
                int size = list.size();
1440

    
1441
                for (int i = 0; i < self; i++) {
1442
                        if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1443
                                provList.add(new Integer(i));
1444
                        }
1445
                }
1446

    
1447
                for (int i = (self + 1); i < size; i++) {
1448
                        if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1449
                                provList.add(new Integer(i));
1450
                        }
1451
                }
1452

    
1453
                if (provList.size() == 0) {
1454
                        // logger.debug("LineString is not contained by any other ls.");
1455
                } else {
1456
                        if (provList.size() == 1) {
1457
                                resp = ((Integer) provList.get(0)).intValue();
1458
                        } else {
1459
                                if (provList.size() == 2) {
1460
                                        int ind_1 = ((Integer) provList.get(0)).intValue();
1461
                                        int ind_2 = ((Integer) provList.get(1)).intValue();
1462
                                        LineString3D ls1 = (LineString3D) list.get(ind_1);
1463
                                        LineString3D ls2 = (LineString3D) list.get(ind_2);
1464

    
1465
                                        if (lineString3DIsContainedBy(ls1, ls2)) {
1466
                                                resp = ind_1;
1467
                                        } else {
1468
                                                resp = ind_2;
1469
                                        }
1470
                                } else {
1471
                                        // not so deep, sorry!
1472
                                        // it's going to be a shell: resp = -1;
1473
                                }
1474
                        }
1475
                }
1476

    
1477
                return resp;
1478
        }
1479

    
1480
        private static int[] getIndicesOfShells(int[] containings) {
1481
                List<Integer> resp = new ArrayList<Integer>();
1482

    
1483
                for (int i = 0; i < containings.length; i++) {
1484
                        if (containings[i] == -1) {
1485
                                resp.add(new Integer(i));
1486
                        }
1487
                }
1488

    
1489
                int size = resp.size();
1490
                int[] _resp = new int[size];
1491

    
1492
                for (int i = 0; i < size; i++) {
1493
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1494
                }
1495

    
1496
                return _resp;
1497
        }
1498

    
1499
        private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1500
                List<Integer> resp = new ArrayList<Integer>();
1501

    
1502
                for (int i = 0; i < containings.length; i++) {
1503
                        int cont_by = containings[i];
1504

    
1505
                        if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1506
                                resp.add(new Integer(i));
1507
                        }
1508
                }
1509

    
1510
                int size = resp.size();
1511
                int[] _resp = new int[size];
1512

    
1513
                for (int i = 0; i < size; i++) {
1514
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1515
                }
1516

    
1517
                return _resp;
1518
        }
1519

    
1520
        private static int[] getFinalContainings(int[] containings, int[] holes) {
1521
                List<Integer> resp = new ArrayList<Integer>();
1522

    
1523
                for (int i = 0; i < containings.length; i++) {
1524
                        int cont_by = containings[i];
1525

    
1526
                        if (isOneOf(cont_by, holes)) {
1527
                                resp.add(new Integer(-1));
1528
                        } else {
1529
                                resp.add(new Integer(cont_by));
1530
                        }
1531
                }
1532

    
1533
                int size = resp.size();
1534
                int[] _resp = new int[size];
1535

    
1536
                for (int i = 0; i < size; i++) {
1537
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1538
                }
1539

    
1540
                return _resp;
1541
        }
1542

    
1543
        private static List getHolesOf(int ind, int[] final_contn, List all) {
1544
                List<Integer> resp_ind = new ArrayList<Integer>();
1545

    
1546
                for (int i = 0; i < final_contn.length; i++) {
1547
                        if (final_contn[i] == ind) {
1548
                                resp_ind.add(new Integer(i));
1549
                        }
1550
                }
1551

    
1552
                List resp = new ArrayList();
1553

    
1554
                for (int i = 0; i < resp_ind.size(); i++) {
1555
                        Integer aux = (Integer) resp_ind.get(i);
1556
                        resp.add(all.get(aux.intValue()));
1557
                }
1558

    
1559
                return resp;
1560
        }
1561

    
1562
        private static List getShellsIn(int[] final_contn, List all) {
1563
                List resp_ind = new ArrayList();
1564

    
1565
                for (int i = 0; i < final_contn.length; i++) {
1566
                        if (final_contn[i] == -1) {
1567
                                resp_ind.add(new Integer(i));
1568
                        }
1569
                }
1570

    
1571
                List resp = new ArrayList();
1572

    
1573
                for (int i = 0; i < resp_ind.size(); i++) {
1574
                        Integer aux = (Integer) resp_ind.get(i);
1575
                        resp.add(all.get(aux.intValue()));
1576
                }
1577

    
1578
                return resp;
1579
        }
1580

    
1581
        /**
1582
         * This method tries to guess who is a shell and who is a hole from a set of
1583
         * linestrings.
1584
         * 
1585
         * @param all_ls
1586
         *            a set of linestrings to be checked.
1587
         * 
1588
         * @return a 2-item array. the first is an arraylist of linestrings thought
1589
         *         to be shells. the second is an array of arraylists containing the
1590
         *         holes of each shell found in the first item
1591
         * 
1592
         */
1593
        public static Object[] getHolesForShells(List all_ls) {
1594
                int no_of_ls = all_ls.size();
1595
                int[] containedby = new int[no_of_ls];
1596
                int[] shells;
1597
                int[] holes;
1598
                int[] final_cont;
1599

    
1600
                for (int i = 0; i < no_of_ls; i++) {
1601
                        LineString3D ls_aux = (LineString3D) all_ls.get(i);
1602
                        containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1603
                }
1604

    
1605
                shells = getIndicesOfShells(containedby);
1606
                holes = getIndicesOfHoles(containedby, shells);
1607
                final_cont = getFinalContainings(containedby, holes);
1608

    
1609
                // true shells:
1610
                shells = getIndicesOfShells(final_cont);
1611

    
1612
                List resp_shells = new ArrayList();
1613
                List resp_holes_for_shells = new ArrayList();
1614
                List aux_holes;
1615

    
1616
                for (int i = 0; i < shells.length; i++) {
1617
                        resp_shells.add(all_ls.get(shells[i]));
1618
                        aux_holes = getHolesOf(i, final_cont, all_ls);
1619
                        resp_holes_for_shells.add(aux_holes);
1620
                }
1621

    
1622
                Object[] _resp = new Object[2];
1623
                _resp[0] = resp_shells;
1624
                _resp[1] = resp_holes_for_shells;
1625

    
1626
                return _resp;
1627
        }
1628

    
1629
        private static int getTotalSize(List listOfLists) {
1630
                int resp = 0;
1631

    
1632
                for (int i = 0; i < listOfLists.size(); i++) {
1633
                        resp = resp + ((List) listOfLists.get(i)).size();
1634
                }
1635

    
1636
                return resp;
1637
        }
1638

    
1639
        // private static STRUCT // private static ArrayList
1640
        // getPolygonsEasily(FShape mpolygon) {
1641
        private static STRUCT multiPolygonAsStruct(MultiSurface2D mpol, int srid,
1642
                        boolean threed, Connection _conn, boolean agu_bien, boolean hasSrid)
1643
                        throws SQLException {
1644
                List<LineString3D> all_ls = getPolygonsEasily(mpol);
1645
                Object[] hs = getHolesForShells(all_ls);
1646
                List sh = (List) hs[0];
1647
                List _ho = (List) hs[1];
1648
                List ho = reverseHoles(_ho);
1649

    
1650
                return getMultiPolygonAsStruct(sh, ho, srid, threed, _conn, agu_bien,
1651
                                hasSrid);
1652
        }
1653

    
1654
        private static List reverseHoles(List hh) {
1655
                List resp = new ArrayList();
1656

    
1657
                for (int i = 0; i < hh.size(); i++) {
1658
                        List item = (List) hh.get(i);
1659
                        List newitem = new ArrayList();
1660

    
1661
                        for (int j = 0; j < item.size(); j++) {
1662
                                LineString3D ls = (LineString3D) item.get(j);
1663
                                newitem.add(ls.createReverse());
1664
                        }
1665

    
1666
                        resp.add(newitem);
1667
                }
1668

    
1669
                return resp;
1670
        }
1671

    
1672
        private static STRUCT getMultiPolygonAsStruct(List<LineString3D> shells,
1673
                        List<List<LineString3D>> holes, int srid, boolean threed,
1674
                        Connection _conn, boolean explicito, boolean hasSrid)
1675
                        throws SQLException {
1676
                int t = 1003;
1677

    
1678
                if (explicito) {
1679
                        t = 2003;
1680
                }
1681

    
1682
                int size = shells.size() + getTotalSize(holes);
1683
                int geotype = 2003;
1684
                if (size > 1)
1685
                        geotype = 2007;
1686

    
1687
                int dim = 2;
1688

    
1689
                if (threed) {
1690
                        geotype = geotype + 1000;
1691
                        dim = 3;
1692
                }
1693

    
1694
                NUMBER[] indices = new NUMBER[3 * size];
1695

    
1696
                int acum = 0;
1697
                int start_ind = 0;
1698

    
1699
                for (int i = 0; i < shells.size(); i++) {
1700
                        indices[start_ind] = new NUMBER(acum + 1);
1701
                        indices[start_ind + 1] = new NUMBER(1003);
1702
                        indices[start_ind + 2] = new NUMBER(1);
1703
                        start_ind = start_ind + 3;
1704
                        acum = acum
1705
                                        + (dim * ((LineString3D) shells.get(i)).getLs()
1706
                                                        .getNumPoints());
1707

    
1708
                        List<LineString3D> item_holes = (List<LineString3D>) holes.get(i);
1709

    
1710
                        for (int j = 0; j < item_holes.size(); j++) {
1711
                                indices[start_ind] = new NUMBER(acum + 1);
1712
                                indices[start_ind + 1] = new NUMBER(t); // 1003
1713
                                indices[start_ind + 2] = new NUMBER(1);
1714
                                start_ind = start_ind + 3;
1715
                                acum = acum
1716
                                                + (dim * ((LineString3D) item_holes.get(j)).getLs()
1717
                                                                .getNumPoints());
1718
                        }
1719
                }
1720

    
1721
                int _ind = 0;
1722
                NUMBER[] ords = new NUMBER[acum];
1723

    
1724
                for (int i = 0; i < shells.size(); i++) {
1725
                        // --------------------------------
1726
                        LineString3D ls = (LineString3D) shells.get(i);
1727
                        int num_p = ls.getLs().getNumPoints();
1728

    
1729
                        for (int j = 0; j < num_p; j++) {
1730
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1731
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1732

    
1733
                                if (threed) {
1734
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1735
                                }
1736

    
1737
                                _ind = _ind + dim;
1738
                        }
1739

    
1740
                        // -------------------------------
1741
                        List<LineString3D> item_holes = (List<LineString3D>) holes.get(i);
1742

    
1743
                        for (int j = 0; j < item_holes.size(); j++) {
1744
                                ls = (LineString3D) item_holes.get(j);
1745
                                num_p = ls.getLs().getNumPoints();
1746

    
1747
                                for (int k = 0; k < num_p; k++) {
1748
                                        ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
1749
                                        ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1750

    
1751
                                        if (threed) {
1752
                                                ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1753
                                        }
1754

    
1755
                                        _ind = _ind + dim;
1756
                                }
1757
                        }
1758
                }
1759

    
1760
                STRUCT resp;
1761
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1762
                                "MDSYS.SDO_GEOMETRY", _conn);
1763
                Object[] obj = new Object[5];
1764
                obj[0] = new NUMBER(geotype);
1765

    
1766
                if (hasSrid) {
1767
                        obj[1] = new NUMBER(srid);
1768
                } else {
1769
                        obj[1] = null;
1770
                }
1771

    
1772
                obj[2] = null;
1773
                obj[3] = indices;
1774
                obj[4] = ords;
1775

    
1776
                // String ind_str = printArray(indices);
1777
                // String ord_str = printArray(ords);
1778
                resp = new STRUCT(dsc, _conn, obj);
1779

    
1780
                return resp;
1781
        }
1782

    
1783
        /**
1784
         * 
1785
         * @param array
1786
         * @return
1787
         */
1788
        public static String printArray(NUMBER[] array) {
1789
                String resp = "[ ";
1790

    
1791
                for (int i = 0; i < array.length; i++) {
1792
                        resp = resp + " " + array[i].doubleValue() + " , ";
1793
                }
1794

    
1795
                resp = resp.substring(0, resp.length() - 2) + "]";
1796

    
1797
                return resp;
1798
        }
1799

    
1800
        /**
1801
         * 
1802
         * @param ind
1803
         * @param list
1804
         * @return
1805
         */
1806
        private static boolean isOneOf(int ind, int[] list) {
1807
                for (int i = 0; i < list.length; i++) {
1808
                        if (list[i] == ind) {
1809
                                return true;
1810
                        }
1811
                }
1812

    
1813
                return false;
1814
        }
1815

    
1816
        /**
1817
         * This method appends the geometries from a geometry collection in one
1818
         * STRUCT.
1819
         * 
1820
         * @param co
1821
         *            the geometry collection
1822
         * @param _forced_type
1823
         *            a type that has to be used as the struct's main type
1824
         * @param _conn
1825
         *            the connection
1826
         * @param _o_srid
1827
         *            the geometry's SRS (oracle code)
1828
         * @param withSrid
1829
         *            whether the SRS is non-NULL
1830
         * @param agu_bien
1831
         *            whether to check holes' validity
1832
         * @param _isGeoCS
1833
         *            whether the SRS is geodetic
1834
         * @return the STRUCT with the appended geometries
1835
         */
1836
        public static STRUCT appendGeometriesInStruct(Aggregate co,
1837
                        int _forced_type, Connection _conn, String _o_srid,
1838
                        boolean withSrid, boolean agu_bien, boolean _isGeoCS) {
1839

    
1840
                Geometry[] geoms = new Geometry[co.getPrimitivesNumber()];
1841
                for (int i = 0; i < co.getPrimitivesNumber(); i++) {
1842
                        geoms[i] = co.getPrimitiveAt(i);
1843
                }
1844

    
1845
                STRUCT[] sts = new STRUCT[co.getPrimitivesNumber()];
1846

    
1847
                for (int i = 0; i < co.getPrimitivesNumber(); i++) {
1848
                        sts[i] = geometryToSTRUCT(geoms[i], _forced_type, _conn, _o_srid,
1849
                                        withSrid, agu_bien, _isGeoCS);
1850
                }
1851

    
1852
                if (co.getPrimitivesNumber() == 1) {
1853
                        return sts[0];
1854
                }
1855

    
1856
                STRUCT aux = sts[0];
1857

    
1858
                for (int i = 1; i < co.getPrimitivesNumber(); i++) {
1859
                        aux = appendStructs(aux, sts[i], _conn);
1860
                }
1861

    
1862
                return aux;
1863
        }
1864

    
1865
        /**
1866
         * 
1867
         * @param st1
1868
         * @param st2
1869
         * @param _conn
1870
         * @return
1871
         */
1872
        private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection _conn) {
1873
                try {
1874
                        ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1875
                        int length_of_head_ords = _ords.getOracleArray().length;
1876

    
1877
                        NUMBER gtype = new NUMBER(
1878
                                        4 + (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1879
                        NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1880
                        NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1881

    
1882
                        ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1883
                        ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1884
                        ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1885
                        ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1886

    
1887
                        Datum[] info = appendDatumArrays(info1.getOracleArray(), info2
1888
                                        .getOracleArray(), length_of_head_ords);
1889

    
1890
                        Datum[] ords = appendDatumArrays(ords1.getOracleArray(), ords2
1891
                                        .getOracleArray(), 0);
1892

    
1893
                        StructDescriptor dsc = st1.getDescriptor();
1894

    
1895
                        Object[] atts = new Object[5];
1896
                        atts[0] = gtype;
1897
                        atts[1] = srid;
1898
                        atts[2] = middle;
1899
                        atts[3] = info;
1900
                        atts[4] = ords;
1901

    
1902
                        STRUCT resp = new STRUCT(dsc, _conn, atts);
1903

    
1904
                        return resp;
1905
                } catch (SQLException sqle) {
1906
                        logger.error("While appending structs: " + sqle.getMessage(), sqle);
1907
                }
1908

    
1909
                return null;
1910
        }
1911

    
1912
        /**
1913
         * 
1914
         * @param head
1915
         * @param tail
1916
         * @param offset
1917
         * @return
1918
         */
1919
        private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
1920
                        int offset) {
1921
                int head_l = head.length;
1922
                int tail_l = tail.length;
1923
                Datum[] resp = new Datum[head_l + tail_l];
1924

    
1925
                for (int i = 0; i < head_l; i++)
1926
                        resp[i] = head[i];
1927

    
1928
                if (offset == 0) {
1929
                        for (int i = 0; i < tail_l; i++)
1930
                                resp[head_l + i] = tail[i];
1931
                } else {
1932
                        try {
1933
                                for (int i = 0; i < tail_l; i++) {
1934
                                        if ((i % 3) == 0) {
1935
                                                resp[head_l + i] = new NUMBER(tail[i].intValue()
1936
                                                                + offset);
1937
                                        } else {
1938
                                                resp[head_l + i] = tail[i];
1939
                                        }
1940
                                }
1941
                        } catch (SQLException se) {
1942
                                logger.error("Unexpected error: " + se.getMessage());
1943
                        }
1944
                }
1945

    
1946
                return resp;
1947
        }
1948

    
1949
        /**
1950
         * Utility method to get an ineteger as a formatted string.
1951
         * 
1952
         * @param n
1953
         *            the integer
1954
         * @return the formatted string
1955
         */
1956
        public static String getFormattedInteger(int n) {
1957
                df.setGroupingUsed(true);
1958
                df.setGroupingSize(3);
1959
                dfs.setGroupingSeparator('.');
1960
                df.setDecimalFormatSymbols(dfs);
1961

    
1962
                return df.format(n);
1963
        }
1964

    
1965
        /**
1966
         * Tells whether these arrays belong to a rectangle polygon.
1967
         * 
1968
         * @param info
1969
         *            the struct's element info array
1970
         * @param ords
1971
         *            the struct's coordinate array
1972
         * @return true if it is a rectangle polygon. false otherwise.
1973
         */
1974
        public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
1975
                try {
1976
                        int[] infos = info.getIntArray();
1977

    
1978
                        return ((infos[2] == 3) && (infos.length == 3));
1979
                } catch (SQLException se) {
1980
                        logger.error("While ckecking rectangle: " + se.getMessage(), se);
1981
                }
1982

    
1983
                return false;
1984
        }
1985

    
1986
        /**
1987
         * Utility method to deal with oracle info arrays.
1988
         */
1989
        public static ARRAY getDevelopedInfoArray(ARRAY info) {
1990
                ARRAY _resp = null;
1991

    
1992
                try {
1993
                        Datum[] resp = new Datum[3];
1994
                        Datum[] in = info.getOracleArray();
1995
                        resp[0] = in[0];
1996
                        resp[1] = in[1];
1997
                        resp[2] = new NUMBER(1);
1998
                        _resp = new ARRAY(info.getDescriptor(), info
1999
                                        .getInternalConnection(), resp);
2000
                } catch (SQLException se) {
2001
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
2002
                }
2003

    
2004
                return _resp;
2005
        }
2006

    
2007
        /**
2008
         * Utility method to deal with oracle coordinate arrays.
2009
         */
2010
        public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
2011
                ARRAY _resp = null;
2012

    
2013
                try {
2014
                        Datum[] resp = new Datum[10];
2015
                        Datum[] corners = ords.getOracleArray();
2016

    
2017
                        // x
2018
                        resp[0] = corners[0];
2019
                        resp[2] = corners[2];
2020
                        resp[4] = corners[2];
2021
                        resp[6] = corners[0];
2022
                        resp[8] = corners[0];
2023

    
2024
                        // y
2025
                        resp[1] = corners[1];
2026
                        resp[3] = corners[1];
2027
                        resp[5] = corners[3];
2028
                        resp[7] = corners[3];
2029
                        resp[9] = corners[1];
2030
                        _resp = new ARRAY(ords.getDescriptor(), ords
2031
                                        .getInternalConnection(), resp);
2032
                } catch (SQLException se) {
2033
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
2034
                }
2035

    
2036
                return _resp;
2037
        }
2038

    
2039
        /**
2040
         * utility method to convert a STRUCT into a GeneralPathX
2041
         * 
2042
         * @param aux
2043
         *            the struct's datum array
2044
         * @return the GeneralPathX instance created
2045
         */
2046
        public static GeneralPathX structToGPX(Datum[] aux) {
2047
                GeneralPathX resp = new GeneralPathX();
2048
                ARRAY infoARRAY = null;
2049
                ARRAY ordsARRAY = null;
2050
                Datum[] info_array = null;
2051
                Datum[] ords_array = null;
2052
                int info_array_size = 0;
2053
                int[] start_ind;
2054
                int[] end_ind;
2055
                int dims = 0;
2056
                boolean next_must_do_first = true;
2057

    
2058
                try {
2059
                        infoARRAY = (ARRAY) aux[3];
2060
                        ordsARRAY = (ARRAY) aux[4];
2061

    
2062
                        if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
2063
                                infoARRAY = getDevelopedInfoArray(infoARRAY);
2064
                                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
2065
                        }
2066

    
2067
                        dims = ((NUMBER) aux[0]).intValue() / 1000;
2068

    
2069
                        if (dims == 0) {
2070
                                dims = 2;
2071
                        }
2072

    
2073
                        info_array = (Datum[]) infoARRAY.getOracleArray();
2074
                        ords_array = (Datum[]) ordsARRAY.getOracleArray();
2075
                        info_array_size = info_array.length / 3;
2076

    
2077
                        int last_index = ords_array.length - dims + 1;
2078

    
2079
                        // set indices:
2080
                        start_ind = new int[info_array_size];
2081
                        end_ind = new int[info_array_size];
2082

    
2083
                        for (int i = 0; i < info_array_size; i++)
2084
                                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
2085

    
2086
                        for (int i = 0; i < (info_array_size - 1); i++)
2087
                                end_ind[i] = start_ind[i + 1] - 1;
2088

    
2089
                        end_ind[info_array_size - 1] = last_index;
2090

    
2091
                        int lineType = PathIterator.SEG_LINETO;
2092

    
2093
                        if (end_ind[0] == 0) { // collection of paths
2094

    
2095
                                for (int i = 1; i < info_array_size; i++) {
2096
                                        lineType = getLineToType(info_array, i);
2097

    
2098
                                        // -----------------------
2099
                                        if (end_ind[i] == (start_ind[i] - 1))
2100
                                                lineType = PathIterator.SEG_MOVETO;
2101
                                        // -----------------------
2102

    
2103
                                        next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
2104
                                                        end_ind[i] - 1, ords_array, dims, lineType,
2105
                                                        (i == 1) || (lineType == PathIterator.SEG_MOVETO),
2106
                                                        next_must_do_first);
2107
                                }
2108
                        } else {
2109
                                // standard case, do the moveto always
2110
                                for (int i = 0; i < info_array_size; i++) {
2111
                                        lineType = getLineToType(info_array, i);
2112
                                        addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1,
2113
                                                        ords_array, dims, lineType, true, true);
2114
                                }
2115
                        }
2116

    
2117
                        // boolean do_the_moves = true;
2118
                } catch (SQLException se) {
2119
                        logger.error("While creating GPX: " + se.getMessage(), se);
2120
                }
2121

    
2122
                return resp;
2123
        }
2124

    
2125
        /**
2126
         * 
2127
         * @param infos
2128
         * @param i
2129
         * @return
2130
         */
2131
        private static int getLineToType(Datum[] infos, int i) {
2132
                int resp = PathIterator.SEG_LINETO;
2133

    
2134
                try {
2135
                        if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) {
2136
                                resp = PathIterator.SEG_QUADTO;
2137
                        }
2138
                } catch (SQLException e) {
2139
                        logger.error("While getting line-to type: " + e.getMessage()
2140
                                        + " (returned SEG_LINETO)");
2141
                }
2142

    
2143
                return resp;
2144
        }
2145

    
2146
        /**
2147
         * 
2148
         * @param gpx
2149
         * @param zero_based_start
2150
         * @param zero_based_include_end
2151
         * @param ords
2152
         * @param d
2153
         * @param ltype
2154
         * @param do_the_move
2155
         * @param must_do_first
2156
         * @return
2157
         */
2158
        private static boolean addOrdsToGPX(GeneralPathX gpx, int zero_based_start,
2159
                        int zero_based_include_end, Datum[] ords, int d, int ltype,
2160
                        boolean do_the_move, boolean must_do_first) {
2161
                int length = ords.length;
2162
                boolean return_following_must_do_first = true;
2163

    
2164
                double x = ((NUMBER) ords[zero_based_start]).doubleValue();
2165
                double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
2166

    
2167
                if (must_do_first) {
2168
                        if (do_the_move) {
2169
                                gpx.moveTo(x, y);
2170
                        } else {
2171
                                gpx.lineTo(x, y);
2172
                        }
2173
                }
2174

    
2175
                int ind = 1;
2176

    
2177
                int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2178
                int indx;
2179
                int indx2;
2180

    
2181
                if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2182

    
2183
                        double x2;
2184
                        double y2;
2185

    
2186
                        while (ind < size) {
2187
                                indx = zero_based_start + (ind * d);
2188
                                x = ((NUMBER) ords[indx]).doubleValue();
2189
                                y = ((NUMBER) ords[indx + 1]).doubleValue();
2190

    
2191
                                indx2 = zero_based_start + ((ind + 1) * d);
2192

    
2193
                                if (indx >= length) {
2194
                                        indx2 = zero_based_start;
2195
                                }
2196

    
2197
                                x2 = ((NUMBER) ords[indx2]).doubleValue();
2198
                                y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
2199
                                gpx.quadTo(x, y, x2, y2);
2200
                                ind++;
2201
                                ind++;
2202
                        }
2203

    
2204
                        return_following_must_do_first = false;
2205
                } else { // PathIterator.SEG_LINETO (interpretation = 1)
2206

    
2207
                        while (ind < size) {
2208
                                indx = zero_based_start + (ind * d);
2209
                                x = ((NUMBER) ords[indx]).doubleValue();
2210
                                y = ((NUMBER) ords[indx + 1]).doubleValue();
2211
                                gpx.lineTo(x, y);
2212
                                ind++;
2213
                        }
2214
                }
2215

    
2216
                return return_following_must_do_first;
2217
        }
2218

    
2219
        /**
2220
         * Utility method. Gets FShape type from oracle geometry type.
2221
         * 
2222
         * @param otype
2223
         * @return FShape type
2224
         */
2225
        public static int oracleGTypeToFShapeType(int otype) {
2226
                switch (otype) {
2227
                case ORACLE_GTYPE_UNKNOWN:
2228
                        return Geometry.TYPES.NULL;
2229

    
2230
                case ORACLE_GTYPE_POINT:
2231
                case ORACLE_GTYPE_MULTIPOINT:
2232
                        return Geometry.TYPES.POINT;
2233

    
2234
                case ORACLE_GTYPE_LINE:
2235
                case ORACLE_GTYPE_MULTILINE:
2236
                        return Geometry.TYPES.CURVE;
2237

    
2238
                case ORACLE_GTYPE_POLYGON:
2239
                case ORACLE_GTYPE_MULTIPOLYGON:
2240
                        return Geometry.TYPES.SURFACE;
2241

    
2242
                case ORACLE_GTYPE_COLLECTION:
2243
                        return Geometry.TYPES.AGGREGATE;
2244
                }
2245

    
2246
                logger.warn("Unknown oracle geometry type: " + otype);
2247

    
2248
                return Geometry.TYPES.NULL;
2249
        }
2250

    
2251
        /**
2252
         * Utility method to get struct's type.
2253
         * 
2254
         * @param the_data
2255
         *            the struct's datum array
2256
         * @return the struct type
2257
         */
2258
        public static int getStructType(Datum[] the_data) {
2259
                int resp = -1;
2260

    
2261
                try {
2262
                        resp = ((NUMBER) the_data[0]).intValue() % 1000;
2263
                } catch (SQLException se) {
2264
                        logger.error("Error: " + se.getMessage(), se);
2265
                }
2266

    
2267
                return resp;
2268
        }
2269

    
2270
        /**
2271
         * Utility method to get struct's SRID.
2272
         * 
2273
         * @param the_data
2274
         *            the struct's datum array
2275
         * @return the struct0's SRID
2276
         */
2277
        public static int getStructSRID(Datum[] the_data) {
2278
                int resp = -1;
2279

    
2280
                try {
2281
                        resp = ((NUMBER) the_data[1]).intValue();
2282
                } catch (SQLException se) {
2283
                        logger.error("Error: " + se.getMessage(), se);
2284
                }
2285

    
2286
                return resp;
2287
        }
2288

    
2289
        /**
2290
         * Utility method to find out if a struct is a circle.
2291
         * 
2292
         * @param the_data
2293
         *            the struct's datum array
2294
         * @return whether it is a circle
2295
         */
2296
        public static boolean isCircle(Datum[] the_data) {
2297
                int[] info = null;
2298

    
2299
                try {
2300
                        info = ((ARRAY) the_data[3]).getIntArray();
2301
                } catch (SQLException se) {
2302
                        logger.error("While cheking circle: " + se.getMessage(), se);
2303

    
2304
                        return false;
2305
                }
2306

    
2307
                if (info == null) {
2308
                        return false;
2309
                }
2310

    
2311
                boolean resp = ((info.length == 3) && (info[2] == 4));
2312

    
2313
                return resp;
2314
        }
2315

    
2316
        /**
2317
         * Gets the struct's dimension size.
2318
         * 
2319
         * @param st
2320
         *            the struct
2321
         * @return the structs dimension
2322
         */
2323
        public static int getStructDimensions(STRUCT st) {
2324
                int resp = -1;
2325

    
2326
                try {
2327
                        resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2328
                } catch (SQLException se) {
2329
                        logger.error("Error: " + se.getMessage(), se);
2330
                }
2331

    
2332
                if (resp < 2) {
2333
                        resp = 2;
2334
                }
2335

    
2336
                return resp;
2337
        }
2338

    
2339
        /**
2340
         * Gets a struct's coordinates array.
2341
         * 
2342
         * @param the_data
2343
         *            the struct's datum array
2344
         * @return the coordinates array
2345
         */
2346
        public static double[] getOrds(Datum[] the_data) {
2347
                double[] resp = null;
2348

    
2349
                try {
2350
                        ARRAY aux = (ARRAY) the_data[4];
2351

    
2352
                        if (aux == null) {
2353
                                return null;
2354
                        }
2355

    
2356
                        resp = aux.getDoubleArray();
2357
                } catch (SQLException se) {
2358
                        logger.error("While getting ordinates: " + se.getMessage(), se);
2359
                }
2360

    
2361
                return resp;
2362
        }
2363

    
2364
        /**
2365
         * Utility method to create a struct with the given data.
2366
         * 
2367
         * @param type
2368
         *            struct type
2369
         * @param srid
2370
         *            coordinate system
2371
         * @param info
2372
         *            element info array
2373
         * @param ords
2374
         *            coordinates array
2375
         * @param conn
2376
         *            connection
2377
         * @return the created struct
2378
         */
2379
        public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info,
2380
                        Datum[] ords, Connection conn) {
2381
                try {
2382
                        StructDescriptor dsc = StructDescriptor.createDescriptor(
2383
                                        "MDSYS.SDO_GEOMETRY", conn);
2384
                        Object[] obj = new Object[5];
2385
                        obj[0] = type;
2386
                        obj[1] = srid;
2387
                        obj[2] = null;
2388
                        obj[3] = info;
2389
                        obj[4] = ords;
2390

    
2391
                        return new STRUCT(dsc, conn, obj);
2392
                } catch (SQLException se) {
2393
                        logger.error("While creating STRUCT: " + se.getMessage(), se);
2394
                }
2395

    
2396
                return null;
2397
        }
2398

    
2399
        /**
2400
         * 
2401
         * @param dim_info
2402
         * @return
2403
         */
2404
        public static String getDimInfoAsString(ARRAY dim_info) {
2405
                String resp = "DIMENSIONS: ";
2406

    
2407
                if (dim_info == null) {
2408
                        return "NULL" + "\n";
2409
                } else {
2410
                        try {
2411
                                Datum[] da = dim_info.getOracleArray();
2412
                                int size = da.length;
2413
                                resp = resp + size + "\n";
2414
                                for (int i = 0; i < size; i++) {
2415
                                        STRUCT dim_itemx = (STRUCT) da[i];
2416
                                        Object[] dim_desc = dim_itemx.getAttributes();
2417
                                        resp = resp + "DIMENSION " + i + ": " + ", NAME: "
2418
                                                        + dim_desc[0].toString() + ", MIN: "
2419
                                                        + dim_desc[1].toString() + ", MAX: "
2420
                                                        + dim_desc[2].toString() + ", TOL: "
2421
                                                        + dim_desc[3].toString();
2422
                                        if (i != (size - 1)) {
2423
                                                resp = resp + "\n";
2424
                                        }
2425
                                }
2426
                        } catch (Exception ex) {
2427
                                return "ERROR: " + ex.getMessage() + "\n";
2428
                        }
2429
                }
2430
                return resp;
2431
        }
2432

    
2433
        /**
2434
         * 
2435
         * @param conn
2436
         * @param fromStruct
2437
         * @param toSrid
2438
         * @return
2439
         */
2440
        public static STRUCT reprojectGeometry(Connection conn, STRUCT fromStruct,
2441
                        String toSrid) {
2442

    
2443
                String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2444
                STRUCT resp = null;
2445

    
2446
                try {
2447
                        PreparedStatement _st = conn.prepareStatement(qry);
2448
                        _st.setObject(1, fromStruct);
2449
                        ResultSet _rs = _st.executeQuery();
2450

    
2451
                        if (_rs.next()) {
2452
                                resp = (STRUCT) _rs.getObject(1);
2453
                        } else {
2454
                                logger
2455
                                                .error("While executing reprojection: empty resultset (?)");
2456
                                return fromStruct;
2457
                        }
2458
                } catch (Exception ex) {
2459
                        logger.error("While reprojecting: " + ex.getMessage());
2460
                        return fromStruct;
2461
                }
2462

    
2463
                if (resp == null) {
2464
                        return fromStruct;
2465
                } else {
2466
                        return resp;
2467
                }
2468
        }
2469

    
2470
        /**
2471
         * Utility method. Gets FShape type from oracle geometry type.
2472
         * 
2473
         * @param otype
2474
         * @return FShape type
2475
         */
2476
        public static int oracleGTypeToGvsigGeometryType(int otype, boolean complex) {
2477

    
2478
                int resp = Geometry.TYPES.NULL;
2479

    
2480
                if (complex) {
2481

    
2482
                        switch (otype) {
2483
                        case OracleValues.ORACLE_GTYPE_COMPLEX_VOIDED_POLYON:
2484
                        case OracleValues.ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON:
2485
                                resp = Geometry.TYPES.SURFACE;
2486
                                break;
2487
                        case OracleValues.ORACLE_GTYPE_COMPLEX_COMPOUND_LINE:
2488
                                resp = Geometry.TYPES.CURVE;
2489
                                break;
2490
                        }
2491

    
2492
                } else {
2493

    
2494
                        // =========== not complex =================
2495
                        switch (otype) {
2496
                        case OracleValues.ORACLE_GTYPE_UNKNOWN:
2497
                                resp = Geometry.TYPES.NULL;
2498
                                break;
2499

    
2500
                        case OracleValues.ORACLE_GTYPE_POINT:
2501
                        case OracleValues.ORACLE_GTYPE_MULTIPOINT:
2502
                                resp = Geometry.TYPES.POINT;
2503
                                break;
2504

    
2505
                        case OracleValues.ORACLE_GTYPE_LINE:
2506
                        case OracleValues.ORACLE_GTYPE_MULTILINE:
2507
                                resp = Geometry.TYPES.CURVE;
2508
                                break;
2509

    
2510
                        case OracleValues.ORACLE_GTYPE_POLYGON:
2511
                        case OracleValues.ORACLE_GTYPE_MULTIPOLYGON:
2512
                                resp = Geometry.TYPES.SURFACE;
2513
                                break;
2514

    
2515
                        case OracleValues.ORACLE_GTYPE_COLLECTION:
2516
                                resp = Geometry.TYPES.GEOMETRY;
2517
                                break;
2518
                        }
2519
                        // =========== not complex =================
2520
                }
2521

    
2522
                if (resp == Geometry.TYPES.NULL) {
2523
                        logger.error("Unknown oracle geometry type: " + otype);
2524
                }
2525
                return resp;
2526
        }
2527

    
2528
        /**
2529
         * 
2530
         * @param name
2531
         * @param arr
2532
         * @return
2533
         */
2534
        private static boolean isOneOfThese(String name, String[] arr) {
2535

    
2536
                for (int i = 0; i < arr.length; i++) {
2537
                        if (arr[i].compareToIgnoreCase(name) == 0)
2538
                                return true;
2539
                }
2540
                return false;
2541
        }
2542

    
2543
        /**
2544
         * 
2545
         * @param tt
2546
         * @param are_dims
2547
         * @return
2548
         */
2549
        public static boolean hasSeveralGeometryTypes(ArrayList tt, boolean are_dims) {
2550
                if (tt.size() == 0) {
2551
                        return false;
2552
                }
2553

    
2554
                HashMap m = new HashMap();
2555

    
2556
                for (int i = 0; i < tt.size(); i++) {
2557
                        Integer integ = (Integer) tt.get(i);
2558
                        int val = integ.intValue();
2559

    
2560
                        if ((val == 4) && (!are_dims)) {
2561
                                return true;
2562
                        }
2563

    
2564
                        m.put("" + (val % 4), "a type");
2565
                }
2566

    
2567
                Iterator iter = m.keySet().iterator();
2568
                iter.next();
2569

    
2570
                return iter.hasNext();
2571
        }
2572

    
2573
        /**
2574
         * 
2575
         * @param input
2576
         * @param ind
2577
         * @param n
2578
         * @return
2579
         */
2580
        private static double[] getIndDoublesModule(double[] input, int ind, int n) {
2581
                int size = input.length / n;
2582
                double[] resp = new double[size];
2583

    
2584
                for (int i = 0; i < size; i++) {
2585
                        resp[i] = input[(i * n) + ind];
2586
                }
2587

    
2588
                return resp;
2589
        }
2590

    
2591
        /**
2592
         * 
2593
         * @param input
2594
         * @param ind
2595
         * @param n
2596
         * @return
2597
         */
2598
        private static double[] getIndBigDecimalModule(double[] input, int ind,
2599
                        int n) {
2600
                int size = input.length / n;
2601
                double[] resp = new double[size];
2602

    
2603
                for (int i = 0; i < size; i++) {
2604
                        resp[i] = input[(i * n) + ind];
2605
                }
2606

    
2607
                return resp;
2608
        }
2609

    
2610
        /**
2611
         * 
2612
         * @param the_data
2613
         * @param dim
2614
         * @return
2615
         */
2616
        public static Geometry getFMapGeometryMultipolygon(Datum[] the_data, int dim) {
2617
                Geometry ig = null;
2618

    
2619
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2620

    
2621
                if (OracleUtils.isCircle(the_data)) {
2622
                        ig = getCircleFromStruct(the_data);
2623
                } else {
2624
                        GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2625

    
2626
                        try {
2627
                                if (dim == 2) {
2628
                                        ig = geomManager.createSurface(gpx,
2629
                                                        Geometry.SUBTYPES.GEOM2D);
2630
                                } else {
2631
                                        double[] ords = null;
2632

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

    
2640
                                        double[] z = getIndBigDecimalModule(ords, 2, dim);
2641

    
2642
                                        ig = geomManager.createSurface(gpx,
2643
                                                        Geometry.SUBTYPES.GEOM2DZ);
2644
                                        for (int i = 0; i < z.length; i++) {
2645
                                                ((Surface2DZ) ig).setCoordinateAt(i, dim, z[i]);
2646
                                        }
2647

    
2648
                                }
2649

    
2650
                        } catch (CreateGeometryException e) {
2651
                                e.printStackTrace();
2652
                                return null;
2653
                        }
2654
                }
2655

    
2656
                return ig;
2657
        }
2658

    
2659
        /**
2660
         * 
2661
         * @param the_data
2662
         * @return
2663
         */
2664
        private static Geometry getCircleFromStruct(Datum[] the_data) {
2665
                double[] threep = null;
2666
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2667

    
2668
                try {
2669
                        threep = ((ARRAY) the_data[4]).getDoubleArray();
2670
                } catch (SQLException se) {
2671
                        logger.error("While getting ords from struct: " + se.getMessage(),
2672
                                        se);
2673

    
2674
                        try {
2675
                                return geomManager
2676
                                                .createNullGeometry(Geometry.SUBTYPES.UNKNOWN);
2677
                        } catch (CreateGeometryException e) {
2678
                                // TODO Auto-generated catch block
2679
                                e.printStackTrace();
2680
                        }
2681
                }
2682

    
2683
                Point2D[] three = new Point2D.Double[3];
2684
                three[0] = new Point2D.Double(threep[0], threep[1]);
2685
                three[1] = new Point2D.Double(threep[2], threep[3]);
2686
                three[2] = new Point2D.Double(threep[4], threep[5]);
2687

    
2688
                Object[] cent_rad = OracleUtils.getCenterAndRadiousOfCirc(three);
2689

    
2690
                Point2D cent = (Point2D) cent_rad[0];
2691
                double radius = ((Double) cent_rad[1]).doubleValue();
2692

    
2693
                Geometry circ = null;
2694
                try {
2695
                        circ = geomManager.create(Geometry.TYPES.CIRCLE,
2696
                                        Geometry.SUBTYPES.GEOM2D);
2697
                        ((Circle2D) circ).setPoints(cent, radius);
2698
                } catch (CreateGeometryException e) {
2699
                        e.printStackTrace();
2700
                        return null;
2701
                }
2702
                return circ;
2703
        }
2704

    
2705
        /**
2706
         * 
2707
         * @param the_data
2708
         * @param dim
2709
         * @return
2710
         */
2711
        public static Geometry getFMapGeometryMultiLineString(Datum[] the_data,
2712
                        int dim) {
2713
                GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2714
                Geometry ig = null;
2715
                double[] ords = null;
2716

    
2717
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2718

    
2719
                try {
2720
                        if (dim == 2) {
2721
                                ig = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM2D);
2722
                        } else {
2723
                                ords = OracleUtils.getOrds(the_data);
2724

    
2725
                                double[] z = getIndBigDecimalModule(ords, 2, dim);
2726
                                ig = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM2DZ);
2727
                                ((Curve2DZ) ig).setGeneralPath(gpx);
2728
                                for (int i = 0; i < z.length; i++) {
2729
                                        ((Curve2DZ) ig).setCoordinateAt(i, dim, z[i]);
2730
                                }
2731
                        }
2732
                } catch (Exception e) {
2733
                        e.printStackTrace();
2734
                        return null;
2735
                }
2736

    
2737
                return ig;
2738
        }
2739

    
2740
        /**
2741
         * 
2742
         * @param the_data
2743
         * @param dim
2744
         * @return
2745
         */
2746
        public static Geometry getFMapGeometryPoint(Datum[] the_data, int dim) {
2747

    
2748
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2749

    
2750
                double[] ords = OracleUtils.getOrds(the_data);
2751

    
2752
                if (ords == null) { // sdo_point
2753

    
2754
                        return getFMapGeometrySdoPoint(the_data, dim);
2755
                }
2756

    
2757
                Geometry ig = null;
2758
                int total_size = ords.length;
2759
                int no_po = total_size / dim;
2760
                double[] x = new double[no_po];
2761
                double[] y = new double[no_po];
2762
                double[] z = new double[no_po];
2763

    
2764
                for (int i = 0; i < no_po; i++) {
2765
                        x[i] = ords[i * dim]; // pp[i].getX();
2766
                        y[i] = ords[(i * dim) + 1];
2767

    
2768
                        if (dim >= 3) {
2769
                                z[i] = ords[(i * dim) + 2];
2770
                        }
2771
                }
2772
                try {
2773
                        if (dim == 2) {
2774
                                if (no_po == 1) {
2775

    
2776
                                        ig = geomManager.create(Geometry.TYPES.POINT,
2777
                                                        Geometry.SUBTYPES.GEOM2D);
2778

    
2779
                                        ((Point2D) ig).setLocation(x[0], y[0]);
2780
                                } else {
2781
                                        ig = geomManager.create(Geometry.TYPES.MULTIPOINT,
2782
                                                        Geometry.SUBTYPES.GEOM2D);
2783
                                        Point pto = null;
2784
                                        for (int i = 0; i < x.length; i++) {
2785
                                                pto = geomManager.createPoint(x[i], y[i],
2786
                                                                Geometry.SUBTYPES.GEOM2D);
2787
                                                ((MultiPoint2D) ig).addPoint(pto);
2788
                                        }
2789
                                }
2790
                        } else {
2791
                                if (no_po == 1) {
2792
                                        ig = geomManager.create(Geometry.TYPES.POINT,
2793
                                                        Geometry.SUBTYPES.GEOM2DZ);
2794
                                        double[] values = { x[0], y[0], z[0] };
2795
                                        ((Point2DZ) ig).setCoordinates(values);
2796
                                } else {
2797
                                        ig = geomManager.create(Geometry.TYPES.MULTIPOINT,
2798
                                                        Geometry.SUBTYPES.GEOM2DZ);
2799
                                        Point pto = null;
2800
                                        for (int i = 0; i < x.length; i++) {
2801
                                                pto = (Point) geomManager.create(Geometry.TYPES.POINT,
2802
                                                                Geometry.SUBTYPES.GEOM2DZ);
2803
                                                double[] valu = { x[i], y[i], z[i] };
2804
                                                ((Point2DZ) pto).setCoordinates(valu);
2805
                                                ((MultiPoint2D) ig).addPoint(pto);
2806
                                        }
2807
                                }
2808
                        }
2809
                } catch (CreateGeometryException e) {
2810
                        e.printStackTrace();
2811
                        return null;
2812
                }
2813

    
2814
                return ig;
2815
        }
2816

    
2817
        /**
2818
         * 
2819
         * @param the_data
2820
         * @param d
2821
         * @return
2822
         */
2823
        public static Geometry getFMapGeometrySdoPoint(Datum[] the_data, int d) {
2824
                double x = 0;
2825
                double y = 0;
2826
                double z = 0;
2827

    
2828
                try {
2829
                        Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
2830
                        x = ((NUMBER) aux[0]).doubleValue();
2831
                        y = ((NUMBER) aux[1]).doubleValue();
2832

    
2833
                        if (d > 2) {
2834
                                z = ((NUMBER) aux[2]).doubleValue();
2835
                        }
2836
                } catch (SQLException se) {
2837
                        logger.error("While getting sdo point ordinates: "
2838
                                        + se.getMessage(), se);
2839
                }
2840

    
2841
                Geometry ig = null;
2842

    
2843
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2844
                if (d == 2) {
2845
                        try {
2846
                                ig = geomManager.create(Geometry.TYPES.POINT,
2847
                                                Geometry.SUBTYPES.GEOM2D);
2848
                                ((Point2D) ig).setLocation(x, y);
2849
                        } catch (CreateGeometryException e) {
2850
                                e.printStackTrace();
2851
                        }
2852
                } else {
2853
                        try {
2854
                                ig = geomManager.create(Geometry.TYPES.POINT,
2855
                                                Geometry.SUBTYPES.GEOM3D);
2856
                                double[] values = { x, y, z };
2857
                                ((Point2DZ) ig).setCoordinates(values);
2858
                        } catch (CreateGeometryException e) {
2859
                                e.printStackTrace();
2860
                        }
2861
                }
2862

    
2863
                return ig;
2864
        }
2865

    
2866
        /**
2867
         * 
2868
         * @param the_data
2869
         * @return
2870
         */
2871
        public static boolean isActuallyACollection(Datum[] the_data) {
2872
                int[] info = null;
2873

    
2874
                try {
2875
                        ARRAY aux = (ARRAY) the_data[3];
2876

    
2877
                        if (aux == null) {
2878
                                return false;
2879
                        }
2880

    
2881
                        info = aux.getIntArray();
2882
                } catch (SQLException se) {
2883
                        logger.error("While checking collection: " + se.getMessage());
2884
                        return false;
2885
                }
2886

    
2887
                if (info == null) {
2888
                        return false; // sdo_point
2889
                }
2890

    
2891
                int size = info.length / 3;
2892

    
2893
                if (size == 1) {
2894
                        return false;
2895
                }
2896

    
2897
                if (size == 2) {
2898
                        return ((info[1] % 1000) != (info[4] % 1000))
2899
                                        && (!((info[1] == 1005) && (info[4] == 2)));
2900
                }
2901

    
2902
                int second = info[4] % 1000;
2903
                int item = 0;
2904

    
2905
                for (int i = 2; i < size; i++) {
2906
                        item = info[(i * 3) + 1] % 1000;
2907
                        if ((item != second) && (!((item == 5) && (second == 2)))) {
2908
                                return true;
2909
                        }
2910
                }
2911

    
2912
                return false;
2913
        }
2914

    
2915
        /**
2916
         * 
2917
         * @param info
2918
         * @return
2919
         */
2920
        public static Datum[] updateIndexes(Datum[] info) {
2921
                int size = info.length / 3;
2922
                NUMBER[] resp = new NUMBER[3 * size];
2923

    
2924
                try {
2925
                        int rest = info[0].intValue() - 1;
2926

    
2927
                        for (int i = 0; i < size; i++) {
2928
                                resp[3 * i] = new NUMBER(info[3 * i].intValue() - rest);
2929
                                resp[(3 * i) + 1] = new NUMBER(info[(3 * i) + 1].intValue());
2930
                                resp[(3 * i) + 2] = new NUMBER(info[(3 * i) + 2].intValue());
2931
                        }
2932
                } catch (SQLException se) {
2933
                        logger.error("Unexpected error: " + se.getMessage());
2934
                }
2935

    
2936
                return resp;
2937
        }
2938

    
2939
        /**
2940
         * 
2941
         * @param all
2942
         * @param first_inc
2943
         * @param last_inc
2944
         * @return
2945
         */
2946
        public static double[] getSubSet(double[] all, int first_inc, int last_inc) {
2947
                double[] resp = new double[last_inc - first_inc + 1];
2948

    
2949
                for (int i = first_inc; i <= last_inc; i++) {
2950
                        resp[i - first_inc] = all[i];
2951
                }
2952

    
2953
                return resp;
2954
        }
2955

    
2956
        /**
2957
         * 
2958
         * @param all
2959
         * @param groups
2960
         * @return
2961
         * @throws SQLException
2962
         */
2963
        public static Object[] getOrdOfGroups(Datum[] all, Object[] groups)
2964
                        throws SQLException {
2965
                Object[] resp = new Object[groups.length];
2966

    
2967
                if (resp.length == 1) {
2968
                        resp[0] = all;
2969

    
2970
                        return resp;
2971
                }
2972

    
2973
                int ind = 0;
2974
                Datum[] aux = (Datum[]) groups[1];
2975
                int _end = aux[0].intValue() - 2;
2976
                Datum[] ord_aux = getSubSet(all, 0, _end);
2977

    
2978
                int _start = _end + 1;
2979
                resp[ind] = ord_aux;
2980
                ind++;
2981

    
2982
                for (int i = 2; i < groups.length; i++) {
2983
                        aux = (Datum[]) groups[i];
2984
                        _end = aux[0].intValue() - 2;
2985
                        ord_aux = getSubSet(all, _start, _end);
2986
                        resp[ind] = ord_aux;
2987
                        ind++;
2988
                        _start = _end + 1;
2989
                }
2990

    
2991
                // last
2992
                _end = all.length - 1;
2993
                ord_aux = getSubSet(all, _start, _end);
2994
                resp[groups.length - 1] = ord_aux;
2995

    
2996
                return resp;
2997
        }
2998

    
2999
        /**
3000
         * 
3001
         * @param all
3002
         * @param groups
3003
         * @return
3004
         */
3005
        public static Object[] getOrdOfGroups(double[] all, Object[] groups) {
3006
                Object[] resp = new Object[groups.length];
3007

    
3008
                if (resp.length == 1) {
3009
                        resp[0] = all;
3010

    
3011
                        return resp;
3012
                }
3013

    
3014
                int ind = 0;
3015
                int[] aux = (int[]) groups[1];
3016
                int _end = aux[0] - 2;
3017
                double[] ord_aux = getSubSet(all, 0, _end);
3018

    
3019
                int _start = _end + 1;
3020
                resp[ind] = ord_aux;
3021
                ind++;
3022

    
3023
                for (int i = 2; i < groups.length; i++) {
3024
                        aux = (int[]) groups[i];
3025
                        _end = aux[0] - 2;
3026
                        ord_aux = getSubSet(all, _start, _end);
3027
                        resp[ind] = ord_aux;
3028
                        ind++;
3029
                        _start = _end + 1;
3030
                }
3031

    
3032
                // last
3033
                _end = all.length - 1;
3034
                ord_aux = getSubSet(all, _start, _end);
3035
                resp[groups.length - 1] = ord_aux;
3036

    
3037
                return resp;
3038
        }
3039

    
3040
        /**
3041
         * 
3042
         * @param all_elem
3043
         * @return
3044
         */
3045
        public static Object[] groupByElement(int[] all_elem) {
3046
                List<int[]> resp = new ArrayList<int[]>();
3047

    
3048
                int size = all_elem.length / 3;
3049

    
3050
                int[] aux = getNthGroupOfThree(all_elem, 0);
3051

    
3052
                int[] newaux;
3053
                int i = 1;
3054

    
3055
                while (i < size) {
3056
                        newaux = getNthGroupOfThree(all_elem, i);
3057

    
3058
                        if (newaux[0] == aux[0]) {
3059
                                // aux[2] says how many components
3060
                                for (int j = 0; j < aux[2]; j++) {
3061
                                        aux = appendIntArrays(aux, getNthGroupOfThree(all_elem, j
3062
                                                        + i));
3063
                                }
3064

    
3065
                                resp.add(aux);
3066
                                i = i + aux[2];
3067
                                aux = getNthGroupOfThree(all_elem, i);
3068
                        } else {
3069
                                if (newaux[1] == 2003) {
3070
                                        aux = appendIntArrays(aux, newaux);
3071
                                } else {
3072
                                        resp.add(aux);
3073
                                        aux = getNthGroupOfThree(all_elem, i);
3074
                                }
3075
                        }
3076

    
3077
                        i++;
3078
                }
3079

    
3080
                resp.add(aux);
3081

    
3082
                return resp.toArray();
3083
        }
3084

    
3085
        /**
3086
         * 
3087
         * @param all_elem
3088
         * @return
3089
         */
3090
        public static boolean isSimpleCollectionOfLines(Datum[] all_elem) {
3091

    
3092
                try {
3093
                        int size = all_elem.length;
3094
                        if (all_elem[1].intValue() != 4)
3095
                                return false;
3096
                        int size3 = size / 3;
3097

    
3098
                        for (int i = 1; i < size3; i++) {
3099
                                if (all_elem[3 * i + 1].intValue() != 2)
3100
                                        return false;
3101
                        }
3102
                        return true;
3103

    
3104
                } catch (SQLException ex) {
3105
                        logger.error("While is simple line collection: " + ex.getMessage());
3106
                }
3107

    
3108
                return false;
3109
        }
3110

    
3111
        /**
3112
         * 
3113
         * @param elem
3114
         * @return
3115
         */
3116
        public static Datum[] removeThreeFirst(Datum[] elem) {
3117
                int sz = elem.length;
3118
                Datum[] resp = new Datum[sz - 3];
3119
                for (int i = 3; i < sz; i++)
3120
                        resp[i - 3] = elem[i];
3121
                return resp;
3122
        }
3123

    
3124
        /**
3125
         * 
3126
         * @param all_elem
3127
         * @return
3128
         */
3129
        public static Object[] groupByElement(Datum[] all_elem) {
3130

    
3131
                if (isSimpleCollectionOfLines(all_elem)) {
3132
                        Object[] r = new Object[1];
3133
                        r[0] = removeThreeFirst(all_elem);
3134
                        return r;
3135
                }
3136

    
3137
                List<Datum[]> resp = new ArrayList<Datum[]>();
3138

    
3139
                int size = all_elem.length / 3;
3140

    
3141
                Datum[] aux = getNthGroupOfThree(all_elem, 0);
3142

    
3143
                Datum[] newaux;
3144
                int i = 1;
3145
                boolean add_last_time = true;
3146

    
3147
                try {
3148
                        while (i < size) {
3149
                                newaux = getNthGroupOfThree(all_elem, i);
3150

    
3151
                                if (newaux[0].intValue() == aux[0].intValue()) {
3152
                                        // aux[2] says how many components
3153
                                        for (int j = 0; j < ((NUMBER) aux[2]).intValue(); j++) {
3154
                                                aux = appendDatArrays(aux, getNthGroupOfThree(all_elem,
3155
                                                                j + i));
3156
                                        }
3157

    
3158
                                        resp.add(aux);
3159
                                        i = i + ((NUMBER) aux[2]).intValue();
3160
                                        if (i < size) { // in some cases (line collection, 4)
3161
                                                aux = getNthGroupOfThree(all_elem, i);
3162
                                        } else {
3163
                                                add_last_time = false;
3164
                                        }
3165
                                } else {
3166
                                        if (((NUMBER) newaux[1]).intValue() == 2003) {
3167
                                                aux = appendDatArrays(aux, newaux);
3168
                                        } else {
3169
                                                resp.add(aux);
3170
                                                aux = getNthGroupOfThree(all_elem, i);
3171
                                        }
3172
                                }
3173

    
3174
                                i++;
3175
                        }
3176
                } catch (SQLException se) {
3177
                        logger.error("Unexpected error: " + se.getMessage());
3178
                }
3179

    
3180
                if (add_last_time) {
3181
                        resp.add(aux);
3182
                }
3183

    
3184
                return resp.toArray();
3185
        }
3186

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

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

    
3208
                STRUCT resp = null;
3209

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

    
3217
                        // for (int i=0; i<size; i++) new_obj[i] = old_obj[i];
3218
                        new_obj[0] = new NUMBER(2003);
3219

    
3220
                        if (hasSrid) {
3221
                                new_obj[1] = new NUMBER(_oracleSRID);
3222
                        } else {
3223
                                new_obj[1] = null;
3224
                        }
3225

    
3226
                        new_obj[2] = null;
3227

    
3228
                        NUMBER[] elem_info = new NUMBER[3];
3229
                        elem_info[0] = new NUMBER(1);
3230
                        elem_info[1] = new NUMBER(1003);
3231
                        elem_info[2] = new NUMBER(3);
3232
                        new_obj[3] = elem_info;
3233

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

    
3242
                        StructDescriptor dsc = StructDescriptor.createDescriptor(
3243
                                        "MDSYS.SDO_GEOMETRY", __conn);
3244

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

    
3251
                return resp;
3252
        }
3253

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

    
3265
                if (r2.getMaxX() <= r1.getMinX()) {
3266
                        return null;
3267
                }
3268

    
3269
                if (r1.getMaxY() <= r2.getMinY()) {
3270
                        return null;
3271
                }
3272

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

    
3277
                double minx = Math.max(r1.getMinX(), r2.getMinX());
3278
                double miny = Math.max(r1.getMinY(), r2.getMinY());
3279
                double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
3280
                double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
3281

    
3282
                double w = maxx - minx;
3283
                double h = maxy - miny;
3284

    
3285
                return new Rectangle2D.Double(minx, miny, w, h);
3286
        }
3287

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

    
3300
                if (!thas)
3301
                        return false;
3302
                if (oracleSRID2 == null)
3303
                        return false;
3304

    
3305
                int ora_cs = 0;
3306

    
3307
                try {
3308
                        ora_cs = Integer.parseInt(oracleSRID2);
3309
                } catch (Exception ex) {
3310
                        return false;
3311
                }
3312

    
3313
                if (((ora_cs >= 8000) && (ora_cs <= 8999)) || (ora_cs == 524288)) {
3314
                        return true;
3315
                } else {
3316
                        return false;
3317
                }
3318
        }
3319

    
3320
        /**
3321
         * 
3322
         * @param sample
3323
         * @return
3324
         * @throws SQLException
3325
         */
3326
        public static int getShapeTypeOfStruct(STRUCT sample) throws SQLException {
3327

    
3328
                int code = ((NUMBER) sample.getOracleAttributes()[0]).intValue();
3329

    
3330
                int type_part = code % 10;
3331
                int dim_part = code / 1000;
3332

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

    
3342
                switch (type_part) {
3343
                case 1:
3344
                        return z_added + Geometry.TYPES.POINT;
3345

    
3346
                case 2:
3347
                        return z_added + Geometry.TYPES.CURVE;
3348

    
3349
                case 3:
3350
                        return z_added + Geometry.TYPES.SURFACE;
3351

    
3352
                case 4:
3353
                        return z_added + Geometry.TYPES.AGGREGATE;
3354

    
3355
                case 5:
3356
                        return z_added + Geometry.TYPES.MULTIPOINT;
3357

    
3358
                case 6:
3359
                        return z_added + Geometry.TYPES.MULTICURVE;
3360

    
3361
                case 7:
3362
                        return z_added + Geometry.TYPES.MULTISURFACE;
3363
                }
3364

    
3365
                logger.error("Unknown geometry type: " + code);
3366

    
3367
                return Geometry.TYPES.NULL;
3368
        }
3369

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

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

    
3386
                return resp;
3387
        }
3388

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

    
3399
                for (int i = 0; i < hsize; i++) {
3400
                        resp[i] = head[i];
3401
                }
3402

    
3403
                for (int i = 0; i < tail.length; i++) {
3404
                        resp[hsize + i] = tail[i];
3405
                }
3406

    
3407
                return resp;
3408
        }
3409

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

    
3420
                for (int i = 0; i < hsize; i++) {
3421
                        resp[i] = head[i];
3422
                }
3423

    
3424
                for (int i = 0; i < tail.length; i++) {
3425
                        resp[hsize + i] = tail[i];
3426
                }
3427

    
3428
                return resp;
3429
        }
3430

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

    
3443
                return resp;
3444
        }
3445

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

    
3458
                return resp;
3459
        }
3460

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

    
3471
                for (int i = first_inc; i <= last_inc; i++) {
3472
                        resp[i - first_inc] = all[i];
3473
                }
3474

    
3475
                return resp;
3476
        }
3477

    
3478
        /**
3479
         * 
3480
         * @param _type
3481
         * @return
3482
         */
3483
        public static int maxSizeForFieldType(int _type) {
3484
                switch (_type) {
3485
                case Types.VARCHAR:
3486
                        return OracleValues.VARCHAR2_STANDARD_SIZE;
3487

    
3488
                case Types.LONGVARCHAR:
3489
                        return OracleValues.VARCHAR2_LONG_SIZE;
3490
                }
3491

    
3492
                return -1;
3493
        }
3494

    
3495
        /**
3496
         * Utility method to transform a struct into a IGeometry.
3497
         * 
3498
         * @param st
3499
         *            the struct to be converted
3500
         * @param complex
3501
         *            comes from a complex sdo geometry
3502
         * @return the IGeometry
3503
         */
3504
        private Geometry getFMapGeometry(STRUCT st, boolean complex) {
3505

    
3506
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
3507

    
3508
                if (st == null) {
3509
                        return geomManager.createNullGeometry(Geometry.SUBTYPES.UNKNOWN);
3510
                }
3511

    
3512
                Datum[] the_data = null;
3513

    
3514
                try {
3515
                        the_data = st.getOracleAttributes();
3516

    
3517
                        int jgtype = ((NUMBER) the_data[0]).intValue() % 1000;
3518
                        jgtype = oracleGTypeToGvsigGeometryType(jgtype, complex);
3519

    
3520
                        int dim = ((NUMBER) the_data[0]).intValue() / 1000;
3521

    
3522
                        if (dim < 2) {
3523
                                dim = 2;
3524
                        }
3525

    
3526
                        Geometry ig = null;
3527

    
3528
                        if (OracleUtils.isActuallyACollection(the_data)) {
3529
                                jgtype = Geometry.TYPES.AGGREGATE;
3530
                        }
3531

    
3532
                        switch (jgtype) {
3533
                        case Geometry.TYPES.AGGREGATE:
3534

    
3535
                                // int srid = ((NUMBER) the_data[1]).intValue();
3536
                                ig = getFMapGeometryCollection(the_data, dim);
3537

    
3538
                                break;
3539

    
3540
                        case Geometry.TYPES.POINT:
3541
                                ig = OracleUtils.getFMapGeometryPoint(the_data, dim);
3542

    
3543
                                break;
3544

    
3545
                        case Geometry.TYPES.CURVE:
3546
                                ig = OracleUtils.getFMapGeometryMultiLineString(the_data, dim);
3547

    
3548
                                break;
3549

    
3550
                        case Geometry.TYPES.SURFACE:
3551
                                ig = OracleUtils.getFMapGeometryMultipolygon(the_data, dim);
3552

    
3553
                                break;
3554
                        }
3555

    
3556
                        return ig;
3557
                } catch (SQLException e) {
3558
                        logger.error(e);
3559
                }
3560

    
3561
                return null;
3562
        }
3563

    
3564
        private Geometry getFMapGeometryCollection(Datum[] the_data, int dim) {
3565
                // int __srid) {
3566

    
3567
                NUMBER _srid = new NUMBER(0);
3568
                NUMBER main_type = new NUMBER((dim * 1000)
3569
                                + OracleUtils.getStructType(the_data));
3570

    
3571
                Datum[] all_info_array = null;
3572
                Object[] elems_info_aray = null;
3573
                Datum[] all_ords = null;
3574

    
3575
                Object[] ords_of_groups = null;
3576
                Object[] _elems_info_aray = null;
3577
                try {
3578
                        all_info_array = ((ARRAY) the_data[3]).getOracleArray();
3579
                        elems_info_aray = OracleUtils.groupByElement(all_info_array);
3580
                        all_ords = ((ARRAY) the_data[4]).getOracleArray();
3581

    
3582
                        ords_of_groups = OracleUtils.getOrdOfGroups(all_ords,
3583
                                        elems_info_aray);
3584
                        _elems_info_aray = new Object[elems_info_aray.length];
3585
                } catch (SQLException e) {
3586
                        logger.error("Unexpected error: " + e.getMessage());
3587
                }
3588

    
3589
                for (int i = 0; i < elems_info_aray.length; i++) {
3590
                        _elems_info_aray[i] = OracleUtils
3591
                                        .updateIndexes((Datum[]) elems_info_aray[i]);
3592
                }
3593

    
3594
                // _elems_info_aray, ords_of_groups
3595
                int no_of_elems = ords_of_groups.length;
3596
                Geometry[] geoms = new Geometry[no_of_elems];
3597

    
3598
                for (int i = 0; i < no_of_elems; i++) {
3599
                        Datum[] item_info_array = null;
3600
                        Datum[] item_ords = null;
3601
                        NUMBER gtype = null;
3602

    
3603
                        try {
3604
                                item_info_array = (Datum[]) _elems_info_aray[i];
3605
                                item_ords = (Datum[]) ords_of_groups[i];
3606

    
3607
                                gtype = new NUMBER((dim * 1000)
3608
                                                + (item_info_array[1].intValue() % 1000));
3609

    
3610
                                if (tableHasSrid) {
3611
                                        _srid = new NUMBER(Integer.parseInt(oracleSRID));
3612
                                }
3613
                        } catch (SQLException se) {
3614
                                logger.error("Unexpected error: " + se.getMessage());
3615
                        }
3616

    
3617
                        // if it's the first geometry, the type is the collection's main
3618
                        // type (no?) - no
3619
                        // if (i == 0) gtype = main_type;
3620

    
3621
                        STRUCT itemst = null;
3622

    
3623
                        if (tableHasSrid) {
3624

    
3625
                                itemst = OracleUtils.createStruct(gtype, _srid,
3626
                                                item_info_array, item_ords, conn);
3627
                        } else {
3628
                                itemst = OracleUtils.createStruct(gtype, null, item_info_array,
3629
                                                item_ords, conn);
3630
                        }
3631

    
3632
                        geoms[i] = getFMapGeometry(itemst, true);
3633
                }
3634

    
3635
                return new FGeometryCollection(geoms);
3636
        }
3637

    
3638
        /**
3639
         * 
3640
         * @param tname
3641
         * @param suffix
3642
         * @return
3643
         */
3644
        public static String getDerivedName(String tname, String suffix) {
3645

    
3646
                int ind = tname.lastIndexOf(".");
3647
                if (ind == -1) {
3648

    
3649
                        int l = Math.min(28, tname.length());
3650
                        return tname.substring(0, l) + "_" + suffix;
3651

    
3652
                } else {
3653

    
3654
                        String pre = tname.substring(0, ind);
3655
                        String post = tname.substring(ind + 1, tname.length());
3656
                        int lpost = Math.min(24, post.length());
3657
                        int lpre = Math.min(3, pre.length());
3658
                        return pre.substring(0, lpre) + "_" + post.substring(0, lpost)
3659
                                        + "_" + suffix;
3660
                }
3661

    
3662
        }
3663

    
3664
}