Statistics
| Revision:

root / branches / v2_0_0_prep / extensions / org.gvsig.oracle / src / org / gvsig / fmap / dal / store / oracle / OracleUtils.java @ 31889

History | View | Annotate | Download (96.8 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

    
28
package org.gvsig.fmap.dal.store.oracle;
29

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

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

    
58
import org.apache.log4j.Logger;
59
import org.cresques.cts.IProjection;
60
import org.geotools.xml.filter.FilterOpsComplexTypes.UpperBoundaryType;
61
import org.gvsig.fmap.dal.DALLocator;
62
import org.gvsig.fmap.dal.DataManager;
63
import org.gvsig.fmap.dal.exception.DataException;
64
import org.gvsig.fmap.dal.feature.EditableFeatureType;
65
import org.gvsig.fmap.dal.feature.Feature;
66
import org.gvsig.fmap.dal.feature.FeatureQuery;
67
import org.gvsig.fmap.dal.feature.FeatureSet;
68
import org.gvsig.fmap.dal.feature.FeatureStore;
69
import org.gvsig.fmap.geom.Geometry;
70
import org.gvsig.fmap.geom.GeometryLocator;
71
import org.gvsig.fmap.geom.GeometryManager;
72
import org.gvsig.fmap.geom.Geometry.SUBTYPES;
73
import org.gvsig.fmap.geom.Geometry.TYPES;
74
import org.gvsig.fmap.geom.aggregate.MultiPrimitive;
75
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2D;
76
import org.gvsig.fmap.geom.aggregate.impl.MultiPoint2DZ;
77
import org.gvsig.fmap.geom.complex.Complex;
78
import org.gvsig.fmap.geom.exception.CreateGeometryException;
79
import org.gvsig.fmap.geom.primitive.Curve;
80
import org.gvsig.fmap.geom.primitive.GeneralPathX;
81
import org.gvsig.fmap.geom.primitive.Point;
82
import org.gvsig.fmap.geom.primitive.Primitive;
83
import org.gvsig.fmap.geom.primitive.Surface;
84
import org.gvsig.fmap.geom.primitive.impl.Circle2D;
85
import org.gvsig.fmap.geom.primitive.impl.Curve2DZ;
86
import org.gvsig.fmap.geom.primitive.impl.Point2DZ;
87
import org.gvsig.fmap.geom.primitive.impl.Surface2D;
88
import org.gvsig.fmap.geom.primitive.impl.Surface2DZ;
89
import org.gvsig.oracle.utils.LineString3D;
90

    
91
import com.vividsolutions.jts.algorithm.CGAlgorithms;
92
import com.vividsolutions.jts.geom.Coordinate;
93
import com.vividsolutions.jts.geom.CoordinateArrays;
94
import com.vividsolutions.jts.geom.Envelope;
95
import com.vividsolutions.jts.geom.GeometryFactory;
96
import com.vividsolutions.jts.geom.LineString;
97
import com.vividsolutions.jts.geom.LinearRing;
98
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
99

    
100
/**
101
 * Utility class with static methods.
102
 * 
103
 * @author jldominguez, vsanjaime
104
 * 
105
 */
106
public class OracleUtils {
107
        private static Logger logger = Logger
108
                        .getLogger(OracleUtils.class.getName());
109
        private static double FLATNESS = 0.8;
110
        private static GeometryFactory geomFactory = new GeometryFactory();
111
        private static final double IRRELEVANT_DISTANCE = 0.00000001;
112
        public static final Rectangle2D DEFAULT_BBOX = new Rectangle2D.Double(-180, -90, 360, 180);;
113
        private static Random rnd = new Random();
114
        private static DecimalFormat df = new DecimalFormat();
115
        private static DecimalFormatSymbols dfs = new DecimalFormatSymbols();
116
        
117
        public static final String ENVELOPE_ID = "Envelope_Key";
118
        public static final String DIMENSIONS_ID = "Dimensions_Key";
119

    
120

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

    
136
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
137

    
138
                GeneralPathX gpx = new GeneralPathX();
139
                File file = new File(filepath.getFile());
140
                List<Double> z = new ArrayList<Double>();
141

    
142
                try {
143
                        FileReader fr = new FileReader(file);
144
                        BufferedReader br = new BufferedReader(fr);
145
                        double[] coords = new double[3];
146

    
147
                        boolean move = true;
148

    
149
                        String line = br.readLine();
150

    
151
                        while (line != null) {
152
                                coords = parseLine(line);
153

    
154
                                if (line.length() == 0) {
155
                                        move = true;
156
                                } else {
157
                                        if (move) {
158
                                                gpx.moveTo(coords[0], coords[1]);
159
                                                z.add(new Double(coords[2]));
160
                                        } else {
161
                                                gpx.lineTo(coords[0], coords[1]);
162
                                                z.add(new Double(coords[2]));
163
                                        }
164

    
165
                                        move = false;
166
                                }
167

    
168
                                line = br.readLine();
169
                        }
170
                } catch (Exception ex) {
171
                        logger.error("While creating GeneralPathX: " + ex.getMessage());
172
                        return null;
173
                }
174

    
175
                if (polygon) {
176
                        Surface surface = (Surface) geomManager.create(
177
                                        Geometry.TYPES.SURFACE, Geometry.SUBTYPES.GEOM2DZ);
178
                        surface.setGeneralPath(gpx);
179
                        for (int i = 0; i < z.size(); i++) {
180
                                surface
181
                                                .setCoordinateAt(i, 3, ((Double) z.get(i))
182
                                                                .doubleValue());
183
                        }
184
                        return surface;
185
                } else {
186
                        Curve curve = (Curve) geomManager.create(Geometry.TYPES.CURVE,
187
                                        Geometry.SUBTYPES.GEOM2DZ);
188
                        curve.setGeneralPath(gpx);
189
                        for (int i = 0; i < z.size(); i++) {
190
                                curve.setCoordinateAt(i, 3, ((Double) z.get(i)).doubleValue());
191
                        }
192
                        return curve;
193
                }
194
        }
195

    
196
        /**
197
         * 
198
         * @param line
199
         * @return
200
         */
201
        private static double[] parseLine(String line) {
202
                String[] sep = line.split(" ");
203
                double[] resp = new double[3];
204

    
205
                for (int i = 0; i < 3; i++)
206
                        resp[i] = 0.0;
207

    
208
                try {
209
                        resp[0] = Double.parseDouble(sep[0]);
210
                } catch (Exception ex) {
211
                }
212

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

    
219
                        if (sep.length > 2) {
220
                                try {
221
                                        resp[2] = Double.parseDouble(sep[2]);
222
                                } catch (Exception ex) {
223
                                }
224
                        }
225
                }
226

    
227
                return resp;
228
        }
229

    
230
        /**
231
         * Transform multipoint2d or multipoint2dz to Oracle STRUCT
232
         * 
233
         * @param mp2d
234
         * @param conn
235
         * @param osrid
236
         * @param hasSrid
237
         * @return
238
         * @throws SQLException
239
         */
240
        private static STRUCT multiPoint2DToStruct(MultiPoint2D mp2d,
241
                        Connection conn, int osrid, boolean hasSrid) throws SQLException {
242
                int np = mp2d.getPrimitivesNumber();
243
                boolean threed = (mp2d instanceof MultiPoint2DZ);
244
                int gtype = 2005;
245
                int dim = 2;
246
                MultiPoint2DZ mp3d = null;
247

    
248
                if (threed) {
249
                        gtype = 3005;
250
                        dim = 3;
251
                        mp3d = (MultiPoint2DZ) mp2d;
252
                }
253

    
254
                NUMBER[] indices = new NUMBER[3];
255
                indices[0] = new NUMBER(1);
256
                indices[1] = new NUMBER(1);
257
                indices[2] = new NUMBER(np);
258

    
259
                NUMBER[] ords = new NUMBER[dim * np];
260

    
261
                for (int i = 0; i < np; i++) {
262
                        ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
263
                        ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY());
264

    
265
                        if (threed) {
266
                                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
267
                        }
268
                }
269

    
270
                STRUCT resp;
271
                StructDescriptor dsc = StructDescriptor.createDescriptor(
272
                                "MDSYS.SDO_GEOMETRY", conn);
273
                Object[] obj = new Object[5];
274
                obj[0] = new NUMBER(gtype);
275

    
276
                if (hasSrid) {
277
                        obj[1] = new NUMBER(osrid);
278
                } else { // , boolean hasSrid
279
                        obj[1] = null;
280
                }
281

    
282
                obj[2] = null;
283
                obj[3] = indices;
284
                obj[4] = ords;
285
                resp = new STRUCT(dsc, conn, obj);
286

    
287
                return resp;
288
        }
289

    
290
        /**
291
         * Transform circle2d to Oracle STRUCT
292
         * 
293
         * @param fcirc
294
         * @param osrid
295
         * @param _conn
296
         * @param hasSrid
297
         * @return
298
         * @throws SQLException
299
         */
300
        private static STRUCT getCircleAsStruct(Circle2D fcirc, int osrid,
301
                        Connection conn, boolean hasSrid) throws SQLException {
302
                int geotype = 2003;
303
                NUMBER[] indices = new NUMBER[3];
304
                indices[0] = new NUMBER(1);
305
                indices[1] = new NUMBER(1003);
306
                indices[2] = new NUMBER(4);
307

    
308
                NUMBER[] ords = new NUMBER[6];
309
                Coordinate[] three_points = getThreePointsOfCircumference(fcirc
310
                                .getCenter(), fcirc.getRadious());
311

    
312
                for (int i = 0; i < three_points.length; i++) {
313
                        ords[i * 2] = new NUMBER(three_points[i].x);
314
                        ords[(i * 2) + 1] = new NUMBER(three_points[i].y);
315
                }
316

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

    
323
                if (hasSrid) {
324
                        obj[1] = new NUMBER(osrid);
325
                } else {
326
                        obj[1] = null;
327
                }
328

    
329
                obj[2] = null;
330
                obj[3] = indices;
331
                obj[4] = ords;
332
                resp = new STRUCT(dsc, conn, obj);
333

    
334
                return resp;
335
        }
336

    
337
        /**
338
         * 
339
         * @param center
340
         * @param radius
341
         * @return
342
         */
343
        private static Coordinate[] getThreePointsOfCircumference(Point center,
344
                        double radius) {
345
                Coordinate[] resp = new Coordinate[3];
346
                double x;
347
                double y;
348
                double alpha = 0;
349

    
350
                for (int i = 0; i < 3; i++) {
351
                        alpha = (i * 120.0 * Math.PI) / 180.0;
352
                        x = center.getX() + (radius * Math.cos(alpha));
353
                        y = center.getY() + (radius * Math.sin(alpha));
354
                        resp[i] = new Coordinate(x, y);
355
                }
356

    
357
                return resp;
358
        }
359

    
360
        /**
361
         * Get coordinates from a point
362
         * 
363
         * @param pto
364
         * @return
365
         */
366
        private static Coordinate getSingleCoordinate(Point pto) {
367
                Coordinate resp = new Coordinate();
368
                resp.x = pto.getX();
369
                resp.y = pto.getY();
370
                if (pto instanceof Point2DZ) {
371
                        resp.z = ((Point2DZ) pto).getCoordinateAt(3);
372
                }
373
                return resp;
374
        }
375

    
376
        /**
377
         * 
378
         * @param cc
379
         * @return
380
         */
381
        private static List<Coordinate> ensureSensibleLineString(List<Coordinate> cc) {
382
                if (cc.size() == 2) {
383
                        if (same2DCoordinate(cc.get(0), cc.get(cc.size() - 1))) {
384
                                List<Coordinate> resp = new ArrayList<Coordinate>();
385
                                resp.add(cc.get(0));
386

    
387
                                Coordinate newc = new Coordinate(cc.get(0));
388
                                newc.x = newc.x + IRRELEVANT_DISTANCE;
389
                                resp.add(newc);
390

    
391
                                return resp;
392
                        }
393
                }
394
                return cc;
395
        }
396

    
397
        /**
398
         * 
399
         * @param c1
400
         * @param c2
401
         * @return
402
         */
403
        private static boolean same2DCoordinate(Coordinate c1, Coordinate c2) {
404
                if (c1.x != c2.x) {
405
                        return false;
406
                }
407
                if (c1.y != c2.y) {
408
                        return false;
409
                }
410

    
411
                return true;
412
        }
413

    
414
        /**
415
         * 
416
         * @param cc
417
         * @return
418
         */
419
        private static List<Coordinate> getClosedRelevantPolygon(List<Coordinate> cc) {
420
                if (cc.size() == 2) {
421
                        return getMinClosedCoords(cc.get(0));
422
                }
423

    
424
                if (cc.size() == 3) {
425
                        if (same2DCoordinate(cc.get(0), cc.get(1))) {
426
                                return getMinClosedCoords(cc.get(0));
427
                        }
428

    
429
                        if (same2DCoordinate(cc.get(0), cc.get(2))) {
430
                                return getMinClosedCoords((Coordinate) cc.get(0));
431
                        }
432

    
433
                        if (same2DCoordinate(cc.get(1), cc.get(2))) {
434
                                return getMinClosedCoords(cc.get(1));
435
                        }
436

    
437
                        cc.add(cc.get(0));
438

    
439
                        return cc;
440
                }
441

    
442
                if (!same2DCoordinate(cc.get(0), cc.get(cc.size() - 1))) {
443
                        cc.add(cc.get(0));
444
                }
445

    
446
                return cc;
447
        }
448

    
449
        /**
450
         * 
451
         * @param c
452
         * @return
453
         */
454
        private static List<Coordinate> getMinClosedCoords(Coordinate c) {
455
                List<Coordinate> resp = new ArrayList<Coordinate>();
456
                resp.add(c);
457

    
458
                Coordinate nc = new Coordinate(c);
459
                nc.x = nc.x + IRRELEVANT_DISTANCE;
460
                resp.add(nc);
461

    
462
                Coordinate nc2 = new Coordinate(nc);
463
                nc2.y = nc2.y + IRRELEVANT_DISTANCE;
464
                resp.add(nc2);
465

    
466
                resp.add(new Coordinate(c));
467

    
468
                return resp;
469
        }
470

    
471
        /**
472
         * 
473
         * @param c
474
         * @return
475
         */
476
        private static LinearRing getMinLinearRing(Coordinate c) {
477
                Coordinate[] p = new Coordinate[4];
478
                p[0] = c;
479

    
480
                Coordinate nc = new Coordinate(c);
481
                nc.x = nc.x + IRRELEVANT_DISTANCE;
482

    
483
                Coordinate nc2 = new Coordinate(nc);
484
                nc2.y = nc2.y - IRRELEVANT_DISTANCE;
485
                p[1] = nc;
486
                p[2] = nc2;
487
                p[3] = new Coordinate(c);
488

    
489
                CoordinateArraySequence cs = new CoordinateArraySequence(p);
490
                LinearRing ls = new LinearRing(cs, geomFactory);
491

    
492
                return ls;
493
        }
494

    
495
        /**
496
         * 
497
         * @return
498
         */
499
        private static double[] getMinLinearRingZ() {
500
                double[] resp = new double[4];
501

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

    
505
                return resp;
506
        }
507

    
508
        /**
509
         * 
510
         * @param testPoint
511
         * @param pointList
512
         * @return
513
         */
514
        private static boolean pointInList(Coordinate testPoint,
515
                        Coordinate[] pointList) {
516
                int t;
517
                int numpoints;
518
                Coordinate p;
519

    
520
                numpoints = Array.getLength(pointList);
521

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

    
525
                        if ((testPoint.x == p.x)
526
                                        && (testPoint.y == p.y)
527
                                        && ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z)))) {
528
                                return true;
529
                        }
530
                }
531

    
532
                return false;
533
        }
534

    
535
        /***
536
         * 
537
         * @param mpolygon
538
         * @return
539
         */
540
        private static List<LineString3D> getPolygonsEasily(Geometry mpolygon) {
541
                boolean threed = false;
542

    
543
                if (mpolygon instanceof Surface2DZ) {
544
                        threed = true;
545
                }
546

    
547
                int start_ind = 0;
548
                int end_ind = 0;
549
                int ind = 0;
550
                int new_size;
551
                List<Coordinate> arrayCoords = null;
552
                List<LineString3D> resp = new ArrayList<LineString3D>();
553
                Coordinate[] points = null;
554
                int theType = -99;
555
                double[] theData = new double[6];
556
                Coordinate onlyCoord = null;
557
                int numParts = 0;
558

    
559
                PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
560

    
561
                while (!theIterator.isDone()) {
562
                        // while not done
563
                        theType = theIterator.currentSegment(theData);
564

    
565
                        if (onlyCoord == null) {
566
                                onlyCoord = new Coordinate();
567
                                onlyCoord.x = theData[0];
568
                                onlyCoord.y = theData[1];
569
                        }
570

    
571
                        switch (theType) {
572
                        case PathIterator.SEG_MOVETO:
573

    
574
                                if (arrayCoords == null) {
575
                                        arrayCoords = new ArrayList<Coordinate>();
576
                                } else {
577
                                        end_ind = ind - 1;
578

    
579
                                        arrayCoords = getClosedRelevantPolygon(arrayCoords);
580
                                        new_size = arrayCoords.size();
581

    
582
                                        if (arrayCoords != null) {
583
                                                points = CoordinateArrays
584
                                                                .toCoordinateArray(arrayCoords);
585

    
586
                                                try {
587
                                                        LinearRing aux = geomFactory
588
                                                                        .createLinearRing(points);
589
                                                        double[] z = null;
590

    
591
                                                        if (threed) {
592
                                                                z = getZ((Surface2DZ) mpolygon, start_ind,
593
                                                                                end_ind, new_size);
594
                                                        }
595

    
596
                                                        LineString3D ring = new LineString3D(aux, z);
597

    
598
                                                        if (CGAlgorithms.isCCW(points)) {
599
                                                                resp.add(ring);
600
                                                        } else {
601
                                                                resp.add(ring.createReverse());
602
                                                        }
603
                                                } catch (Exception e) {
604
                                                        logger.error("Topology exception: "
605
                                                                        + e.getMessage());
606

    
607
                                                        return null;
608
                                                }
609
                                        }
610

    
611
                                        arrayCoords = new ArrayList<Coordinate>();
612

    
613
                                        start_ind = ind;
614
                                }
615

    
616
                                numParts++;
617

    
618
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
619
                                ind++;
620

    
621
                                break;
622

    
623
                        case PathIterator.SEG_LINETO:
624
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
625
                                ind++;
626

    
627
                                break;
628

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

    
636
                                break;
637

    
638
                        case PathIterator.SEG_CUBICTO:
639
                                logger.info("SEG_CUBICTO Not supported here");
640
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
641
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
642
                                arrayCoords.add(new Coordinate(theData[4], theData[5]));
643
                                ind++;
644
                                ind++;
645
                                ind++;
646

    
647
                                break;
648

    
649
                        case PathIterator.SEG_CLOSE:
650
                                break;
651
                        }
652

    
653
                        theIterator.next();
654
                }
655

    
656
                end_ind = ind - 1;
657

    
658
                // null shape:
659
                if (arrayCoords == null) {
660
                        arrayCoords = new ArrayList<Coordinate>();
661

    
662
                        Coordinate _c = new Coordinate(0, 0, 0);
663
                        arrayCoords.add(new Coordinate(_c));
664
                        arrayCoords.add(new Coordinate(_c));
665
                }
666

    
667
                // --------------------------------------------
668
                arrayCoords = getClosedRelevantPolygon(arrayCoords);
669
                new_size = arrayCoords.size();
670

    
671
                if (arrayCoords != null) {
672
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
673

    
674
                        try {
675
                                LinearRing aux = geomFactory.createLinearRing(points);
676
                                double[] z = null;
677

    
678
                                if (threed) {
679
                                        z = getZ((Surface2DZ) mpolygon, start_ind, end_ind,
680
                                                        new_size);
681
                                }
682

    
683
                                LineString3D ring = new LineString3D(aux, z);
684

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

    
693
                                return null;
694
                        }
695
                }
696

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

    
702
                return resp;
703
        }
704

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

    
717
                for (int i = 0; i < size; i++) {
718
                        resp[i] = _z[size - 1 - i];
719
                }
720

    
721
                return resp;
722
        }
723

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

    
736
                for (int i = 0; i < size; i++) {
737
                        resp[i] = _z[size - 1 - i];
738
                }
739

    
740
                return resp;
741
        }
742

    
743
        /**
744
         * 
745
         * @param geom
746
         * @param _str
747
         * @param _end
748
         * @param size
749
         * @return
750
         */
751
        private static double[] getZ(Geometry geom, int _str, int _end, int size) {
752
                double[] resp = new double[size];
753

    
754
                double[] allz = new double[1];
755

    
756
                if (geom instanceof Point2DZ) {
757
                        allz[0] = ((Point2DZ) geom).getCoordinateAt(3);
758
                }
759
                if (geom instanceof Curve2DZ) {
760
                        Curve2DZ curve = (Curve2DZ) geom;
761
                        allz = new double[curve.getNumVertices()];
762
                        for (int i = 0; i < allz.length; i++) {
763
                                allz[i] = curve.getCoordinateAt(i, 3);
764
                        }
765
                }
766
                if (geom instanceof Surface2DZ) {
767
                        Surface2DZ surface = (Surface2DZ) geom;
768
                        allz = new double[surface.getNumVertices()];
769
                        for (int i = 0; i < allz.length; i++) {
770
                                allz[i] = surface.getCoordinateAt(i, 3);
771
                        }
772
                }
773

    
774
                for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) {
775
                        resp[i - _str] = allz[i];
776
                }
777

    
778
                if ((_end - _str + 1) < size) {
779
                        double repe = allz[_end];
780

    
781
                        for (int i = (_end - _str + 1); i < size; i++) {
782
                                resp[i] = repe;
783
                        }
784
                }
785
                return resp;
786
        }
787

    
788
        /**
789
         * 
790
         * @param mlines
791
         * @return
792
         */
793
        private static List<LineString3D> getLineStrings(Geometry mlines) {
794
                boolean threed = false;
795

    
796
                if (mlines instanceof Curve2DZ) {
797
                        threed = true;
798
                }
799

    
800
                int start_ind = 0;
801
                int end_ind = 0;
802
                int ind = 0;
803
                int new_size = 0;
804

    
805
                LineString3D lin;
806

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

    
814
                while (!theIterator.isDone()) {
815
                        // while not done
816
                        theType = theIterator.currentSegment(theData);
817

    
818
                        switch (theType) {
819
                        case PathIterator.SEG_MOVETO:
820

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

    
828
                                        LineString aux = geomFactory
829
                                                        .createLineString(CoordinateArrays
830
                                                                        .toCoordinateArray(arrayCoords));
831
                                        double[] z = null;
832

    
833
                                        if (threed) {
834
                                                z = getZ((Curve2DZ) mlines, start_ind, end_ind,
835
                                                                new_size);
836
                                        }
837

    
838
                                        lin = new LineString3D(aux, z);
839
                                        arrayLines.add(lin);
840
                                        arrayCoords = new ArrayList<Coordinate>();
841

    
842
                                        start_ind = ind;
843
                                }
844

    
845
                                numParts++;
846
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
847

    
848
                                break;
849

    
850
                        case PathIterator.SEG_LINETO:
851
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
852

    
853
                                break;
854

    
855
                        case PathIterator.SEG_QUADTO:
856
                                logger.info("Not supported here: SEG_QUADTO");
857

    
858
                                break;
859

    
860
                        case PathIterator.SEG_CUBICTO:
861
                                logger.info("Not supported here: SEG_CUBICTO");
862

    
863
                                break;
864

    
865
                        case PathIterator.SEG_CLOSE:
866

    
867
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
868
                                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
869

    
870
                                break;
871
                        } // end switch
872

    
873
                        theIterator.next();
874
                        ind++;
875
                } // end while loop
876

    
877
                arrayCoords = ensureSensibleLineString(arrayCoords);
878
                new_size = arrayCoords.size();
879

    
880
                LineString aux = geomFactory.createLineString(CoordinateArrays
881
                                .toCoordinateArray(arrayCoords));
882
                double[] z = null;
883

    
884
                if (threed) {
885
                        z = getZ((Curve2DZ) mlines, start_ind, end_ind, new_size);
886
                }
887

    
888
                lin = new LineString3D(aux, z);
889
                arrayLines.add(lin);
890

    
891
                return arrayLines;
892
        }
893

    
894
        /**
895
         * 
896
         * @param ls
897
         * @param threed
898
         * @return
899
         */
900
        private static String lineStringToWKT(LineString3D ls, boolean threed) {
901
                String resp = "(";
902
                Coordinate[] cc = ls.getLs().getCoordinates();
903
                double[] z = ls.getZc();
904
                int size = cc.length;
905

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

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

    
918
                        resp = resp.substring(0, resp.length() - 2);
919
                        resp = resp + ")";
920
                }
921

    
922
                return resp;
923
        }
924

    
925
        /**
926
         * 
927
         * @param ml
928
         * @param threed
929
         * @return
930
         */
931
        private static String multiLineStringToWKT(List<LineString3D> ml,
932
                        boolean threed) {
933
                String resp = "MULTILINESTRING(";
934

    
935
                for (int i = 0; i < ml.size(); i++) {
936
                        LineString3D ls = ml.get(i);
937
                        resp = resp + lineStringToWKT(ls, threed) + ", ";
938
                }
939

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

    
942
                return resp;
943
        }
944

    
945
        /**
946
         * 
947
         * @param pols
948
         * @param threed
949
         * @return
950
         */
951
        private static String polygonsToWKT(List<LineString3D> pols, boolean threed) {
952
                String resp = "MULTIPOLYGON(";
953
                LineString3D ls = null;
954

    
955
                for (int i = 0; i < pols.size(); i++) {
956
                        ls = pols.get(i);
957
                        resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
958
                }
959

    
960
                resp = resp.substring(0, resp.length() - 2) + ")";
961

    
962
                return resp;
963
        }
964

    
965
        /**
966
         * 
967
         * @param shell
968
         * @param holes
969
         * @param threed
970
         * @return
971
         */
972
        private static String shellAndHolesToWKT(LineString3D shell,
973
                        List<LineString3D> holes, boolean threed) {
974
                String resp = "(";
975
                resp = resp + lineStringToWKT(shell, threed);
976

    
977
                if (holes.size() > 0) {
978
                        for (int i = 0; i < holes.size(); i++) {
979
                                LineString3D ls = holes.get(i);
980
                                resp = resp + ", " + lineStringToWKT(ls, threed);
981
                        }
982
                }
983

    
984
                resp = resp + ")";
985

    
986
                return resp;
987
        }
988

    
989
        /**
990
         * 
991
         * @param shells
992
         * @param hFs
993
         * @param threed
994
         * @return
995
         */
996
        private static String multiPolygonToWKT(List<LineString3D> shells,
997
                        List<List<LineString3D>> hFs, boolean threed) {
998
                String resp = "MULTIPOLYGON(";
999
                LineString3D ls = null;
1000
                List<LineString3D> holes;
1001

    
1002
                for (int i = 0; i < shells.size(); i++) {
1003
                        ls = shells.get(i);
1004
                        holes = hFs.get(i);
1005
                        resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
1006
                }
1007

    
1008
                resp = resp.substring(0, resp.length() - 2) + ")";
1009

    
1010
                return resp;
1011
        }
1012

    
1013
        /**
1014
         * 
1015
         * @param point
1016
         * @param threed
1017
         * @return
1018
         */
1019
        private static String pointToWKT(Point point, boolean threed) {
1020
                String resp = "POINT(" + point.getX() + " " + point.getY();
1021

    
1022
                if ((threed) && (point instanceof Point2DZ)) {
1023
                        resp = resp + " " + ((Point2DZ) point).getCoordinateAt(3);
1024
                }
1025

    
1026
                resp = resp + ")";
1027

    
1028
                return resp;
1029
        }
1030

    
1031
        /**
1032
         * 
1033
         * @param n
1034
         * @param d
1035
         * @return
1036
         */
1037
        private static int twoDIndexToDimsIndex(int n, int d) {
1038
                return ((d * (n - 1)) / 2) + 1;
1039
        }
1040

    
1041
        /**
1042
         * 
1043
         * @param old
1044
         * @param d
1045
         * @return
1046
         * @throws SQLException
1047
         */
1048
        private static ARRAY setSubelementsToDim(ARRAY old, int d)
1049
                        throws SQLException {
1050
                Datum[] infos = (Datum[]) old.getOracleArray();
1051

    
1052
                for (int i = 3; i < infos.length; i = i + 3) {
1053
                        int oldind = infos[i].intValue();
1054
                        oldind = twoDIndexToDimsIndex(oldind, d);
1055
                        infos[i] = new NUMBER(oldind);
1056

    
1057
                        //
1058
                        oldind = infos[i + 1].intValue();
1059
                        infos[i + 1] = new NUMBER(infos[1].intValue());
1060
                }
1061

    
1062
                ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
1063
                                infos);
1064

    
1065
                return resp;
1066
        }
1067

    
1068
        /**
1069
         * 
1070
         * @param p
1071
         * @param ls
1072
         * @return
1073
         */
1074
        private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
1075
                Envelope env = ls.getEnvelopeInternal();
1076

    
1077
                if (!env.contains(p)) {
1078
                        return false;
1079
                }
1080

    
1081
                return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
1082
        }
1083

    
1084
        /**
1085
         * 
1086
         * @param contained
1087
         * @param container
1088
         * @return
1089
         */
1090
        private static boolean lineString3DIsContainedBy(LineString3D contained,
1091
                        LineString3D container) {
1092
                int samples = 10;
1093
                LineString _in = contained.getLs();
1094
                LineString _out = container.getLs();
1095
                Coordinate[] inc = _in.getCoordinates();
1096
                Coordinate aux;
1097
                int size = inc.length;
1098

    
1099
                if (size <= 10) {
1100
                        for (int i = 0; i < size; i++) {
1101
                                aux = inc[i];
1102

    
1103
                                if (!isPointInsideLineString(aux, _out)) {
1104
                                        return false;
1105
                                }
1106
                        }
1107

    
1108
                        return true;
1109
                } else {
1110
                        for (int i = 0; i < samples; i++) {
1111
                                aux = inc[rnd.nextInt(size)];
1112

    
1113
                                if (!isPointInsideLineString(aux, _out)) {
1114
                                        return false;
1115
                                }
1116
                        }
1117

    
1118
                        return true;
1119
                }
1120
        }
1121

    
1122
        /**
1123
         * Transform multipolygons2d or 2dz to Oracle STRUCT
1124
         * 
1125
         * @param pols
1126
         * @param srid
1127
         * @param threed
1128
         * @param _conn
1129
         * @param agu_bien
1130
         * @param hasSrid
1131
         * @return
1132
         * @throws SQLException
1133
         */
1134
        private static STRUCT getMultiPolygonAsStruct(List<LineString3D> pols,
1135
                        int osrid, boolean threed, Connection conn, boolean agu_bien,
1136
                        boolean hasSrid) throws SQLException {
1137
                int size = pols.size();
1138
                int geotype = 2007;
1139
                int dim = 2;
1140
                int acum = 0;
1141

    
1142
                if (threed) {
1143
                        geotype = 3007;
1144
                        dim = 3;
1145
                }
1146

    
1147
                NUMBER[] indices = new NUMBER[3 * size];
1148

    
1149
                for (int i = 0; i < size; i++) {
1150
                        indices[3 * i] = new NUMBER(acum + 1);
1151
                        indices[(3 * i) + 1] = new NUMBER(1003);
1152
                        indices[(3 * i) + 2] = new NUMBER(1);
1153
                        acum = acum + (dim * (pols.get(i)).getLs().getNumPoints());
1154
                }
1155

    
1156
                int _ind = 0;
1157
                NUMBER[] ords = new NUMBER[acum];
1158

    
1159
                for (int i = 0; i < size; i++) {
1160
                        LineString3D ls = (LineString3D) pols.get(i);
1161
                        int num_p = ls.getLs().getNumPoints();
1162

    
1163
                        for (int j = 0; j < num_p; j++) {
1164
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1165
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1166

    
1167
                                if (threed) {
1168
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1169
                                }
1170

    
1171
                                _ind = _ind + dim;
1172
                        }
1173
                }
1174

    
1175
                STRUCT resp;
1176
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1177
                                "MDSYS.SDO_GEOMETRY", conn);
1178
                Object[] obj = new Object[5];
1179
                obj[0] = new NUMBER(geotype);
1180

    
1181
                if (hasSrid) {
1182
                        obj[1] = new NUMBER(osrid);
1183
                } else {
1184
                        obj[1] = null;
1185
                }
1186

    
1187
                obj[2] = null;
1188
                obj[3] = indices;
1189
                obj[4] = ords;
1190
                resp = new STRUCT(dsc, conn, obj);
1191

    
1192
                return resp;
1193
        }
1194

    
1195
        /**
1196
         * 
1197
         * @param lines
1198
         * @param srid
1199
         * @param threed
1200
         * @param _conn
1201
         * @param hasSrid
1202
         * @return
1203
         * @throws SQLException
1204
         */
1205
        private static STRUCT getMultiLineAsStruct(List<LineString3D> lines,
1206
                        int osrid, boolean threed, Connection conn, boolean hasSrid)
1207
                        throws SQLException {
1208

    
1209
                int size = lines.size();
1210
                int geotype = 2006;
1211
                int dim = 2;
1212
                int acum = 0;
1213

    
1214
                if (threed) {
1215
                        geotype = 3006;
1216
                        dim = 3;
1217
                }
1218

    
1219
                NUMBER[] indices = new NUMBER[3 * size];
1220

    
1221
                for (int i = 0; i < size; i++) {
1222
                        indices[3 * i] = new NUMBER(acum + 1);
1223
                        indices[(3 * i) + 1] = new NUMBER(2);
1224
                        indices[(3 * i) + 2] = new NUMBER(1);
1225
                        acum = acum + (dim * (lines.get(i)).getLs().getNumPoints());
1226
                }
1227

    
1228
                int _ind = 0;
1229
                NUMBER[] ords = new NUMBER[acum];
1230

    
1231
                for (int i = 0; i < size; i++) {
1232
                        LineString3D ls = lines.get(i);
1233
                        int num_p = ls.getLs().getNumPoints();
1234

    
1235
                        for (int j = 0; j < num_p; j++) {
1236
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1237
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1238

    
1239
                                if (threed) {
1240
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1241
                                }
1242

    
1243
                                _ind = _ind + dim;
1244
                        }
1245
                }
1246

    
1247
                STRUCT resp;
1248
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1249
                                "MDSYS.SDO_GEOMETRY", conn);
1250
                Object[] obj = new Object[5];
1251
                obj[0] = new NUMBER(geotype);
1252

    
1253
                if (hasSrid) {
1254
                        obj[1] = new NUMBER(osrid);
1255
                } else {
1256
                        obj[1] = null;
1257
                }
1258

    
1259
                obj[2] = null;
1260
                obj[3] = indices;
1261
                obj[4] = ords;
1262
                resp = new STRUCT(dsc, conn, obj);
1263

    
1264
                return resp;
1265
        }
1266

    
1267
        /**
1268
         * 
1269
         * @param pnt
1270
         * @param srid
1271
         * @param threed
1272
         * @param _conn
1273
         * @param hasSrid
1274
         * @return
1275
         * @throws SQLException
1276
         */
1277
        private static STRUCT getMultiPointAsStruct(Coordinate pnt, int osrid,
1278
                        boolean threed, Connection conn, boolean hasSrid)
1279
                        throws SQLException {
1280
                int geotype = 2001;
1281
                int dim = 2;
1282

    
1283
                if (threed) {
1284
                        geotype = 3001;
1285
                        dim = 3;
1286
                }
1287

    
1288
                Object[] ords = new Object[3];
1289
                ords[0] = new NUMBER(pnt.x);
1290
                ords[1] = new NUMBER(pnt.y);
1291
                ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null;
1292

    
1293
                StructDescriptor ord_dsc = StructDescriptor.createDescriptor(
1294
                                "MDSYS.SDO_POINT_TYPE", conn);
1295
                STRUCT ords_st = new STRUCT(ord_dsc, conn, ords);
1296

    
1297
                STRUCT resp;
1298

    
1299
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1300
                                "MDSYS.SDO_GEOMETRY", conn);
1301
                Object[] obj = new Object[5];
1302

    
1303
                obj[0] = new NUMBER(geotype);
1304

    
1305
                if (hasSrid) {
1306
                        obj[1] = new NUMBER(osrid);
1307
                } else {
1308
                        obj[1] = null;
1309
                }
1310

    
1311
                obj[2] = ords_st;
1312
                obj[3] = null;
1313
                obj[4] = null;
1314
                resp = new STRUCT(dsc, conn, obj);
1315

    
1316
                return resp;
1317
        }
1318

    
1319
        /**
1320
         * Utility method to compute a circle's center and radius from three given
1321
         * points.
1322
         * 
1323
         * @param points
1324
         *            three points of a circumference
1325
         * @return a 2-item array with the circumference's center (Point2D) and
1326
         *         radius (Double)
1327
         */
1328
        public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1329
                Object[] resp = new Object[2];
1330
                resp[0] = new Point2D.Double(0, 0);
1331
                resp[1] = new Double(0);
1332

    
1333
                double m11;
1334
                double m12;
1335
                double m13;
1336
                double m14;
1337

    
1338
                if (points.length != 3) {
1339
                        logger.error("Needs 3 points (found " + points.length
1340
                                        + ") - circle cannot be computed.");
1341

    
1342
                        // not a circle
1343
                        return resp;
1344
                }
1345

    
1346
                double[][] a = new double[3][3];
1347

    
1348
                for (int i = 0; i < 3; i++) { // find minor 11
1349
                        a[i][0] = points[i].getX();
1350
                        a[i][1] = points[i].getY();
1351
                        a[i][2] = 1;
1352
                }
1353

    
1354
                m11 = determinant(a, 3);
1355

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

    
1363
                m12 = determinant(a, 3);
1364

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

    
1373
                m13 = determinant(a, 3);
1374

    
1375
                for (int i = 0; i < 3; i++) { // find minor 14
1376
                        a[i][0] = (points[i].getX() * points[i].getX())
1377
                                        + (points[i].getY() * points[i].getY());
1378
                        a[i][1] = points[i].getX();
1379
                        a[i][2] = points[i].getY();
1380
                }
1381

    
1382
                m14 = determinant(a, 3);
1383

    
1384
                Double resp_radius = new Double(0);
1385
                Point2D resp_center = new Point2D.Double(0, 0);
1386

    
1387
                if (m11 == 0) {
1388
                        logger.error("Three points aligned - circle cannot be computed."); // not
1389
                        // a
1390
                        // circle
1391
                } else {
1392
                        double x = (0.5 * m12) / m11;
1393
                        double y = (-0.5 * m13) / m11;
1394
                        resp_center.setLocation(x, y);
1395
                        resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11)));
1396
                        resp[0] = resp_center;
1397
                        resp[1] = resp_radius;
1398
                }
1399

    
1400
                return resp;
1401
        }
1402

    
1403
        /**
1404
         * Utility method to compute a matrix determinant
1405
         * 
1406
         * @param a
1407
         *            the matrix
1408
         * @param n
1409
         *            matrix size
1410
         * @return the matrix's determinant
1411
         */
1412
        public static double determinant(double[][] a, int n) {
1413
                double resp = 0;
1414
                double[][] m = new double[3][3];
1415

    
1416
                if (n == 2) { // terminate recursion
1417
                        resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1418
                } else {
1419
                        resp = 0;
1420

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

    
1423
                                for (int i = 1; i < n; i++) { // create minor
1424

    
1425
                                        int j2 = 0;
1426

    
1427
                                        for (int j = 0; j < n; j++) {
1428
                                                if (j == j1) {
1429
                                                        continue;
1430
                                                }
1431

    
1432
                                                m[i - 1][j2] = a[i][j];
1433
                                                j2++;
1434
                                        }
1435
                                }
1436

    
1437
                                // sum (+/-)cofactor * minor
1438
                                resp = resp
1439
                                                + (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1440
                        }
1441
                }
1442

    
1443
                return resp;
1444
        }
1445

    
1446
        /**
1447
         * 
1448
         * @param ls
1449
         * @param list
1450
         * @param self
1451
         * @return
1452
         */
1453
        private static int getSmallestContainerExcept(LineString3D ls,
1454
                        List<LineString3D> list, int self) {
1455
                int resp = -1;
1456
                List<Integer> provList = new ArrayList<Integer>();
1457

    
1458
                int size = list.size();
1459

    
1460
                for (int i = 0; i < self; i++) {
1461
                        if (lineString3DIsContainedBy(ls, list.get(i))) {
1462
                                provList.add(new Integer(i));
1463
                        }
1464
                }
1465

    
1466
                for (int i = (self + 1); i < size; i++) {
1467
                        if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1468
                                provList.add(new Integer(i));
1469
                        }
1470
                }
1471

    
1472
                if (provList.size() == 0) {
1473
                        // logger.debug("LineString is not contained by any other ls.");
1474
                } else {
1475
                        if (provList.size() == 1) {
1476
                                resp = ((Integer) provList.get(0)).intValue();
1477
                        } else {
1478
                                if (provList.size() == 2) {
1479
                                        int ind_1 = ((Integer) provList.get(0)).intValue();
1480
                                        int ind_2 = ((Integer) provList.get(1)).intValue();
1481
                                        LineString3D ls1 = (LineString3D) list.get(ind_1);
1482
                                        LineString3D ls2 = (LineString3D) list.get(ind_2);
1483

    
1484
                                        if (lineString3DIsContainedBy(ls1, ls2)) {
1485
                                                resp = ind_1;
1486
                                        } else {
1487
                                                resp = ind_2;
1488
                                        }
1489
                                } else {
1490
                                        // not so deep, sorry!
1491
                                        // it's going to be a shell: resp = -1;
1492
                                }
1493
                        }
1494
                }
1495

    
1496
                return resp;
1497
        }
1498

    
1499
        /**
1500
         * 
1501
         * @param containings
1502
         * @return
1503
         */
1504
        private static int[] getIndicesOfShells(int[] containings) {
1505
                List<Integer> resp = new ArrayList<Integer>();
1506

    
1507
                for (int i = 0; i < containings.length; i++) {
1508
                        if (containings[i] == -1) {
1509
                                resp.add(new Integer(i));
1510
                        }
1511
                }
1512

    
1513
                int size = resp.size();
1514
                int[] _resp = new int[size];
1515

    
1516
                for (int i = 0; i < size; i++) {
1517
                        _resp[i] = (resp.get(i)).intValue();
1518
                }
1519

    
1520
                return _resp;
1521
        }
1522

    
1523
        /**
1524
         * 
1525
         * @param containings
1526
         * @param shells
1527
         * @return
1528
         */
1529
        private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1530
                List<Integer> resp = new ArrayList<Integer>();
1531

    
1532
                for (int i = 0; i < containings.length; i++) {
1533
                        int cont_by = containings[i];
1534

    
1535
                        if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1536
                                resp.add(new Integer(i));
1537
                        }
1538
                }
1539

    
1540
                int size = resp.size();
1541
                int[] _resp = new int[size];
1542

    
1543
                for (int i = 0; i < size; i++) {
1544
                        _resp[i] = (resp.get(i)).intValue();
1545
                }
1546

    
1547
                return _resp;
1548
        }
1549

    
1550
        /**
1551
         * 
1552
         * @param containings
1553
         * @param holes
1554
         * @return
1555
         */
1556
        private static int[] getFinalContainings(int[] containings, int[] holes) {
1557
                List<Integer> resp = new ArrayList<Integer>();
1558

    
1559
                for (int i = 0; i < containings.length; i++) {
1560
                        int cont_by = containings[i];
1561

    
1562
                        if (isOneOf(cont_by, holes)) {
1563
                                resp.add(new Integer(-1));
1564
                        } else {
1565
                                resp.add(new Integer(cont_by));
1566
                        }
1567
                }
1568

    
1569
                int size = resp.size();
1570
                int[] _resp = new int[size];
1571

    
1572
                for (int i = 0; i < size; i++) {
1573
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1574
                }
1575

    
1576
                return _resp;
1577
        }
1578

    
1579
        /**
1580
         * 
1581
         * @param ind
1582
         * @param final_contn
1583
         * @param all
1584
         * @return
1585
         */
1586
        private static List<LineString3D> getHolesOf(int ind, int[] final_contn,
1587
                        List<LineString3D> all) {
1588

    
1589
                List<Integer> resp_ind = new ArrayList<Integer>();
1590

    
1591
                for (int i = 0; i < final_contn.length; i++) {
1592
                        if (final_contn[i] == ind) {
1593
                                resp_ind.add(new Integer(i));
1594
                        }
1595
                }
1596

    
1597
                List<LineString3D> resp = new ArrayList<LineString3D>();
1598

    
1599
                for (int i = 0; i < resp_ind.size(); i++) {
1600
                        Integer aux = (Integer) resp_ind.get(i);
1601
                        resp.add(all.get(aux.intValue()));
1602
                }
1603

    
1604
                return resp;
1605
        }
1606

    
1607
        /**
1608
         * 
1609
         * @param final_contn
1610
         * @param all
1611
         * @return
1612
         */
1613
        private static List<LineString3D> getShellsIn(int[] final_contn,
1614
                        List<LineString3D> all) {
1615
                List<Integer> resp_ind = new ArrayList<Integer>();
1616

    
1617
                for (int i = 0; i < final_contn.length; i++) {
1618
                        if (final_contn[i] == -1) {
1619
                                resp_ind.add(new Integer(i));
1620
                        }
1621
                }
1622

    
1623
                List<LineString3D> resp = new ArrayList<LineString3D>();
1624

    
1625
                for (int i = 0; i < resp_ind.size(); i++) {
1626
                        Integer aux = (Integer) resp_ind.get(i);
1627
                        resp.add(all.get(aux.intValue()));
1628
                }
1629

    
1630
                return resp;
1631
        }
1632

    
1633
        /**
1634
         * This method tries to guess who is a shell and who is a hole from a set of
1635
         * linestrings.
1636
         * 
1637
         * @param all_ls
1638
         *            a set of linestrings to be checked.
1639
         * 
1640
         * @return a 2-item array. the first is an arraylist of linestrings thought
1641
         *         to be shells. the second is an array of arraylists containing the
1642
         *         holes of each shell found in the first item
1643
         * 
1644
         */
1645
        public static Object[] getHolesForShells(List<LineString3D> all_ls) {
1646
                int no_of_ls = all_ls.size();
1647
                int[] containedby = new int[no_of_ls];
1648
                int[] shells;
1649
                int[] holes;
1650
                int[] final_cont;
1651

    
1652
                for (int i = 0; i < no_of_ls; i++) {
1653
                        LineString3D ls_aux = all_ls.get(i);
1654
                        containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1655
                }
1656

    
1657
                shells = getIndicesOfShells(containedby);
1658
                holes = getIndicesOfHoles(containedby, shells);
1659
                final_cont = getFinalContainings(containedby, holes);
1660

    
1661
                // true shells:
1662
                shells = getIndicesOfShells(final_cont);
1663

    
1664
                List<LineString3D> resp_shells = new ArrayList<LineString3D>();
1665
                List resp_holes_for_shells = new ArrayList();
1666
                List<LineString3D> aux_holes;
1667

    
1668
                for (int i = 0; i < shells.length; i++) {
1669
                        resp_shells.add(all_ls.get(shells[i]));
1670
                        aux_holes = getHolesOf(i, final_cont, all_ls);
1671
                        resp_holes_for_shells.add(aux_holes);
1672
                }
1673

    
1674
                Object[] _resp = new Object[2];
1675
                _resp[0] = resp_shells;
1676
                _resp[1] = resp_holes_for_shells;
1677

    
1678
                return _resp;
1679
        }
1680

    
1681
        /**
1682
         * 
1683
         * @param listOfLists
1684
         * @return
1685
         */
1686
        private static int getTotalSize(List listOfLists) {
1687
                int resp = 0;
1688

    
1689
                for (int i = 0; i < listOfLists.size(); i++) {
1690
                        resp = resp + ((List) listOfLists.get(i)).size();
1691
                }
1692

    
1693
                return resp;
1694
        }
1695

    
1696
        /**
1697
         * 
1698
         * @param mpol
1699
         * @param srid
1700
         * @param threed
1701
         * @param _conn
1702
         * @param agu_bien
1703
         * @param hasSrid
1704
         * @return
1705
         * @throws SQLException
1706
         */
1707
        private static STRUCT getMultiPolygonAsStruct(Geometry mpol, int osrid,
1708
                        boolean threed, Connection conn, boolean agu_bien, boolean hasSrid)
1709
                        throws SQLException {
1710
                List<LineString3D> all_ls = getPolygonsEasily(mpol);
1711
                Object[] hs = getHolesForShells(all_ls);
1712
                List sh = (List) hs[0];
1713
                List _ho = (List) hs[1];
1714
                List ho = reverseHoles(_ho);
1715

    
1716
                STRUCT st = null;
1717
                
1718
                try {
1719
                        st = getMultiPolygonAsStruct(sh, ho, osrid, threed, conn, agu_bien, hasSrid);
1720
                } catch (Throwable th) {
1721
                        throw new SQLException(th.getMessage());
1722
                }
1723

    
1724
                return st; 
1725
        }
1726

    
1727
        /**
1728
         * 
1729
         * @param hh
1730
         * @return
1731
         */
1732
        private static List reverseHoles(List hh) {
1733
                List resp = new ArrayList();
1734

    
1735
                for (int i = 0; i < hh.size(); i++) {
1736
                        List item = (ArrayList) hh.get(i);
1737
                        List newitem = new ArrayList();
1738

    
1739
                        for (int j = 0; j < item.size(); j++) {
1740
                                LineString3D ls = (LineString3D) item.get(j);
1741
                                newitem.add(ls.createReverse());
1742
                        }
1743

    
1744
                        resp.add(newitem);
1745
                }
1746

    
1747
                return resp;
1748
        }
1749

    
1750
        /**
1751
         * 
1752
         * @param shells
1753
         * @param holes
1754
         * @param srid
1755
         * @param threed
1756
         * @param _conn
1757
         * @param explicito
1758
         * @param hasSrid
1759
         * @return
1760
         * @throws SQLException
1761
         */
1762
        private static STRUCT getMultiPolygonAsStruct(List shells, List holes,
1763
                        int osrid, boolean threed, Connection conn, boolean explicito,
1764
                        boolean hasSrid) throws SQLException {
1765
                int t = 1003;
1766

    
1767
                if (explicito) {
1768
                        t = 2003;
1769
                }
1770

    
1771
                int size = shells.size() + getTotalSize(holes);
1772
                int geotype = 2003;
1773
                if (size > 1)
1774
                        geotype = 2007;
1775

    
1776
                int dim = 2;
1777

    
1778
                if (threed) {
1779
                        geotype = geotype + 1000;
1780
                        dim = 3;
1781
                }
1782

    
1783
                NUMBER[] indices = new NUMBER[3 * size];
1784

    
1785
                int acum = 0;
1786
                int start_ind = 0;
1787

    
1788
                for (int i = 0; i < shells.size(); i++) {
1789
                        indices[start_ind] = new NUMBER(acum + 1);
1790
                        indices[start_ind + 1] = new NUMBER(1003);
1791
                        indices[start_ind + 2] = new NUMBER(1);
1792
                        start_ind = start_ind + 3;
1793
                        acum = acum + (dim * ((LineString3D) shells.get(i)).getLs().getNumPoints());
1794

    
1795
                        List item_holes = (List) holes.get(i);
1796

    
1797
                        for (int j = 0; j < item_holes.size(); j++) {
1798
                                indices[start_ind] = new NUMBER(acum + 1);
1799
                                indices[start_ind + 1] = new NUMBER(t); // 1003
1800
                                indices[start_ind + 2] = new NUMBER(1);
1801
                                start_ind = start_ind + 3;
1802
                                acum = acum
1803
                                                + (dim * ((LineString3D) item_holes.get(j)).getLs()
1804
                                                                .getNumPoints());
1805
                        }
1806
                }
1807

    
1808
                int _ind = 0;
1809
                NUMBER[] ords = new NUMBER[acum];
1810

    
1811
                for (int i = 0; i < shells.size(); i++) {
1812
                        // --------------------------------
1813
                        LineString3D ls = (LineString3D) shells.get(i);
1814
                        int num_p = ls.getLs().getNumPoints();
1815

    
1816
                        for (int j = 0; j < num_p; j++) {
1817
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1818
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1819

    
1820
                                if (threed) {
1821
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1822
                                }
1823

    
1824
                                _ind = _ind + dim;
1825
                        }
1826

    
1827
                        // -------------------------------
1828
                        List item_holes = (ArrayList) holes.get(i);
1829

    
1830
                        for (int j = 0; j < item_holes.size(); j++) {
1831
                                ls = (LineString3D) item_holes.get(j);
1832
                                num_p = ls.getLs().getNumPoints();
1833

    
1834
                                for (int k = 0; k < num_p; k++) {
1835
                                        ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
1836
                                        ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1837

    
1838
                                        if (threed) {
1839
                                                ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1840
                                        }
1841

    
1842
                                        _ind = _ind + dim;
1843
                                }
1844
                        }
1845
                }
1846

    
1847
                STRUCT resp;
1848
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", conn);
1849
                Object[] obj = new Object[5];
1850
                obj[0] = new NUMBER(geotype);
1851

    
1852
                if (hasSrid) {
1853
                        obj[1] = new NUMBER(osrid);
1854
                } else {
1855
                        obj[1] = null;
1856
                }
1857

    
1858
                obj[2] = null;
1859
                obj[3] = indices;
1860
                obj[4] = ords;
1861

    
1862
                resp = new STRUCT(dsc, conn, obj);
1863

    
1864
                return resp;
1865
        }
1866

    
1867
        /**
1868
         * 
1869
         * @param array
1870
         * @return
1871
         */
1872
        public static String printArray(NUMBER[] array) {
1873
                String resp = "[ ";
1874

    
1875
                for (int i = 0; i < array.length; i++) {
1876
                        resp = resp + " " + array[i].doubleValue() + " , ";
1877
                }
1878

    
1879
                resp = resp.substring(0, resp.length() - 2) + "]";
1880

    
1881
                return resp;
1882
        }
1883

    
1884
        /**
1885
         * 
1886
         * @param ind
1887
         * @param list
1888
         * @return
1889
         */
1890
        private static boolean isOneOf(int ind, int[] list) {
1891
                for (int i = 0; i < list.length; i++) {
1892
                        if (list[i] == ind) {
1893
                                return true;
1894
                        }
1895
                }
1896
                return false;
1897
        }
1898

    
1899
        /**
1900
         * This method appends the geometries from a geometries array in one STRUCT.
1901
         * 
1902
         * @param co
1903
         *            the geometry collection
1904
         * @param _forced_type
1905
         *            a type that has to be used as the struct's main type
1906
         * @param _conn
1907
         *            the connection
1908
         * @param _o_srid
1909
         *            the geometry's SRS (oracle code)
1910
         * @param withSrid
1911
         *            whether the SRS is non-NULL
1912
         * @param agu_bien
1913
         *            whether to check holes' validity
1914
         * @param _isGeoCS
1915
         *            whether the SRS is geodetic
1916
         * @return the STRUCT with the appended geometries
1917
         * @throws SQLException
1918
         */
1919
        public static STRUCT appendGeometriesInStruct(Geometry[] geoms,
1920
                        int _forced_type, Connection conn, String osrid, boolean withSrid,
1921
                        boolean agu_bien, boolean _isGeoCS) throws SQLException {
1922
                int osridd = Integer.parseInt(osrid);
1923
                int size = geoms.length;
1924
                STRUCT[] sts = new STRUCT[size];
1925

    
1926
                for (int i = 0; i < size; i++) {
1927
                        Geometry geom = geoms[i];
1928
                        sts[i] = geometryToSTRUCT(geom, conn, osridd, agu_bien, withSrid);
1929
                }
1930

    
1931
                if (size == 1) {
1932
                        return sts[0];
1933
                }
1934

    
1935
                STRUCT aux = sts[0];
1936

    
1937
                for (int i = 1; i < size; i++) {
1938
                        aux = appendStructs(aux, sts[i], conn);
1939
                }
1940

    
1941
                return aux;
1942
        }
1943

    
1944
        /**
1945
         * 
1946
         * @param st1
1947
         * @param st2
1948
         * @param _conn
1949
         * @return
1950
         */
1951
        private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection conn) {
1952
                try {
1953
                        ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1954
                        int length_of_head_ords = _ords.getOracleArray().length;
1955

    
1956
                        NUMBER gtype = new NUMBER(
1957
                                        4 + (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1958
                        NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1959
                        NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1960

    
1961
                        ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1962
                        ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1963
                        ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1964
                        ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1965

    
1966
                        Datum[] info = appendDatumArrays(info1.getOracleArray(), info2
1967
                                        .getOracleArray(), length_of_head_ords);
1968

    
1969
                        Datum[] ords = appendDatumArrays(ords1.getOracleArray(), ords2
1970
                                        .getOracleArray(), 0);
1971

    
1972
                        StructDescriptor dsc = st1.getDescriptor();
1973

    
1974
                        Object[] atts = new Object[5];
1975
                        atts[0] = gtype;
1976
                        atts[1] = srid;
1977
                        atts[2] = middle;
1978
                        atts[3] = info;
1979
                        atts[4] = ords;
1980

    
1981
                        STRUCT resp = new STRUCT(dsc, conn, atts);
1982

    
1983
                        return resp;
1984
                } catch (SQLException sqle) {
1985
                        logger.error("While appending structs: " + sqle.getMessage(), sqle);
1986
                }
1987

    
1988
                return null;
1989
        }
1990

    
1991
        /**
1992
         * 
1993
         * @param head
1994
         * @param tail
1995
         * @param offset
1996
         * @return
1997
         */
1998
        private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
1999
                        int offset) {
2000
                int head_l = head.length;
2001
                int tail_l = tail.length;
2002
                Datum[] resp = new Datum[head_l + tail_l];
2003

    
2004
                for (int i = 0; i < head_l; i++)
2005
                        resp[i] = head[i];
2006

    
2007
                if (offset == 0) {
2008
                        for (int i = 0; i < tail_l; i++)
2009
                                resp[head_l + i] = tail[i];
2010
                } else {
2011
                        try {
2012
                                for (int i = 0; i < tail_l; i++) {
2013
                                        if ((i % 3) == 0) {
2014
                                                resp[head_l + i] = new NUMBER(tail[i].intValue()
2015
                                                                + offset);
2016
                                        } else {
2017
                                                resp[head_l + i] = tail[i];
2018
                                        }
2019
                                }
2020
                        } catch (SQLException se) {
2021
                                logger.error("Unexpected error: " + se.getMessage());
2022
                        }
2023
                }
2024

    
2025
                return resp;
2026
        }
2027

    
2028
        /**
2029
         * Utility method to get an ineteger as a formatted string.
2030
         * 
2031
         * @param n
2032
         *            the integer
2033
         * @return the formatted string
2034
         */
2035
        public static String getFormattedInteger(int n) {
2036
                df.setGroupingUsed(true);
2037
                df.setGroupingSize(3);
2038
                dfs.setGroupingSeparator('.');
2039
                df.setDecimalFormatSymbols(dfs);
2040

    
2041
                return df.format(n);
2042
        }
2043

    
2044
        /**
2045
         * Tells whether these arrays belong to a rectangle polygon.
2046
         * 
2047
         * @param info
2048
         *            the struct's element info array
2049
         * @param ords
2050
         *            the struct's coordinate array
2051
         * @return true if it is a rectangle polygon. false otherwise.
2052
         */
2053
        public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
2054
                try {
2055
                        int[] infos = info.getIntArray();
2056

    
2057
                        return ((infos[2] == 3) && (infos.length == 3));
2058
                } catch (SQLException se) {
2059
                        logger.error("While ckecking rectangle: " + se.getMessage(), se);
2060
                }
2061

    
2062
                return false;
2063
        }
2064

    
2065
        /**
2066
         * Utility method to deal with oracle info arrays.
2067
         */
2068
        public static ARRAY getDevelopedInfoArray(ARRAY info) {
2069
                ARRAY _resp = null;
2070

    
2071
                try {
2072
                        Datum[] resp = new Datum[3];
2073
                        Datum[] in = info.getOracleArray();
2074
                        resp[0] = in[0];
2075
                        resp[1] = in[1];
2076
                        resp[2] = new NUMBER(1);
2077
                        _resp = new ARRAY(info.getDescriptor(), info
2078
                                        .getInternalConnection(), resp);
2079
                } catch (SQLException se) {
2080
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
2081
                }
2082

    
2083
                return _resp;
2084
        }
2085

    
2086
        /**
2087
         * Utility method to deal with oracle coordinate arrays.
2088
         */
2089
        public static ARRAY getDevelopedOrdsArray(ARRAY ords) {
2090
                ARRAY _resp = null;
2091

    
2092
                try {
2093
                        Datum[] resp = new Datum[10];
2094
                        Datum[] corners = ords.getOracleArray();
2095

    
2096
                        // x
2097
                        resp[0] = corners[0];
2098
                        resp[2] = corners[2];
2099
                        resp[4] = corners[2];
2100
                        resp[6] = corners[0];
2101
                        resp[8] = corners[0];
2102

    
2103
                        // y
2104
                        resp[1] = corners[1];
2105
                        resp[3] = corners[1];
2106
                        resp[5] = corners[3];
2107
                        resp[7] = corners[3];
2108
                        resp[9] = corners[1];
2109
                        _resp = new ARRAY(ords.getDescriptor(), ords
2110
                                        .getInternalConnection(), resp);
2111
                } catch (SQLException se) {
2112
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
2113
                }
2114

    
2115
                return _resp;
2116
        }
2117

    
2118
        /**
2119
         * utility method to convert a STRUCT into a GeneralPathX
2120
         * 
2121
         * @param aux
2122
         *            the struct's datum array
2123
         * @return the GeneralPathX instance created
2124
         */
2125
        public static GeneralPathX structToGPX(Datum[] aux) {
2126
                GeneralPathX resp = new GeneralPathX();
2127
                ARRAY infoARRAY = null;
2128
                ARRAY ordsARRAY = null;
2129
                Datum[] info_array = null;
2130
                Datum[] ords_array = null;
2131
                int info_array_size = 0;
2132
                int[] start_ind;
2133
                int[] end_ind;
2134
                int dims = 0;
2135
                boolean next_must_do_first = true;
2136

    
2137
                try {
2138
                        infoARRAY = (ARRAY) aux[3];
2139
                        ordsARRAY = (ARRAY) aux[4];
2140

    
2141
                        if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
2142
                                infoARRAY = getDevelopedInfoArray(infoARRAY);
2143
                                ordsARRAY = getDevelopedOrdsArray(ordsARRAY);
2144
                        }
2145

    
2146
                        dims = ((NUMBER) aux[0]).intValue() / 1000;
2147

    
2148
                        if (dims == 0) {
2149
                                dims = 2;
2150
                        }
2151

    
2152
                        info_array = (Datum[]) infoARRAY.getOracleArray();
2153
                        ords_array = (Datum[]) ordsARRAY.getOracleArray();
2154
                        info_array_size = info_array.length / 3;
2155

    
2156
                        int last_index = ords_array.length - dims + 1;
2157

    
2158
                        // set indices:
2159
                        start_ind = new int[info_array_size];
2160
                        end_ind = new int[info_array_size];
2161

    
2162
                        for (int i = 0; i < info_array_size; i++)
2163
                                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
2164

    
2165
                        for (int i = 0; i < (info_array_size - 1); i++)
2166
                                end_ind[i] = start_ind[i + 1] - 1;
2167

    
2168
                        end_ind[info_array_size - 1] = last_index;
2169

    
2170
                        int lineType = PathIterator.SEG_LINETO;
2171

    
2172
                        if (end_ind[0] == 0) { // collection of paths
2173

    
2174
                                for (int i = 1; i < info_array_size; i++) {
2175
                                        lineType = getLineToType(info_array, i);
2176

    
2177
                                        // -----------------------
2178
                                        if (end_ind[i] == (start_ind[i] - 1))
2179
                                                lineType = PathIterator.SEG_MOVETO;
2180
                                        // -----------------------
2181

    
2182
                                        next_must_do_first = addOrdsToGPX(resp, start_ind[i] - 1,
2183
                                                        end_ind[i] - 1, ords_array, dims, lineType,
2184
                                                        (i == 1) || (lineType == PathIterator.SEG_MOVETO),
2185
                                                        next_must_do_first);
2186
                                }
2187
                        } else {
2188
                                // standard case, do the moveto always
2189
                                for (int i = 0; i < info_array_size; i++) {
2190
                                        lineType = getLineToType(info_array, i);
2191
                                        addOrdsToGPX(resp, start_ind[i] - 1, end_ind[i] - 1,
2192
                                                        ords_array, dims, lineType, true, true);
2193
                                }
2194
                        }
2195

    
2196
                        // boolean do_the_moves = true;
2197
                } catch (SQLException se) {
2198
                        logger.error("While creating GPX: " + se.getMessage(), se);
2199
                }
2200

    
2201
                return resp;
2202
        }
2203

    
2204
        /**
2205
         * 
2206
         * @param infos
2207
         * @param i
2208
         * @return
2209
         */
2210
        private static int getLineToType(Datum[] infos, int i) {
2211
                int resp = PathIterator.SEG_LINETO;
2212

    
2213
                try {
2214
                        if (((NUMBER) infos[(3 * i) + 2]).intValue() == 2) {
2215
                                resp = PathIterator.SEG_QUADTO;
2216
                        }
2217
                } catch (SQLException e) {
2218
                        logger.error("While getting line-to type: " + e.getMessage()
2219
                                        + " (returned SEG_LINETO)");
2220
                }
2221

    
2222
                return resp;
2223
        }
2224

    
2225
        /**
2226
         * 
2227
         * @param gpx
2228
         * @param zero_based_start
2229
         * @param zero_based_include_end
2230
         * @param ords
2231
         * @param d
2232
         * @param ltype
2233
         * @param do_the_move
2234
         * @param must_do_first
2235
         * @return
2236
         */
2237
        private static boolean addOrdsToGPX(GeneralPathX gpx, int zero_based_start,
2238
                        int zero_based_include_end, Datum[] ords, int d, int ltype,
2239
                        boolean do_the_move, boolean must_do_first) {
2240
                int length = ords.length;
2241
                boolean return_following_must_do_first = true;
2242

    
2243
                double x = ((NUMBER) ords[zero_based_start]).doubleValue();
2244
                double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
2245

    
2246
                if (must_do_first) {
2247
                        if (do_the_move) {
2248
                                gpx.moveTo(x, y);
2249
                        } else {
2250
                                gpx.lineTo(x, y);
2251
                        }
2252
                }
2253

    
2254
                int ind = 1;
2255

    
2256
                int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2257
                int indx;
2258
                int indx2;
2259

    
2260
                if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2261

    
2262
                        double x2;
2263
                        double y2;
2264

    
2265
                        while (ind < size) {
2266
                                indx = zero_based_start + (ind * d);
2267
                                x = ((NUMBER) ords[indx]).doubleValue();
2268
                                y = ((NUMBER) ords[indx + 1]).doubleValue();
2269

    
2270
                                indx2 = zero_based_start + ((ind + 1) * d);
2271

    
2272
                                if (indx >= length) {
2273
                                        indx2 = zero_based_start;
2274
                                }
2275

    
2276
                                x2 = ((NUMBER) ords[indx2]).doubleValue();
2277
                                y2 = ((NUMBER) ords[indx2 + 1]).doubleValue();
2278
                                gpx.quadTo(x, y, x2, y2);
2279
                                ind++;
2280
                                ind++;
2281
                        }
2282

    
2283
                        return_following_must_do_first = false;
2284
                } else { // PathIterator.SEG_LINETO (interpretation = 1)
2285

    
2286
                        while (ind < size) {
2287
                                indx = zero_based_start + (ind * d);
2288
                                x = ((NUMBER) ords[indx]).doubleValue();
2289
                                y = ((NUMBER) ords[indx + 1]).doubleValue();
2290
                                gpx.lineTo(x, y);
2291
                                ind++;
2292
                        }
2293
                }
2294

    
2295
                return return_following_must_do_first;
2296
        }
2297

    
2298
        /**
2299
         * Utility method. Gets FShape type from oracle geometry type.
2300
         * 
2301
         * @param otype
2302
         * @return FShape type
2303
         */
2304
        public static int oracleGTypeToGvsigGeometryType(int otype) {
2305
                switch (otype) {
2306
                case OracleValues.ORACLE_GTYPE_UNKNOWN:
2307
                        return Geometry.TYPES.NULL;
2308

    
2309
                case OracleValues.ORACLE_GTYPE_POINT:
2310
                case OracleValues.ORACLE_GTYPE_MULTIPOINT:
2311
                        return Geometry.TYPES.POINT;
2312

    
2313
                case OracleValues.ORACLE_GTYPE_LINE:
2314
                case OracleValues.ORACLE_GTYPE_MULTILINE:
2315
                        return Geometry.TYPES.CURVE;
2316

    
2317
                case OracleValues.ORACLE_GTYPE_POLYGON:
2318
                case OracleValues.ORACLE_GTYPE_MULTIPOLYGON:
2319
                        return Geometry.TYPES.SURFACE;
2320

    
2321
                case OracleValues.ORACLE_GTYPE_COLLECTION:
2322
                        return Geometry.TYPES.AGGREGATE;
2323
                }
2324

    
2325
                logger.warn("Unknown oracle geometry type: " + otype);
2326

    
2327
                return Geometry.TYPES.NULL;
2328
        }
2329

    
2330
        /**
2331
         * Utility method to get struct's type.
2332
         * 
2333
         * @param the_data
2334
         *            the struct's datum array
2335
         * @return the struct type
2336
         */
2337
        public static int getStructType(Datum[] the_data) {
2338
                int resp = -1;
2339

    
2340
                try {
2341
                        resp = ((NUMBER) the_data[0]).intValue() % 1000;
2342
                } catch (SQLException se) {
2343
                        logger.error("Error: " + se.getMessage(), se);
2344
                }
2345

    
2346
                return resp;
2347
        }
2348

    
2349
        /**
2350
         * Utility method to get struct's SRID.
2351
         * 
2352
         * @param the_data
2353
         *            the struct's datum array
2354
         * @return the struct0's SRID
2355
         */
2356
        public static int getStructSRID(Datum[] the_data) {
2357
                int resp = -1;
2358

    
2359
                try {
2360
                        resp = ((NUMBER) the_data[1]).intValue();
2361
                } catch (SQLException se) {
2362
                        logger.error("Error: " + se.getMessage(), se);
2363
                }
2364

    
2365
                return resp;
2366
        }
2367

    
2368
        /**
2369
         * Utility method to find out if a struct is a circle.
2370
         * 
2371
         * @param the_data
2372
         *            the struct's datum array
2373
         * @return whether it is a circle
2374
         */
2375
        public static boolean isCircle(Datum[] the_data) {
2376
                int[] info = null;
2377

    
2378
                try {
2379
                        info = ((ARRAY) the_data[3]).getIntArray();
2380
                } catch (SQLException se) {
2381
                        logger.error("While cheking circle: " + se.getMessage(), se);
2382

    
2383
                        return false;
2384
                }
2385

    
2386
                if (info == null) {
2387
                        return false;
2388
                }
2389

    
2390
                boolean resp = ((info.length == 3) && (info[2] == 4));
2391

    
2392
                return resp;
2393
        }
2394

    
2395
        /**
2396
         * Gets the struct's dimension size.
2397
         * 
2398
         * @param st
2399
         *            the struct
2400
         * @return the structs dimension
2401
         */
2402
        public static int getStructDimensions(STRUCT st) {
2403
                int resp = -1;
2404

    
2405
                try {
2406
                        resp = ((NUMBER) st.getOracleAttributes()[0]).intValue() / 1000;
2407
                } catch (SQLException se) {
2408
                        logger.error("Error: " + se.getMessage(), se);
2409
                }
2410

    
2411
                if (resp < 2) {
2412
                        resp = 2;
2413
                }
2414

    
2415
                return resp;
2416
        }
2417
        
2418

    
2419

    
2420

    
2421
        /**
2422
         * Gets a struct's coordinates array.
2423
         * 
2424
         * @param the_data
2425
         *            the struct's datum array
2426
         * @return the coordinates array
2427
         */
2428
        public static double[] getOrds(Datum[] the_data) {
2429
                double[] resp = null;
2430

    
2431
                try {
2432
                        ARRAY aux = (ARRAY) the_data[4];
2433

    
2434
                        if (aux == null) {
2435
                                return null;
2436
                        }
2437

    
2438
                        resp = aux.getDoubleArray();
2439
                } catch (SQLException se) {
2440
                        logger.error("While getting ordinates: " + se.getMessage(), se);
2441
                }
2442

    
2443
                return resp;
2444
        }
2445

    
2446
        /**
2447
         * Utility method to create a struct with the given data.
2448
         * 
2449
         * @param type
2450
         *            struct type
2451
         * @param srid
2452
         *            coordinate system
2453
         * @param info
2454
         *            element info array
2455
         * @param ords
2456
         *            coordinates array
2457
         * @param conn
2458
         *            connection
2459
         * @return the created struct
2460
         */
2461
        public static STRUCT createStruct(NUMBER type, NUMBER srid, Datum[] info,
2462
                        Datum[] ords, Connection conn) {
2463
                try {
2464
                        StructDescriptor dsc = StructDescriptor.createDescriptor(
2465
                                        "MDSYS.SDO_GEOMETRY", conn);
2466
                        Object[] obj = new Object[5];
2467
                        obj[0] = type;
2468
                        obj[1] = srid;
2469
                        obj[2] = null;
2470
                        obj[3] = info;
2471
                        obj[4] = ords;
2472

    
2473
                        return new STRUCT(dsc, conn, obj);
2474
                } catch (SQLException se) {
2475
                        logger.error("While creating STRUCT: " + se.getMessage(), se);
2476
                }
2477

    
2478
                return null;
2479
        }
2480

    
2481
        /**
2482
         * 
2483
         * @param dim_info
2484
         * @return
2485
         */
2486
        public static String getDimInfoAsString(ARRAY dim_info) {
2487
                String resp = "DIMENSIONS: ";
2488

    
2489
                if (dim_info == null) {
2490
                        return "NULL" + "\n";
2491
                } else {
2492
                        try {
2493
                                Datum[] da = dim_info.getOracleArray();
2494
                                int size = da.length;
2495
                                resp = resp + size + "\n";
2496
                                for (int i = 0; i < size; i++) {
2497
                                        STRUCT dim_itemx = (STRUCT) da[i];
2498
                                        Object[] dim_desc = dim_itemx.getAttributes();
2499
                                        resp = resp + "DIMENSION " + i + ": " + ", NAME: "
2500
                                                        + dim_desc[0].toString() + ", MIN: "
2501
                                                        + dim_desc[1].toString() + ", MAX: "
2502
                                                        + dim_desc[2].toString() + ", TOL: "
2503
                                                        + dim_desc[3].toString();
2504
                                        if (i != (size - 1)) {
2505
                                                resp = resp + "\n";
2506
                                        }
2507
                                }
2508
                        } catch (Exception ex) {
2509
                                return "ERROR: " + ex.getMessage() + "\n";
2510
                        }
2511
                }
2512
                return resp;
2513
        }
2514

    
2515
        /**
2516
         * 
2517
         * @param conn
2518
         * @param fromStruct
2519
         * @param toSrid
2520
         * @return
2521
         */
2522
        public static STRUCT reprojectGeometry(Connection conn, STRUCT fromStruct,
2523
                        String toSrid) {
2524

    
2525
                String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2526
                STRUCT resp = null;
2527

    
2528
                try {
2529
                        PreparedStatement _st = conn.prepareStatement(qry);
2530
                        _st.setObject(1, fromStruct);
2531
                        ResultSet _rs = _st.executeQuery();
2532

    
2533
                        if (_rs.next()) {
2534
                                resp = (STRUCT) _rs.getObject(1);
2535
                        } else {
2536
                                logger
2537
                                                .error("While executing reprojection: empty resultset (?)");
2538
                                return fromStruct;
2539
                        }
2540
                } catch (Exception ex) {
2541
                        logger.error("While reprojecting: " + ex.getMessage());
2542
                        return fromStruct;
2543
                }
2544

    
2545
                if (resp == null) {
2546
                        return fromStruct;
2547
                } else {
2548
                        return resp;
2549
                }
2550
        }
2551

    
2552
        /**
2553
         * 
2554
         * @param st
2555
         */
2556
        public static void printStruct(STRUCT st) {
2557

    
2558
                logger.debug("----------------------------------------------");
2559
                logger.debug("-- 16 FEBRERO 2009 ---------------------------");
2560
                logger.debug("----------------------------------------------");
2561

    
2562
                try {
2563
                        Object[] att = st.getAttributes();
2564
                        int l = att.length;
2565

    
2566
                        for (int i = 0; i < l; i++) {
2567
                                if (att[i] != null) {
2568
                                        if (att[i] instanceof ARRAY) {
2569
                                                ARRAY arr = (ARRAY) att[i];
2570
                                                logger.debug("ATT " + i + ": ");
2571
                                                printARRAY(arr);
2572
                                        } else {
2573
                                                logger.debug("ATT " + i + ": " + att[i].toString());
2574
                                        }
2575
                                        logger
2576
                                                        .debug("----------------------------------------------");
2577
                                }
2578
                        }
2579
                } catch (Exception ex) {
2580
                        logger.debug("-- Error: " + ex.getMessage());
2581
                }
2582

    
2583
        }
2584

    
2585
        /**
2586
         * 
2587
         * @param arr
2588
         * @throws Exception
2589
         */
2590
        private static void printARRAY(ARRAY arr) throws Exception {
2591

    
2592
                int[] intarr = arr.getIntArray();
2593
                if (intarr == null) {
2594
                        float[] floarr = arr.getFloatArray();
2595
                        if (floarr == null) {
2596
                                logger.debug("INT NULL y FLOAT NULL (?)");
2597
                        } else {
2598
                                int len = floarr.length;
2599
                                for (int i = 0; i < len; i++) {
2600
                                        if (Math.min(i, (len - i)) < 20) {
2601
                                                logger.debug("" + floarr[i]);
2602
                                        }
2603
                                }
2604
                        }
2605

    
2606
                } else {
2607
                        int len = intarr.length;
2608
                        for (int i = 0; i < len; i++) {
2609
                                if (Math.min(i, (len - i)) < 20) {
2610
                                        logger.debug("" + intarr[i]);
2611
                                }
2612
                        }
2613
                }
2614
        }
2615

    
2616
        /**
2617
         * Utility method. Gets FShape type from oracle geometry type.
2618
         * 
2619
         * @param otype
2620
         * @return FShape type
2621
         */
2622
        public static int oracleGTypeToFShapeType(int otype, boolean complex) {
2623

    
2624
                int resp = Geometry.TYPES.NULL;
2625

    
2626
                if (complex) {
2627

    
2628
                        switch (otype) {
2629
                        case OracleValues.ORACLE_GTYPE_COMPLEX_VOIDED_POLYON:
2630
                        case OracleValues.ORACLE_GTYPE_COMPLEX_COMPOUND_POLYON:
2631
                                resp = Geometry.TYPES.SURFACE;
2632
                                break;
2633
                        case OracleValues.ORACLE_GTYPE_COMPLEX_COMPOUND_LINE:
2634
                                resp = Geometry.TYPES.CURVE;
2635
                                break;
2636
                        }
2637

    
2638
                } else {
2639

    
2640
                        // =========== not complex =================
2641
                        switch (otype) {
2642
                        case OracleValues.ORACLE_GTYPE_UNKNOWN:
2643
                                resp = Geometry.TYPES.NULL;
2644
                                break;
2645

    
2646
                        case OracleValues.ORACLE_GTYPE_POINT:
2647
                        case OracleValues.ORACLE_GTYPE_MULTIPOINT:
2648
                                resp = Geometry.TYPES.POINT;
2649
                                break;
2650

    
2651
                        case OracleValues.ORACLE_GTYPE_LINE:
2652
                        case OracleValues.ORACLE_GTYPE_MULTILINE:
2653
                                resp = Geometry.TYPES.CURVE;
2654
                                break;
2655

    
2656
                        case OracleValues.ORACLE_GTYPE_POLYGON:
2657
                        case OracleValues.ORACLE_GTYPE_MULTIPOLYGON:
2658
                                resp = Geometry.TYPES.SURFACE;
2659
                                break;
2660

    
2661
                        case OracleValues.ORACLE_GTYPE_COLLECTION:
2662
                                resp = Geometry.TYPES.AGGREGATE;
2663
                                break;
2664
                        }
2665
                        // =========== not complex =================
2666
                }
2667

    
2668
                if (resp == Geometry.TYPES.NULL) {
2669
                        logger.error("Unknown oracle geometry type: " + otype);
2670
                }
2671
                return resp;
2672
        }
2673

    
2674
        /**
2675
         * 
2676
         * @param name
2677
         * @param arr
2678
         * @return
2679
         */
2680
        private static boolean isOneOfThese(String name, String[] arr) {
2681

    
2682
                for (int i = 0; i < arr.length; i++) {
2683
                        if (arr[i].compareToIgnoreCase(name) == 0)
2684
                                return true;
2685
                }
2686
                return false;
2687
        }
2688

    
2689
        /**
2690
         * 
2691
         * @param tt
2692
         * @param are_dims
2693
         * @return
2694
         */
2695
        public static boolean hasSeveralGeometryTypes(List tt, boolean are_dims) {
2696
                if (tt.size() == 0) {
2697
                        return false;
2698
                }
2699

    
2700
                HashMap m = new HashMap();
2701

    
2702
                for (int i = 0; i < tt.size(); i++) {
2703
                        Integer integ = (Integer) tt.get(i);
2704
                        int val = integ.intValue();
2705

    
2706
                        if ((val == 4) && (!are_dims)) {
2707
                                return true;
2708
                        }
2709

    
2710
                        m.put("" + (val % 4), "a type");
2711
                }
2712

    
2713
                Iterator iter = m.keySet().iterator();
2714
                iter.next();
2715

    
2716
                return iter.hasNext();
2717
        }
2718

    
2719
        /**
2720
         * 
2721
         */
2722
        public static void showMemory() {
2723
                Runtime r = Runtime.getRuntime();
2724
                long mem = r.totalMemory() - r.freeMemory();
2725
                logger.info("Total memory : " + mem);
2726
        }
2727

    
2728
        /**
2729
         * 
2730
         * @param input
2731
         * @param ind
2732
         * @param n
2733
         * @return
2734
         */
2735
        private static double[] getIndDoublesModule(double[] input, int ind, int n) {
2736
                int size = input.length / n;
2737
                double[] resp = new double[size];
2738

    
2739
                for (int i = 0; i < size; i++) {
2740
                        resp[i] = input[(i * n) + ind];
2741
                }
2742

    
2743
                return resp;
2744
        }
2745

    
2746
        /**
2747
         * 
2748
         * @param input
2749
         * @param ind
2750
         * @param n
2751
         * @return
2752
         */
2753
        private static double[] getIndBigDecimalModule(double[] input, int ind,
2754
                        int n) {
2755
                int size = input.length / n;
2756
                double[] resp = new double[size];
2757

    
2758
                for (int i = 0; i < size; i++) {
2759
                        resp[i] = input[(i * n) + ind];
2760
                }
2761

    
2762
                return resp;
2763
        }
2764

    
2765
        /**
2766
         * 
2767
         * @param the_data
2768
         * @param dim
2769
         * @return
2770
         * @throws CreateGeometryException
2771
         */
2772
        public static Geometry getFMapGeometryMultipolygon(Datum[] the_data, int dim)
2773
                        throws CreateGeometryException {
2774

    
2775
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2776

    
2777
                Geometry geom = null;
2778

    
2779
                if (OracleUtils.isCircle(the_data)) {
2780
                        geom = getCircleFromStruct(the_data);
2781
                } else {
2782
                        GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2783

    
2784
                        if (dim == 2) {
2785
                                geom = geomManager.createSurface(gpx, Geometry.SUBTYPES.GEOM2D);
2786
                        } else {
2787
                                double[] ords = null;
2788

    
2789
                                try {
2790
                                        ords = ((ARRAY) the_data[4]).getDoubleArray();
2791
                                } catch (SQLException se) {
2792
                                        logger.error("While getting ordinates: " + se.getMessage(),
2793
                                                        se);
2794
                                }
2795

    
2796
                                double[] z = getIndBigDecimalModule(ords, 2, dim);
2797
                                geom = geomManager
2798
                                                .createSurface(gpx, Geometry.SUBTYPES.GEOM2DZ);
2799
                                for (int i = 0; i < z.length; i++) {
2800
                                        ((Surface2DZ) geom).setCoordinateAt(i, 3, z[i]);
2801
                                }
2802
                        }
2803
                }
2804

    
2805
                return geom;
2806
        }
2807

    
2808
        /**
2809
         * 
2810
         * @param the_data
2811
         * @return
2812
         * @throws CreateGeometryException
2813
         */
2814
        private static Geometry getCircleFromStruct(Datum[] the_data)
2815
                        throws CreateGeometryException {
2816

    
2817
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2818

    
2819
                double[] threep = null;
2820

    
2821
                try {
2822
                        threep = ((ARRAY) the_data[4]).getDoubleArray();
2823
                } catch (SQLException se) {
2824
                        logger.error("While getting ords from struct: " + se.getMessage(),
2825
                                        se);
2826

    
2827
                        return geomManager.createNullGeometry(Geometry.SUBTYPES.GEOM2D);
2828
                }
2829

    
2830
                Point2D[] three = new Point2D.Double[3];
2831
                three[0] = new Point2D.Double(threep[0], threep[1]);
2832
                three[1] = new Point2D.Double(threep[2], threep[3]);
2833
                three[2] = new Point2D.Double(threep[4], threep[5]);
2834

    
2835
                Object[] cent_rad = OracleUtils.getCenterAndRadiousOfCirc(three);
2836

    
2837
                Point2D cent = (Point2D) cent_rad[0];
2838
                double radious = ((Double) cent_rad[1]).doubleValue();
2839

    
2840
                Geometry circ = geomManager.create(Geometry.TYPES.CIRCLE,
2841
                                Geometry.SUBTYPES.GEOM2D);
2842
                ((Circle2D) circ).setPoints(cent, radious);
2843

    
2844
                return circ;
2845
        }
2846

    
2847
        /**
2848
         * 
2849
         * @param the_data
2850
         * @param dim
2851
         * @return
2852
         * @throws CreateGeometryException
2853
         */
2854
        public static Geometry getFMapGeometryMultiLineString(Datum[] the_data,
2855
                        int dim) throws CreateGeometryException {
2856

    
2857
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2858

    
2859
                GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2860
                Geometry geom = null;
2861
                double[] ords = null;
2862

    
2863
                if (dim == 2) {
2864
                        geom = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM2D);
2865
                } else {
2866
                        ords = OracleUtils.getOrds(the_data);
2867

    
2868
                        double[] z = getIndBigDecimalModule(ords, 2, dim);
2869
                        geom = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM2DZ);
2870
                        for (int i = 0; i < z.length; i++) {
2871
                                ((Curve2DZ) geom).setCoordinateAt(i, 3, z[i]);
2872
                        }
2873
                }
2874

    
2875
                return geom;
2876
        }
2877

    
2878
        /**
2879
         * 
2880
         * @param the_data
2881
         * @param dim
2882
         * @return
2883
         * @throws CreateGeometryException
2884
         */
2885
        public static Geometry getFMapGeometryPoint(Datum[] the_data, int dim)
2886
                        throws CreateGeometryException {
2887

    
2888
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2889

    
2890
                double[] ords = OracleUtils.getOrds(the_data);
2891

    
2892
                if (ords == null) { // sdo_point
2893

    
2894
                        return getFMapGeometrySdoPoint(the_data, dim);
2895
                }
2896

    
2897
                Geometry geom = null;
2898
                int total_size = ords.length;
2899
                int no_po = total_size / dim;
2900
                double[] x = new double[no_po];
2901
                double[] y = new double[no_po];
2902
                double[] z = new double[no_po];
2903

    
2904
                for (int i = 0; i < no_po; i++) {
2905
                        x[i] = ords[i * dim]; // pp[i].getX();
2906
                        y[i] = ords[(i * dim) + 1];
2907

    
2908
                        if (dim >= 3) {
2909
                                z[i] = ords[(i * dim) + 2];
2910
                        }
2911
                }
2912

    
2913
                if (dim == 2) {
2914
                        if (no_po == 1) {
2915
                                geom = geomManager.createPoint(x[0], y[0],
2916
                                                Geometry.SUBTYPES.GEOM2D);
2917
                        } else {
2918
                                geom = geomManager.create(Geometry.TYPES.MULTIPOINT,
2919
                                                Geometry.SUBTYPES.GEOM2D);
2920

    
2921
                                ((MultiPoint2D) geom).setPoints(x, y);
2922
                        }
2923
                } else {
2924
                        if (no_po == 1) {
2925
                                geom = geomManager.createPoint(x[0], y[0],
2926
                                                Geometry.SUBTYPES.GEOM2DZ);
2927
                                ((Point2DZ) geom).setCoordinateAt(3, z[0]);
2928
                        } else {
2929
                                geom = geomManager.create(Geometry.TYPES.MULTIPOINT,
2930
                                                Geometry.SUBTYPES.GEOM2DZ);
2931
                                ((MultiPoint2DZ) geom).setPoints(x, y);
2932
                                Point2DZ pto = null;
2933
                                for (int i = 0; i < x.length; i++) {
2934
                                        pto = (Point2DZ) geomManager.create(Geometry.TYPES.POINT,
2935
                                                        Geometry.SUBTYPES.GEOM2DZ);
2936
                                        pto.setX(x[i]);
2937
                                        pto.setY(y[i]);
2938
                                        pto.setCoordinateAt(3, z[i]);
2939
                                        ((MultiPoint2DZ) geom).addPoint(pto);
2940
                                }
2941
                        }
2942
                }
2943

    
2944
                return geom;
2945
        }
2946

    
2947
        /**
2948
         * 
2949
         * @param the_data
2950
         * @param d
2951
         * @return
2952
         * @throws CreateGeometryException
2953
         */
2954
        public static Geometry getFMapGeometrySdoPoint(Datum[] the_data, int d)
2955
                        throws CreateGeometryException {
2956

    
2957
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2958

    
2959
                double x = 0;
2960
                double y = 0;
2961
                double z = 0;
2962

    
2963
                try {
2964
                        Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
2965
                        x = ((NUMBER) aux[0]).doubleValue();
2966
                        y = ((NUMBER) aux[1]).doubleValue();
2967

    
2968
                        if (d > 2) {
2969
                                z = ((NUMBER) aux[2]).doubleValue();
2970
                        }
2971
                } catch (SQLException se) {
2972
                        logger.error("While getting sdo point ordinates: "
2973
                                        + se.getMessage(), se);
2974
                }
2975

    
2976
                Geometry geom = null;
2977

    
2978
                if (d == 2) {
2979
                        geom = geomManager.createPoint(x, y, Geometry.SUBTYPES.GEOM2D);
2980
                } else {
2981

    
2982
                        Point2DZ point = (Point2DZ) geomManager.create(
2983
                                        Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM2DZ);
2984
                        point.setX(x);
2985
                        point.setY(y);
2986
                        point.setCoordinateAt(3, z);
2987
                        geom = point;
2988
                }
2989

    
2990
                return geom;
2991
        }
2992

    
2993
        /**
2994
         * 
2995
         * @param the_data
2996
         * @return
2997
         */
2998
        public static boolean isActuallyACollection(Datum[] the_data) {
2999
                int[] info = null;
3000

    
3001
                try {
3002
                        ARRAY aux = (ARRAY) the_data[3];
3003

    
3004
                        if (aux == null) {
3005
                                return false;
3006
                        }
3007

    
3008
                        info = aux.getIntArray();
3009
                } catch (SQLException se) {
3010
                        logger.error("While checking collection: " + se.getMessage());
3011
                        return false;
3012
                }
3013

    
3014
                if (info == null) {
3015
                        return false; // sdo_point
3016
                }
3017

    
3018
                int size = info.length / 3;
3019

    
3020
                if (size == 1) {
3021
                        return false;
3022
                }
3023

    
3024
                if (size == 2) {
3025
                        return ((info[1] % 1000) != (info[4] % 1000))
3026
                                        && (!((info[1] == 1005) && (info[4] == 2)));
3027
                }
3028

    
3029
                int second = info[4] % 1000;
3030
                int item = 0;
3031

    
3032
                for (int i = 2; i < size; i++) {
3033
                        item = info[(i * 3) + 1] % 1000;
3034
                        if ((item != second) && (!((item == 5) && (second == 2)))) {
3035
                                return true;
3036
                        }
3037
                }
3038

    
3039
                return false;
3040
        }
3041

    
3042
        /**
3043
         * 
3044
         * @param info
3045
         * @return
3046
         */
3047
        public static Datum[] updateIndexes(Datum[] info) {
3048
                int size = info.length / 3;
3049
                NUMBER[] resp = new NUMBER[3 * size];
3050

    
3051
                try {
3052
                        int rest = info[0].intValue() - 1;
3053

    
3054
                        for (int i = 0; i < size; i++) {
3055
                                resp[3 * i] = new NUMBER(info[3 * i].intValue() - rest);
3056
                                resp[(3 * i) + 1] = new NUMBER(info[(3 * i) + 1].intValue());
3057
                                resp[(3 * i) + 2] = new NUMBER(info[(3 * i) + 2].intValue());
3058
                        }
3059
                } catch (SQLException se) {
3060
                        logger.error("Unexpected error: " + se.getMessage());
3061
                }
3062

    
3063
                return resp;
3064
        }
3065

    
3066
        /**
3067
         * 
3068
         * @param all
3069
         * @param first_inc
3070
         * @param last_inc
3071
         * @return
3072
         */
3073
        public static double[] getSubSet(double[] all, int first_inc, int last_inc) {
3074
                double[] resp = new double[last_inc - first_inc + 1];
3075

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

    
3080
                return resp;
3081
        }
3082

    
3083
        /**
3084
         * 
3085
         * @param all
3086
         * @param groups
3087
         * @return
3088
         * @throws SQLException
3089
         */
3090
        public static Object[] getOrdOfGroups(Datum[] all, Object[] groups)
3091
                        throws SQLException {
3092
                Object[] resp = new Object[groups.length];
3093

    
3094
                if (resp.length == 1) {
3095
                        resp[0] = all;
3096

    
3097
                        return resp;
3098
                }
3099

    
3100
                int ind = 0;
3101
                Datum[] aux = (Datum[]) groups[1];
3102
                int _end = aux[0].intValue() - 2;
3103
                Datum[] ord_aux = getSubSet(all, 0, _end);
3104

    
3105
                int _start = _end + 1;
3106
                resp[ind] = ord_aux;
3107
                ind++;
3108

    
3109
                for (int i = 2; i < groups.length; i++) {
3110
                        aux = (Datum[]) groups[i];
3111
                        _end = aux[0].intValue() - 2;
3112
                        ord_aux = getSubSet(all, _start, _end);
3113
                        resp[ind] = ord_aux;
3114
                        ind++;
3115
                        _start = _end + 1;
3116
                }
3117

    
3118
                // last
3119
                _end = all.length - 1;
3120
                ord_aux = getSubSet(all, _start, _end);
3121
                resp[groups.length - 1] = ord_aux;
3122

    
3123
                return resp;
3124
        }
3125

    
3126
        /**
3127
         * 
3128
         * @param all
3129
         * @param groups
3130
         * @return
3131
         */
3132
        public static Object[] getOrdOfGroups(double[] all, Object[] groups) {
3133
                Object[] resp = new Object[groups.length];
3134

    
3135
                if (resp.length == 1) {
3136
                        resp[0] = all;
3137

    
3138
                        return resp;
3139
                }
3140

    
3141
                int ind = 0;
3142
                int[] aux = (int[]) groups[1];
3143
                int _end = aux[0] - 2;
3144
                double[] ord_aux = getSubSet(all, 0, _end);
3145

    
3146
                int _start = _end + 1;
3147
                resp[ind] = ord_aux;
3148
                ind++;
3149

    
3150
                for (int i = 2; i < groups.length; i++) {
3151
                        aux = (int[]) groups[i];
3152
                        _end = aux[0] - 2;
3153
                        ord_aux = getSubSet(all, _start, _end);
3154
                        resp[ind] = ord_aux;
3155
                        ind++;
3156
                        _start = _end + 1;
3157
                }
3158

    
3159
                // last
3160
                _end = all.length - 1;
3161
                ord_aux = getSubSet(all, _start, _end);
3162
                resp[groups.length - 1] = ord_aux;
3163

    
3164
                return resp;
3165
        }
3166

    
3167
        /**
3168
         * 
3169
         * @param all_elem
3170
         * @return
3171
         */
3172
        public static Object[] groupByElement(int[] all_elem) {
3173
                List resp = new ArrayList();
3174

    
3175
                int size = all_elem.length / 3;
3176

    
3177
                int[] aux = getNthGroupOfThree(all_elem, 0);
3178

    
3179
                int[] newaux;
3180
                int i = 1;
3181

    
3182
                while (i < size) {
3183
                        newaux = getNthGroupOfThree(all_elem, i);
3184

    
3185
                        if (newaux[0] == aux[0]) {
3186
                                // aux[2] says how many components
3187
                                for (int j = 0; j < aux[2]; j++) {
3188
                                        aux = appendIntArrays(aux, getNthGroupOfThree(all_elem, j
3189
                                                        + i));
3190
                                }
3191

    
3192
                                resp.add(aux);
3193
                                i = i + aux[2];
3194
                                aux = getNthGroupOfThree(all_elem, i);
3195
                        } else {
3196
                                if (newaux[1] == 2003) {
3197
                                        aux = appendIntArrays(aux, newaux);
3198
                                } else {
3199
                                        resp.add(aux);
3200
                                        aux = getNthGroupOfThree(all_elem, i);
3201
                                }
3202
                        }
3203

    
3204
                        i++;
3205
                }
3206

    
3207
                resp.add(aux);
3208

    
3209
                return resp.toArray();
3210
        }
3211

    
3212
        /**
3213
         * 
3214
         * @param all_elem
3215
         * @return
3216
         */
3217
        public static boolean isSimpleCollectionOfLines(Datum[] all_elem) {
3218

    
3219
                try {
3220
                        int size = all_elem.length;
3221
                        if (all_elem[1].intValue() != 4)
3222
                                return false;
3223
                        int size3 = size / 3;
3224

    
3225
                        for (int i = 1; i < size3; i++) {
3226
                                if (all_elem[3 * i + 1].intValue() != 2)
3227
                                        return false;
3228
                        }
3229
                        return true;
3230

    
3231
                } catch (SQLException ex) {
3232
                        logger.error("While is simple line collection: " + ex.getMessage());
3233
                }
3234

    
3235
                return false;
3236
        }
3237

    
3238
        /**
3239
         * 
3240
         * @param elem
3241
         * @return
3242
         */
3243
        public static Datum[] removeThreeFirst(Datum[] elem) {
3244
                int sz = elem.length;
3245
                Datum[] resp = new Datum[sz - 3];
3246
                for (int i = 3; i < sz; i++)
3247
                        resp[i - 3] = elem[i];
3248
                return resp;
3249
        }
3250

    
3251
        /**
3252
         * 
3253
         * @param all_elem
3254
         * @return
3255
         */
3256
        public static Object[] groupByElement(Datum[] all_elem) {
3257

    
3258
                if (isSimpleCollectionOfLines(all_elem)) {
3259
                        Object[] r = new Object[1];
3260
                        r[0] = removeThreeFirst(all_elem);
3261
                        return r;
3262
                }
3263

    
3264
                List resp = new ArrayList();
3265

    
3266
                int size = all_elem.length / 3;
3267

    
3268
                Datum[] aux = getNthGroupOfThree(all_elem, 0);
3269

    
3270
                Datum[] newaux;
3271
                int i = 1;
3272
                boolean add_last_time = true;
3273

    
3274
                try {
3275
                        while (i < size) {
3276
                                newaux = getNthGroupOfThree(all_elem, i);
3277

    
3278
                                if (newaux[0].intValue() == aux[0].intValue()) {
3279
                                        // aux[2] says how many components
3280
                                        for (int j = 0; j < ((NUMBER) aux[2]).intValue(); j++) {
3281
                                                aux = appendDatArrays(aux, getNthGroupOfThree(all_elem,
3282
                                                                j + i));
3283
                                        }
3284

    
3285
                                        resp.add(aux);
3286
                                        i = i + ((NUMBER) aux[2]).intValue();
3287
                                        if (i < size) { // in some cases (line collection, 4)
3288
                                                aux = getNthGroupOfThree(all_elem, i);
3289
                                        } else {
3290
                                                add_last_time = false;
3291
                                        }
3292
                                } else {
3293
                                        if (((NUMBER) newaux[1]).intValue() == 2003) {
3294
                                                aux = appendDatArrays(aux, newaux);
3295
                                        } else {
3296
                                                resp.add(aux);
3297
                                                aux = getNthGroupOfThree(all_elem, i);
3298
                                        }
3299
                                }
3300

    
3301
                                i++;
3302
                        }
3303
                } catch (SQLException se) {
3304
                        logger.error("Unexpected error: " + se.getMessage());
3305
                }
3306

    
3307
                if (add_last_time) {
3308
                        resp.add(aux);
3309
                }
3310

    
3311
                return resp.toArray();
3312
        }
3313

    
3314
        /**
3315
         * 
3316
         * @param r
3317
         * @param hasSrid
3318
         * @param isView
3319
         * @param _isGeogCS
3320
         * @param _oracleSRID
3321
         * @param __conn
3322
         * @return
3323
         */
3324
        public static STRUCT rectangleToStruct(Rectangle2D r, boolean hasSrid,
3325
                        boolean isView, boolean _isGeogCS, String osrid, Connection __conn) {
3326
                Point2D c1 = new Point2D.Double(r.getMinX(), r.getMinY());
3327
                Point2D c2 = new Point2D.Double(r.getMaxX(), r.getMaxY());
3328

    
3329
                if ((_isGeogCS) && (isView)) {
3330
                        c1.setLocation(Math.max(c1.getX(), -180), Math.max(c1.getY(), -90));
3331
                        c2.setLocation(Math.min(c2.getX(), 180), Math.min(c2.getY(), 90));
3332
                }
3333

    
3334
                STRUCT resp = null;
3335

    
3336
                try {
3337

    
3338
                        int size = 5;
3339
                        Object[] new_obj = new Object[size];
3340

    
3341
                        new_obj[0] = new NUMBER(2003);
3342

    
3343
                        if (hasSrid) {
3344
                                new_obj[1] = new NUMBER(osrid);
3345
                        } else {
3346
                                new_obj[1] = null;
3347
                        }
3348

    
3349
                        new_obj[2] = null;
3350

    
3351
                        NUMBER[] elem_info = new NUMBER[3];
3352
                        elem_info[0] = new NUMBER(1);
3353
                        elem_info[1] = new NUMBER(1003);
3354
                        elem_info[2] = new NUMBER(3);
3355
                        new_obj[3] = elem_info;
3356

    
3357
                        NUMBER[] ords = null;
3358
                        ords = new NUMBER[4];
3359
                        ords[0] = new NUMBER(c1.getX());
3360
                        ords[1] = new NUMBER(c1.getY());
3361
                        ords[2] = new NUMBER(c2.getX());
3362
                        ords[3] = new NUMBER(c2.getY());
3363
                        new_obj[4] = ords;
3364

    
3365
                        StructDescriptor dsc = StructDescriptor.createDescriptor(
3366
                                        "MDSYS.SDO_GEOMETRY", __conn);
3367

    
3368
                        resp = new STRUCT(dsc, __conn, new_obj);
3369
                } catch (Exception ex) {
3370
                        logger.error(
3371
                                        "Error while creating rect struct: " + ex.getMessage(), ex);
3372
                }
3373

    
3374
                return resp;
3375
        }
3376

    
3377
        /**
3378
         * 
3379
         * @param r1
3380
         * @param r2
3381
         * @return
3382
         */
3383
        public static Rectangle2D doIntersect(Rectangle2D r1, Rectangle2D r2) {
3384
                if (r1.getMaxX() <= r2.getMinX()) {
3385
                        return null;
3386
                }
3387

    
3388
                if (r2.getMaxX() <= r1.getMinX()) {
3389
                        return null;
3390
                }
3391

    
3392
                if (r1.getMaxY() <= r2.getMinY()) {
3393
                        return null;
3394
                }
3395

    
3396
                if (r2.getMaxY() <= r1.getMinY()) {
3397
                        return null;
3398
                }
3399

    
3400
                double minx = Math.max(r1.getMinX(), r2.getMinX());
3401
                double miny = Math.max(r1.getMinY(), r2.getMinY());
3402
                double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
3403
                double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
3404

    
3405
                double w = maxx - minx;
3406
                double h = maxy - miny;
3407

    
3408
                return new Rectangle2D.Double(minx, miny, w, h);
3409
        }
3410

    
3411
        /**
3412
         * Utility method to find out if a coordinate system is geodetic or not.
3413
         * 
3414
         * @param oracleSRID2
3415
         *            the coordinate system's oracle code
3416
         * @param thas
3417
         *            whether the table has a coordinate system set. if not, the
3418
         *            method returns false.
3419
         * @return whether the coordinate system is geodetic or not.
3420
         */
3421
        public static boolean getIsGCS(String oracleSRID2, boolean thas) {
3422

    
3423
                if (!thas)
3424
                        return false;
3425
                if (oracleSRID2 == null)
3426
                        return false;
3427

    
3428
                int ora_cs = 0;
3429

    
3430
                try {
3431
                        ora_cs = Integer.parseInt(oracleSRID2);
3432
                } catch (Exception ex) {
3433
                        return false;
3434
                }
3435

    
3436
                if (((ora_cs >= 8000) && (ora_cs <= 8999)) || (ora_cs == 524288)) {
3437
                        return true;
3438
                } else {
3439
                        return false;
3440
                }
3441
        }
3442

    
3443
        /**
3444
         * 
3445
         * @param sample input STRUCT
3446
         * @return type and subtype of geometry
3447
         * @throws SQLException
3448
         */
3449
        public static int[] getGeoTypeSubTypeOfStruct(STRUCT sample) throws SQLException {
3450

    
3451
                int _code = ((NUMBER) sample.getOracleAttributes()[0]).intValue();
3452
                return getGeoTypeSubTypeOfOracleCode(_code);
3453
        }
3454

    
3455
        
3456
        public static int[] getGeoTypeSubTypeOfOracleCode(int code) {
3457

    
3458
                // [TYPES.?, SUBTYPES.?]
3459
                int[] resp = new int[2];
3460
                
3461
                int type_part = code % 10;
3462
                int dim_part = code / 1000;
3463

    
3464
                resp[1] = SUBTYPES.GEOM2D;
3465
                if (dim_part == 3) {
3466
                        resp[1] = SUBTYPES.GEOM3D;
3467
                } else {
3468
                        if (dim_part == 4) {
3469
                                resp[1] = SUBTYPES.GEOM3DM;
3470
                        }
3471
                }
3472

    
3473
                resp[0] = TYPES.GEOMETRY;
3474
                
3475
                switch (type_part) {
3476
                case 1:
3477
                        resp[0] = Geometry.TYPES.POINT;
3478
                        break;
3479
                case 2:
3480
                        resp[0] = Geometry.TYPES.CURVE;
3481
                        break;
3482
                case 3:
3483
                        resp[0] = Geometry.TYPES.SURFACE;
3484
                        break;
3485
                case 4:
3486
                        resp[0] = Geometry.TYPES.AGGREGATE;
3487
                        break;
3488
                case 5:
3489
                        resp[0] = Geometry.TYPES.MULTIPOINT;
3490
                        break;
3491
                case 6:
3492
                        resp[0] = Geometry.TYPES.CURVE;
3493
                        break;
3494
                case 7:
3495
                        resp[0] = Geometry.TYPES.SURFACE;
3496
                        break;
3497
                default:
3498
                        logger.error("Unknown geometry type: " + code);
3499
                break;
3500
                }
3501

    
3502
                return resp;
3503
        }
3504
        /**
3505
         * 
3506
         * @param info
3507
         * @return
3508
         */
3509
        public static int[] updateIndexes(int[] info) {
3510
                int size = info.length / 3;
3511
                int[] resp = new int[3 * size];
3512
                int rest = info[0] - 1;
3513

    
3514
                for (int i = 0; i < size; i++) {
3515
                        resp[3 * i] = info[3 * i] - rest;
3516
                        resp[(3 * i) + 1] = info[(3 * i) + 1];
3517
                        resp[(3 * i) + 2] = info[(3 * i) + 2];
3518
                }
3519

    
3520
                return resp;
3521
        }
3522

    
3523
        /**
3524
         * 
3525
         * @param head
3526
         * @param tail
3527
         * @return
3528
         */
3529
        public static int[] appendIntArrays(int[] head, int[] tail) {
3530
                int[] resp = new int[head.length + tail.length];
3531
                int hsize = head.length;
3532

    
3533
                for (int i = 0; i < hsize; i++) {
3534
                        resp[i] = head[i];
3535
                }
3536

    
3537
                for (int i = 0; i < tail.length; i++) {
3538
                        resp[hsize + i] = tail[i];
3539
                }
3540

    
3541
                return resp;
3542
        }
3543

    
3544
        /**
3545
         * 
3546
         * @param head
3547
         * @param tail
3548
         * @return
3549
         */
3550
        public static Datum[] appendDatArrays(Datum[] head, Datum[] tail) {
3551
                Datum[] resp = new Datum[head.length + tail.length];
3552
                int hsize = head.length;
3553

    
3554
                for (int i = 0; i < hsize; i++) {
3555
                        resp[i] = head[i];
3556
                }
3557

    
3558
                for (int i = 0; i < tail.length; i++) {
3559
                        resp[hsize + i] = tail[i];
3560
                }
3561

    
3562
                return resp;
3563
        }
3564

    
3565
        /**
3566
         * 
3567
         * @param list
3568
         * @param n
3569
         * @return
3570
         */
3571
        public static int[] getNthGroupOfThree(int[] list, int n) {
3572
                int[] resp = new int[3];
3573
                resp[0] = list[3 * n];
3574
                resp[1] = list[(3 * n) + 1];
3575
                resp[2] = list[(3 * n) + 2];
3576

    
3577
                return resp;
3578
        }
3579

    
3580
        /**
3581
         * 
3582
         * @param list
3583
         * @param n
3584
         * @return
3585
         */
3586
        public static Datum[] getNthGroupOfThree(Datum[] list, int n) {
3587
                Datum[] resp = new Datum[3];
3588
                resp[0] = list[3 * n];
3589
                resp[1] = list[(3 * n) + 1];
3590
                resp[2] = list[(3 * n) + 2];
3591

    
3592
                return resp;
3593
        }
3594

    
3595
        /**
3596
         * 
3597
         * @param all
3598
         * @param first_inc
3599
         * @param last_inc
3600
         * @return
3601
         */
3602
        public static Datum[] getSubSet(Datum[] all, int first_inc, int last_inc) {
3603
                Datum[] resp = new Datum[last_inc - first_inc + 1];
3604

    
3605
                for (int i = first_inc; i <= last_inc; i++) {
3606
                        resp[i - first_inc] = all[i];
3607
                }
3608

    
3609
                return resp;
3610
        }
3611

    
3612
        /**
3613
         * 
3614
         * @param _type
3615
         * @return
3616
         */
3617
        public static int maxSizeForFieldType(int _type) {
3618
                switch (_type) {
3619
                case Types.VARCHAR:
3620
                        return OracleValues.VARCHAR2_STANDARD_SIZE;
3621

    
3622
                case Types.LONGVARCHAR:
3623
                        return OracleValues.VARCHAR2_LONG_SIZE;
3624
                }
3625

    
3626
                return -1;
3627
        }
3628

    
3629
        /**
3630
         * 
3631
         * @param tname
3632
         * @param suffix
3633
         * @return
3634
         */
3635
        public static String getDerivedName(String tname, String suffix) {
3636
                int ind = tname.lastIndexOf(".");
3637
                if (ind == -1) {
3638
                        int l = Math.min(28, tname.length());
3639
                        return tname.substring(0, l) + "_" + suffix;
3640
                } else {
3641
                        String pre = tname.substring(0, ind);
3642
                        String post = tname.substring(ind + 1, tname.length());
3643
                        int lpost = Math.min(24, post.length());
3644
                        int lpre = Math.min(3, pre.length());
3645
                        return pre.substring(0, lpre) + "_" + post.substring(0, lpost)
3646
                                        + "_" + suffix;
3647
                }
3648
        }
3649

    
3650
        /**
3651
         * Converts Geometry to STRUCT
3652
         * 
3653
         * @param geom
3654
         *            the geometry to convert
3655
         * @param _forced_type
3656
         *            forced type to use
3657
         * @param _conn
3658
         *            connection
3659
         * @param _o_srid
3660
         *            SRS (oracle code)
3661
         * @param withSrid
3662
         *            whether this STRUCT has a non-NULL SRS
3663
         * @param agu_bien
3664
         *            whether or not to check the correctness of the holes
3665
         * @param _isGeoCS
3666
         *            whether the SRS is geodetic or not
3667
         * @return the generated STRUCT
3668
         * @throws SQLException
3669
         */
3670
        public static STRUCT buildSTRUCT(Geometry geom, int _forced_type,
3671
                        Connection conn, String osrid, boolean withSrid, boolean agu_bien,
3672
                        boolean _isGeoCS) { // throws SQLException {
3673
                if (geom instanceof Complex) {
3674
                        // Complex coll = (Complex) geom;
3675
                        //
3676
                        // return appendGeometriesInStruct(coll, _forced_type, conn, osrid,
3677
                        // withSrid, agu_bien, _isGeoCS);
3678
                        return null;
3679
                } else {
3680
                        // Shape shp = geom.getInternalShape();
3681
                        int osridd = withSrid ? Integer.parseInt(osrid) : 0;
3682
                        STRUCT resp = null;
3683
                        try {
3684
                                resp = geometryToSTRUCT(geom, conn, osridd, agu_bien, withSrid);
3685
                        } catch (SQLException e) {
3686
                                logger.error("While converting to STRUCT: " + e.getMessage());
3687
                        }
3688
                        return resp;
3689
                }
3690
        }
3691

    
3692
        /**
3693
         * Utility method to convert a gvSIG Geometry into a oracle STRUCT
3694
         * 
3695
         * @param geom
3696
         *            the FShape object
3697
         * @param c
3698
         *            the connection
3699
         * @param srid
3700
         *            the SRS (oracle code)
3701
         * @param agu_b
3702
         *            whether to check holes validity
3703
         * @param hasSrid
3704
         *            whether the SRS is non-NULL
3705
         * @return a oracle struct representing the geometry
3706
         * 
3707
         * @throws SQLException
3708
         */
3709
        public static STRUCT geometryToSTRUCT(Geometry geom, Connection conn,
3710
                        int osrid, boolean agu_b, boolean hasSrid) throws SQLException {
3711

    
3712
                boolean three = false;
3713

    
3714
                if (geom.getDimension() == 3) {
3715
                        three = true;
3716
                }
3717

    
3718
                STRUCT resp = null;
3719

    
3720
                if (geom instanceof MultiPoint2D) {
3721
                        resp = multiPoint2DToStruct((MultiPoint2D) geom, conn, osrid,
3722
                                        hasSrid);
3723
                        return resp;
3724
                }
3725

    
3726
                if (geom instanceof Point2D) { // point 2/3d
3727
                        Coordinate p = getSingleCoordinate((Point) geom);
3728
                        resp = getMultiPointAsStruct(p, osrid, three, conn, hasSrid);
3729
                } else {
3730
                        if (geom instanceof Surface2D) { // polygon 2/3d
3731

    
3732
                                if (geom instanceof Circle2D) {
3733
                                        resp = getCircleAsStruct((Circle2D) geom, osrid, conn,
3734
                                                        hasSrid);
3735
                                } else {
3736
                                        // also FEllipse2D
3737
                                        resp = getMultiPolygonAsStruct(geom, osrid, three, conn,
3738
                                                        agu_b, hasSrid);
3739
                                }
3740
                        } else { // line 2/3d
3741

    
3742
                                List<LineString3D> _lines = getLineStrings(geom);
3743
                                resp = getMultiLineAsStruct(_lines, osrid, three, conn, hasSrid);
3744
                        }
3745
                }
3746

    
3747
                return resp;
3748
        }
3749
        
3750
        
3751
        
3752

    
3753

    
3754

    
3755
        public static int getShapeTypeFromArray(ArrayList arrlist) {
3756
                
3757
                int resp = ((Integer) arrlist.get(0)).intValue();
3758
                
3759
                int sz = arrlist.size();
3760
                int aux = 0;
3761
                for (int i=1; i<sz; i++) {
3762
                        aux = ((Integer) arrlist.get(i)).intValue();
3763
                        if (aux != resp) return TYPES.GEOMETRY;
3764
                }
3765
                return resp;
3766
        }
3767

    
3768
        // condition using ROWNUM with growing indexs to do a size-independent sample
3769
    public static String EXPONENTIAL_INDICES_CONDITION = null;
3770
    static {
3771
            
3772
            String sb = "";
3773
            int i=0;
3774
            sb = "(rownum = 1)";
3775
            for (i=2; i<20; i++) {
3776
                    sb = "(" + sb + " OR (rownum = " + i + "))";
3777
            }
3778
            int cnt = 0;
3779
            float aux = 1;
3780
            while (cnt < 35) {
3781
                    aux = aux * 1.5f;
3782
                    i = 20 + Math.round(aux);
3783
                    sb = "(" + sb + " OR (rownum = " + i + "))";
3784
                    cnt++;
3785
            }
3786
                aux = aux * 1.5f;
3787
                i = 20 + Math.round(aux);
3788
                sb = "(" + sb + " OR (rownum = " + i + "))";
3789
                EXPONENTIAL_INDICES_CONDITION = sb;
3790
    }
3791
    
3792
    
3793
        public static void copyFeatureTypeToOracleStoreParams(
3794
                        EditableFeatureType efType, OracleStoreParameters params) {
3795
                
3796
                
3797
                // TODO Auto-generated method stub
3798
                
3799
        }
3800
        
3801

    
3802
    
3803
    /**
3804
     * Utility method to transform a struct into a IGeometry.
3805
     *
3806
     * @param st the struct to be converted
3807
     * @param complex comes from a complex sdo geometry
3808
     * @return the IGeometry
3809
     */
3810
    public static Geometry getGeometry(
3811
                    STRUCT st,
3812
                    boolean complex,
3813
                    boolean __tablehassrid,
3814
                    String __tablesrid,
3815
                    Connection _conn) {
3816

    
3817
            GeometryManager gm = GeometryLocator.getGeometryManager();
3818
            
3819
            if (st == null) {
3820
                    Geometry aux = null;
3821
                    try {
3822
                                aux = gm.createNullGeometry(SUBTYPES.GEOM2D);
3823
                        } catch (CreateGeometryException e) {
3824
                                logger.error("While creating null Geometry: " + e.getMessage());
3825
                        }
3826
                    return aux;
3827
            }
3828

    
3829
        Datum[] the_data = null;
3830

    
3831
        try {
3832
            the_data = st.getOracleAttributes();
3833

    
3834
            int jgtype = ((NUMBER) the_data[0]).intValue() % 1000;
3835
            jgtype = oracleGTypeToFShapeType(jgtype, complex);
3836

    
3837
            int dim = ((NUMBER) the_data[0]).intValue() / 1000;
3838

    
3839
            if (dim < 2) {
3840
                dim = 2;
3841
            }
3842

    
3843
            int subty = getSubTypeFromDims(dim);
3844
            Geometry ig = gm.createNullGeometry(subty);
3845

    
3846
            if (isActuallyACollection(the_data)) {
3847
                jgtype = TYPES.AGGREGATE;
3848
            }
3849

    
3850
            switch (jgtype) {
3851
            case TYPES.AGGREGATE:
3852
                ig = getFMapGeometryCollection(the_data, dim, __tablehassrid, __tablesrid, _conn);
3853
                break;
3854

    
3855
            case TYPES.POINT:
3856
                ig = getFMapGeometryPoint(the_data, dim);
3857
                break;
3858

    
3859
            case TYPES.CURVE:
3860
                ig = getFMapGeometryMultiLineString(the_data, dim);
3861
                break;
3862

    
3863
            case TYPES.SURFACE:
3864
                ig = getFMapGeometryMultipolygon(the_data, dim);
3865
                break;
3866
            }
3867

    
3868
            return ig;
3869
        } catch (Exception e) {
3870
            logger.error("While creating Geometry from STRUCT: " + e.getMessage());
3871
        }
3872
        return null;
3873
    }
3874
    
3875
    
3876
    /**
3877
     * Utility method to transform a struct into a IGeometry.
3878
     *
3879
     * @param st the struct to be converted
3880
     * @param complex comes from a complex sdo geometry
3881
     * @return the IGeometry
3882
     */
3883
    public static Primitive getPrimitive(STRUCT st, boolean complex) {
3884

    
3885
            GeometryManager gm = GeometryLocator.getGeometryManager();
3886
            Primitive resp = null;
3887
            
3888
            if (st == null) {
3889
                    try {
3890
                                resp = gm.createNullGeometry(SUBTYPES.GEOM2D);
3891
                        } catch (CreateGeometryException e) {
3892
                                logger.error("While creating null geometry: " + e.getMessage());
3893
                        }
3894
                        return resp;
3895
            }
3896

    
3897
        Datum[] the_data = null;
3898
        try {
3899
            the_data = st.getOracleAttributes();
3900

    
3901
            int jgtype = ((NUMBER) the_data[0]).intValue() % 1000;
3902
            jgtype = oracleGTypeToFShapeType(jgtype, complex);
3903

    
3904
            int dim = ((NUMBER) the_data[0]).intValue() / 1000;
3905

    
3906
            if (dim < 2) {
3907
                dim = 2;
3908
            }
3909

    
3910
                int subty = getSubTypeFromDims(dim);
3911
                Primitive ig = null;
3912
                try {
3913
                                ig = gm.createNullGeometry(subty);
3914
                        } catch (CreateGeometryException e) {
3915
                                logger.error("While creating null geometry: " + e.getMessage());
3916
                        }
3917

    
3918
            if (isActuallyACollection(the_data)) {
3919
                jgtype = TYPES.AGGREGATE;
3920
            }
3921

    
3922
            try {
3923
                switch (jgtype) {
3924
                case TYPES.POINT:
3925
                    ig = (Primitive) getFMapGeometryPoint(the_data, dim);
3926
                    break;
3927

    
3928
                case TYPES.CURVE:
3929
                    ig = (Primitive) getFMapGeometryMultiLineString(the_data, dim);
3930
                    break;
3931

    
3932
                case TYPES.SURFACE:
3933
                    ig = (Primitive) getFMapGeometryMultipolygon(the_data, dim);
3934
                    break;
3935
                default:
3936
                        logger.error("Aggregate of non primitives not supported.");
3937
                    break;
3938
                }
3939
            } catch (Exception ex) {
3940
                    logger.error("While creating primitive: " + ex.getMessage());
3941
            }
3942

    
3943
            return ig;
3944
        } catch (SQLException e) {
3945
            logger.error(e);
3946
        }
3947

    
3948
        return null;
3949
    }
3950
    
3951
    
3952
    private static int getSubTypeFromDims(int dim) {
3953
            
3954
            switch (dim) {
3955
            case 3:
3956
                    return SUBTYPES.GEOM3D;
3957
            case 4:
3958
                    return SUBTYPES.GEOM3DM;
3959
            default:
3960
                            return SUBTYPES.GEOM2D;
3961
            }
3962
        }
3963

    
3964
        public static Geometry getFMapGeometryCollection(
3965
                    Datum[] the_data,
3966
                    int dim,
3967
                    boolean tableHasSrid,
3968
                    String table_srid,
3969
                    Connection _conn) {
3970

    
3971
            NUMBER _srid = new NUMBER(0);
3972
        NUMBER main_type = new NUMBER((dim * 1000) + getStructType(the_data));
3973

    
3974

    
3975
        Datum[] all_info_array = null;
3976
        Object[] elems_info_aray = null;
3977
        Datum[] all_ords = null;
3978

    
3979
        Object[] ords_of_groups = null;
3980
        Object[] _elems_info_aray = null;
3981
        try {
3982
            all_info_array = ((ARRAY) the_data[3]).getOracleArray();
3983
            elems_info_aray = groupByElement(all_info_array);
3984
            all_ords = ((ARRAY) the_data[4]).getOracleArray();
3985

    
3986
            ords_of_groups = getOrdOfGroups(all_ords, elems_info_aray);
3987
            _elems_info_aray = new Object[elems_info_aray.length];
3988
        }
3989
        catch (SQLException e) {
3990
            logger.error("Unexpected error: " + e.getMessage());
3991
        }
3992

    
3993

    
3994
        for (int i = 0; i < elems_info_aray.length; i++) {
3995
            _elems_info_aray[i] = updateIndexes((Datum[]) elems_info_aray[i]);
3996
        }
3997

    
3998
        // _elems_info_aray, ords_of_groups
3999
        int no_of_elems = ords_of_groups.length;
4000
        Primitive[] geoms = new Primitive[no_of_elems];
4001

    
4002
        for (int i = 0; i < no_of_elems; i++) {
4003
            Datum[] item_info_array = null;
4004
            Datum[] item_ords = null;
4005
            NUMBER gtype = null;
4006

    
4007
            try {
4008
                item_info_array = (Datum[]) _elems_info_aray[i];
4009
                item_ords = (Datum[]) ords_of_groups[i];
4010

    
4011
                gtype = new NUMBER((dim * 1000) +
4012
                        (item_info_array[1].intValue() % 1000));
4013

    
4014
                if (tableHasSrid) {
4015
                        _srid = new NUMBER(Integer.parseInt(table_srid));
4016
                }
4017
            }
4018
            catch (SQLException se) {
4019
                logger.error("Unexpected error: " + se.getMessage());
4020
            }
4021

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

    
4025
            STRUCT itemst = null;
4026

    
4027
            if (tableHasSrid) {
4028

    
4029
                itemst = createStruct(gtype, _srid,
4030
                        item_info_array, item_ords, _conn);
4031
            }
4032
            else {
4033
                itemst = createStruct(gtype, null,
4034
                        item_info_array, item_ords, _conn);
4035
            }
4036
            geoms[i] = getPrimitive(itemst, true);
4037
        }
4038
        
4039
            GeometryManager gm = GeometryLocator.getGeometryManager();
4040
            int subt = getSubTypeFromDims(dim);
4041
        MultiPrimitive resp = null;
4042
        
4043
        try {
4044
                        resp = (MultiPrimitive) gm.create(TYPES.AGGREGATE, subt);
4045
                for (int i = 0; i < no_of_elems; i++) {
4046
                        resp.addPrimitive(geoms[i]);
4047
                }
4048
                } catch (Exception e) {
4049
                        logger.error("While creating multi primitive: " + e.getMessage());
4050
                }
4051
        return resp;
4052
    }
4053
        
4054
        // ===========================================================
4055
        
4056
        /**
4057
         * Get oracle srid from srs code(EPSG code)
4058
         * 
4059
         * @param epsg
4060
         * @return oraSRID
4061
         */
4062
        public static String epsgToOracleSrid(String epsg) {
4063
                
4064
                DataManager manager = DALLocator.getDataManager();
4065
                int isrs = -1;
4066
                if (epsg != null) {
4067
                        FeatureStore oraSrsStore = (FeatureStore) OracleLibrary
4068
                                        .getSRSDataStore();
4069

    
4070
                        FeatureSet set = null;
4071
                        try {
4072
                                FeatureQuery query = oraSrsStore.createFeatureQuery();
4073
                                query.setFilter(manager.createExpresion("EPSG = " + epsg));
4074
                                set = (FeatureSet) oraSrsStore.getDataSet(query);
4075
                                if (set.getSize() > 0) {
4076
                                        Iterator<Feature> it = set.iterator();
4077
                                        while (it.hasNext()) {
4078
                                                Feature feat = it.next();
4079
                                                Double ora = feat.getDouble("ORACLE");
4080
                                                int iora = ora.intValue();
4081
                                                double prefe = feat.getDouble("PRF_ORACLE");
4082
                                                if (prefe == 1) {
4083
                                                        isrs = iora;
4084
                                                        break;
4085
                                                }
4086
                                        }
4087
                                }
4088
                        } catch (DataException e) {
4089
                                e.printStackTrace();
4090
                        }
4091
                        if (isrs >= 0) {
4092
                                return Integer.toString(isrs);
4093
                        }
4094
                }
4095
                return null;
4096
        }
4097

    
4098
        /**
4099
         * Get EPSG SRS from Oracle SRS
4100
         * 
4101
         * @param oraSRID
4102
         * @return
4103
         */
4104
        public static Integer oracleSridToEpsg(String oraSRID) {
4105

    
4106
                DataManager manager = DALLocator.getDataManager();
4107
                Integer isrs = null;
4108
                
4109
                if (oraSRID != null) {
4110
                        FeatureStore oraSrsStore = (FeatureStore) OracleLibrary
4111
                                        .getSRSDataStore();
4112

    
4113
                        FeatureSet set = null;
4114
                        try {
4115
                                FeatureQuery query = oraSrsStore.createFeatureQuery();
4116
                                query.setFilter(manager.createExpresion("ORACLE = " + oraSRID));
4117
                                set = (FeatureSet) oraSrsStore.getDataSet(query);
4118
                                if (set.getSize() > 0) {
4119
                                        Iterator<Feature> it = set.iterator();
4120
                                        while (it.hasNext()) {
4121
                                                Feature feat = it.next();
4122
                                                isrs = new Integer(feat.getInt("EPSG"));
4123
                                        }
4124
                                }
4125
                        } catch (DataException e) {
4126
                                logger.error("While getting EPSG from oracle srid: " + e.getMessage());
4127
                        }
4128
                        return isrs;
4129
                } else {
4130
                        return null;
4131
                }
4132
        }
4133

    
4134
        /**
4135
         * Get Oracle SRS from gvSIG projection
4136
         * 
4137
         * @param proj
4138
         * @return  
4139
         */
4140
        public static String projectionToOracleSrid(IProjection proj) {
4141
                if (proj != null) {
4142
                        String epsg = proj.getAbrev().trim();
4143
                        int ocu = epsg.indexOf(":");
4144
                        if (ocu != -1) {
4145
                                epsg = epsg.substring(ocu + 1);
4146
                        }
4147
                        return epsgToOracleSrid(epsg);
4148
                } else {
4149
                        return null;
4150
                }
4151
        }
4152

    
4153
        public static int dimensionsFromSubtype(int subtype) {
4154
                
4155
                switch (subtype) {
4156
                
4157
                case SUBTYPES.GEOM2D:
4158
                        return 2;
4159
                case SUBTYPES.GEOM3D:
4160
                case SUBTYPES.GEOM2DZ:
4161
                case SUBTYPES.GEOM2DM:
4162
                        return 3;
4163
                case SUBTYPES.GEOM3DM:
4164
                        return 4;
4165
                default:
4166
                                logger.error("Unknown subtype: " + subtype + ". Returned 2 as number of dimensions.");
4167
                        return 2;
4168
                }
4169
        }
4170

    
4171
        public static Rectangle2D envelopeToRectangle2D(org.gvsig.fmap.geom.primitive.Envelope envelope) {
4172
                        
4173
                double x = envelope.getMinimum(0);
4174
                double y = envelope.getMinimum(1);
4175
                double w = envelope.getLength(0);
4176
                double h = envelope.getLength(1);
4177
                Rectangle2D resp = new Rectangle2D.Double(x,y,w,h);
4178
                return resp;
4179
        }
4180

    
4181
}