Statistics
| Revision:

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

History | View | Annotate | Download (103 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.geom.PathIterator;
31
import java.awt.geom.Point2D;
32
import java.awt.geom.Rectangle2D;
33
import java.io.BufferedReader;
34
import java.io.File;
35
import java.io.FileReader;
36
import java.lang.reflect.Array;
37
import java.net.URL;
38
import java.sql.Connection;
39
import java.sql.PreparedStatement;
40
import java.sql.ResultSet;
41
import java.sql.SQLException;
42
import java.sql.Types;
43
import java.text.DecimalFormat;
44
import java.text.DecimalFormatSymbols;
45
import java.util.ArrayList;
46
import java.util.HashMap;
47
import java.util.Iterator;
48
import java.util.List;
49
import java.util.Random;
50

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

    
57
import org.cresques.cts.IProjection;
58
import org.gvsig.fmap.dal.DALLocator;
59
import org.gvsig.fmap.dal.DataManager;
60
import org.gvsig.fmap.dal.exception.DataException;
61
import org.gvsig.fmap.dal.feature.EditableFeatureType;
62
import org.gvsig.fmap.dal.feature.Feature;
63
import org.gvsig.fmap.dal.feature.FeatureAttributeDescriptor;
64
import org.gvsig.fmap.dal.feature.FeatureQuery;
65
import org.gvsig.fmap.dal.feature.FeatureSet;
66
import org.gvsig.fmap.dal.feature.FeatureStore;
67
import org.gvsig.fmap.dal.feature.FeatureType;
68
import org.gvsig.fmap.dal.feature.spi.FeatureReferenceProviderServices;
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.impl.DefaultGeometryManager;
80
import org.gvsig.fmap.geom.primitive.Curve;
81
import org.gvsig.fmap.geom.primitive.Envelope;
82
import org.gvsig.fmap.geom.primitive.GeneralPathX;
83
import org.gvsig.fmap.geom.primitive.Point;
84
import org.gvsig.fmap.geom.primitive.Primitive;
85
import org.gvsig.fmap.geom.primitive.Surface;
86
import org.gvsig.fmap.geom.primitive.impl.Circle2D;
87
import org.gvsig.fmap.geom.primitive.impl.Curve2DZ;
88
import org.gvsig.fmap.geom.primitive.impl.DefaultNullGeometry;
89
import org.gvsig.fmap.geom.primitive.impl.Point2DZ;
90
import org.gvsig.fmap.geom.primitive.impl.Surface2D;
91
import org.gvsig.fmap.geom.primitive.impl.Surface2DZ;
92
import org.gvsig.fmap.geom.type.GeometryType;
93
import org.gvsig.fmap.geom.type.GeometryTypeNotSupportedException;
94
import org.gvsig.oracle.utils.LineString3D;
95
import org.slf4j.Logger;
96
import org.slf4j.LoggerFactory;
97

    
98
import com.vividsolutions.jts.algorithm.CGAlgorithms;
99
import com.vividsolutions.jts.geom.Coordinate;
100
import com.vividsolutions.jts.geom.CoordinateArrays;
101
import com.vividsolutions.jts.geom.GeometryFactory;
102
import com.vividsolutions.jts.geom.LineString;
103
import com.vividsolutions.jts.geom.LinearRing;
104
import com.vividsolutions.jts.geom.impl.CoordinateArraySequence;
105

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

    
127

    
128
        /**
129
         * COnstructs a geometry from a file that contains a vertex per line:
130
         * 
131
         * x1 y1 z1 x2 y2 z2 ...
132
         * 
133
         * @param filepath
134
         *            vertices text file path
135
         * @param polygon
136
         *            whether it is a polygon or not
137
         * @return the created geometry
138
         * @throws CreateGeometryException
139
         */
140
        public static Geometry readGeometry3D(URL filepath, boolean polygon)
141
                        throws CreateGeometryException {
142

    
143
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
144

    
145
                GeneralPathX gpx = new GeneralPathX();
146
                File file = new File(filepath.getFile());
147
                List<Double> z = new ArrayList<Double>();
148

    
149
                try {
150
                        FileReader fr = new FileReader(file);
151
                        BufferedReader br = new BufferedReader(fr);
152
                        double[] coords = new double[3];
153

    
154
                        boolean move = true;
155

    
156
                        String line = br.readLine();
157

    
158
                        while (line != null) {
159
                                coords = parseLine(line);
160

    
161
                                if (line.length() == 0) {
162
                                        move = true;
163
                                } else {
164
                                        if (move) {
165
                                                gpx.moveTo(coords[0], coords[1]);
166
                                                z.add(new Double(coords[2]));
167
                                        } else {
168
                                                gpx.lineTo(coords[0], coords[1]);
169
                                                z.add(new Double(coords[2]));
170
                                        }
171

    
172
                                        move = false;
173
                                }
174

    
175
                                line = br.readLine();
176
                        }
177
                } catch (Exception ex) {
178
                        logger.error("While creating GeneralPathX: " + ex.getMessage());
179
                        return null;
180
                }
181

    
182
                if (polygon) {
183
                        Surface surface = (Surface) geomManager.create(
184
                                        Geometry.TYPES.SURFACE, Geometry.SUBTYPES.GEOM3D);
185
                        surface.setGeneralPath(gpx);
186
                        for (int i = 0; i < z.size(); i++) {
187
                                surface
188
                                                .setCoordinateAt(i, 2, ((Double) z.get(i))
189
                                                                .doubleValue());
190
                        }
191
                        return surface;
192
                } else {
193
                        Curve curve = (Curve) geomManager.create(Geometry.TYPES.CURVE,
194
                                        Geometry.SUBTYPES.GEOM3D);
195
                        curve.setGeneralPath(gpx);
196
                        for (int i = 0; i < z.size(); i++) {
197
                                curve.setCoordinateAt(i, 2, ((Double) z.get(i)).doubleValue());
198
                        }
199
                        return curve;
200
                }
201
        }
202

    
203
        /**
204
         * 
205
         * @param line
206
         * @return
207
         */
208
        private static double[] parseLine(String line) {
209
                String[] sep = line.split(" ");
210
                double[] resp = new double[3];
211

    
212
                for (int i = 0; i < 3; i++)
213
                        resp[i] = 0.0;
214

    
215
                try {
216
                        resp[0] = Double.parseDouble(sep[0]);
217
                } catch (Exception ex) {
218
                }
219

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

    
226
                        if (sep.length > 2) {
227
                                try {
228
                                        resp[2] = Double.parseDouble(sep[2]);
229
                                } catch (Exception ex) {
230
                                }
231
                        }
232
                }
233

    
234
                return resp;
235
        }
236

    
237
        /**
238
         * Transform multipoint2d or multipoint2dz to Oracle STRUCT
239
         * 
240
         * @param mp2d
241
         * @param conn
242
         * @param osrid
243
         * @param hasSrid
244
         * @return
245
         * @throws SQLException
246
         */
247
        private static STRUCT multiPoint2DToStruct(MultiPoint2D mp2d,
248
                        Connection conn, int osrid, boolean hasSrid) throws SQLException {
249
                int np = mp2d.getPrimitivesNumber();
250
                boolean threed = (mp2d instanceof MultiPoint2DZ);
251
                int gtype = 2005;
252
                int dim = 2;
253
                MultiPoint2DZ mp3d = null;
254

    
255
                if (threed) {
256
                        gtype = 3005;
257
                        dim = 3;
258
                        mp3d = (MultiPoint2DZ) mp2d;
259
                }
260

    
261
                NUMBER[] indices = new NUMBER[3];
262
                indices[0] = new NUMBER(1);
263
                indices[1] = new NUMBER(1);
264
                indices[2] = new NUMBER(np);
265

    
266
                NUMBER[] ords = new NUMBER[dim * np];
267

    
268
                for (int i = 0; i < np; i++) {
269
                        ords[dim * i] = new NUMBER(mp2d.getPoint(i).getX());
270
                        ords[(dim * i) + 1] = new NUMBER(mp2d.getPoint(i).getY());
271

    
272
                        if (threed) {
273
                                ords[(dim * i) + 2] = new NUMBER(mp3d.getZs()[i]);
274
                        }
275
                }
276

    
277
                STRUCT resp;
278
                StructDescriptor dsc = StructDescriptor.createDescriptor(
279
                                "MDSYS.SDO_GEOMETRY", conn);
280
                Object[] obj = new Object[5];
281
                obj[0] = new NUMBER(gtype);
282

    
283
                if (hasSrid) {
284
                        obj[1] = new NUMBER(osrid);
285
                } else { // , boolean hasSrid
286
                        obj[1] = null;
287
                }
288

    
289
                obj[2] = null;
290
                obj[3] = indices;
291
                obj[4] = ords;
292
                resp = new STRUCT(dsc, conn, obj);
293

    
294
                return resp;
295
        }
296

    
297
        /**
298
         * Transform circle2d to Oracle STRUCT
299
         * 
300
         * @param fcirc
301
         * @param osrid
302
         * @param _conn
303
         * @param hasSrid
304
         * @return
305
         * @throws SQLException
306
         */
307
        private static STRUCT getCircleAsStruct(Circle2D fcirc, int osrid,
308
                        Connection conn, boolean hasSrid) throws SQLException {
309
                int geotype = 2003;
310
                NUMBER[] indices = new NUMBER[3];
311
                indices[0] = new NUMBER(1);
312
                indices[1] = new NUMBER(1003);
313
                indices[2] = new NUMBER(4);
314

    
315
                NUMBER[] ords = new NUMBER[6];
316
                Coordinate[] three_points = getThreePointsOfCircumference(fcirc
317
                                .getCenter(), fcirc.getRadious());
318

    
319
                for (int i = 0; i < three_points.length; i++) {
320
                        ords[i * 2] = new NUMBER(three_points[i].x);
321
                        ords[(i * 2) + 1] = new NUMBER(three_points[i].y);
322
                }
323

    
324
                STRUCT resp;
325
                StructDescriptor dsc = StructDescriptor.createDescriptor(
326
                                "MDSYS.SDO_GEOMETRY", conn);
327
                Object[] obj = new Object[5];
328
                obj[0] = new NUMBER(geotype);
329

    
330
                if (hasSrid) {
331
                        obj[1] = new NUMBER(osrid);
332
                } else {
333
                        obj[1] = null;
334
                }
335

    
336
                obj[2] = null;
337
                obj[3] = indices;
338
                obj[4] = ords;
339
                resp = new STRUCT(dsc, conn, obj);
340

    
341
                return resp;
342
        }
343

    
344
        /**
345
         * 
346
         * @param center
347
         * @param radius
348
         * @return
349
         */
350
        private static Coordinate[] getThreePointsOfCircumference(Point center,
351
                        double radius) {
352
                Coordinate[] resp = new Coordinate[3];
353
                double x;
354
                double y;
355
                double alpha = 0;
356

    
357
                for (int i = 0; i < 3; i++) {
358
                        alpha = (i * 120.0 * Math.PI) / 180.0;
359
                        x = center.getX() + (radius * Math.cos(alpha));
360
                        y = center.getY() + (radius * Math.sin(alpha));
361
                        resp[i] = new Coordinate(x, y);
362
                }
363

    
364
                return resp;
365
        }
366

    
367
        /**
368
         * Get coordinates from a point
369
         * 
370
         * @param pto
371
         * @return
372
         */
373
        private static Coordinate getSingleCoordinate(Point pto) {
374
                Coordinate resp = new Coordinate();
375
                resp.x = pto.getX();
376
                resp.y = pto.getY();
377
                if (pto instanceof Point2DZ) {
378
                        resp.z = ((Point2DZ) pto).getCoordinateAt(3);
379
                }
380
                return resp;
381
        }
382

    
383
        /**
384
         * 
385
         * @param cc
386
         * @return
387
         */
388
        private static List<Coordinate> ensureSensibleLineString(List<Coordinate> cc) {
389
                if (cc.size() == 2) {
390
                        if (same2DCoordinate(cc.get(0), cc.get(cc.size() - 1))) {
391
                                List<Coordinate> resp = new ArrayList<Coordinate>();
392
                                resp.add(cc.get(0));
393

    
394
                                Coordinate newc = new Coordinate(cc.get(0));
395
                                newc.x = newc.x + IRRELEVANT_DISTANCE;
396
                                resp.add(newc);
397

    
398
                                return resp;
399
                        }
400
                }
401
                return cc;
402
        }
403

    
404
        /**
405
         * 
406
         * @param c1
407
         * @param c2
408
         * @return
409
         */
410
        private static boolean same2DCoordinate(Coordinate c1, Coordinate c2) {
411
                if (c1.x != c2.x) {
412
                        return false;
413
                }
414
                if (c1.y != c2.y) {
415
                        return false;
416
                }
417

    
418
                return true;
419
        }
420

    
421
        /**
422
         * 
423
         * @param cc
424
         * @return
425
         */
426
        private static List<Coordinate> getClosedRelevantPolygon(List<Coordinate> cc) {
427
                if (cc.size() == 2) {
428
                        return getMinClosedCoords(cc.get(0));
429
                }
430

    
431
                if (cc.size() == 3) {
432
                        if (same2DCoordinate(cc.get(0), cc.get(1))) {
433
                                return getMinClosedCoords(cc.get(0));
434
                        }
435

    
436
                        if (same2DCoordinate(cc.get(0), cc.get(2))) {
437
                                return getMinClosedCoords((Coordinate) cc.get(0));
438
                        }
439

    
440
                        if (same2DCoordinate(cc.get(1), cc.get(2))) {
441
                                return getMinClosedCoords(cc.get(1));
442
                        }
443

    
444
                        cc.add(cc.get(0));
445

    
446
                        return cc;
447
                }
448

    
449
                if (!same2DCoordinate(cc.get(0), cc.get(cc.size() - 1))) {
450
                        cc.add(cc.get(0));
451
                }
452

    
453
                return cc;
454
        }
455

    
456
        /**
457
         * 
458
         * @param c
459
         * @return
460
         */
461
        private static List<Coordinate> getMinClosedCoords(Coordinate c) {
462
                List<Coordinate> resp = new ArrayList<Coordinate>();
463
                resp.add(c);
464

    
465
                Coordinate nc = new Coordinate(c);
466
                nc.x = nc.x + IRRELEVANT_DISTANCE;
467
                resp.add(nc);
468

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

    
473
                resp.add(new Coordinate(c));
474

    
475
                return resp;
476
        }
477

    
478
        /**
479
         * 
480
         * @param c
481
         * @return
482
         */
483
        private static LinearRing getMinLinearRing(Coordinate c) {
484
                Coordinate[] p = new Coordinate[4];
485
                p[0] = c;
486

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

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

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

    
499
                return ls;
500
        }
501

    
502
        /**
503
         * 
504
         * @return
505
         */
506
        private static double[] getMinLinearRingZ() {
507
                double[] resp = new double[4];
508

    
509
                for (int i = 0; i < 4; i++)
510
                        resp[i] = 0.0;
511

    
512
                return resp;
513
        }
514

    
515
        /**
516
         * 
517
         * @param testPoint
518
         * @param pointList
519
         * @return
520
         */
521
        private static boolean pointInList(Coordinate testPoint,
522
                        Coordinate[] pointList) {
523
                int t;
524
                int numpoints;
525
                Coordinate p;
526

    
527
                numpoints = Array.getLength(pointList);
528

    
529
                for (t = 0; t < numpoints; t++) {
530
                        p = pointList[t];
531

    
532
                        if ((testPoint.x == p.x)
533
                                        && (testPoint.y == p.y)
534
                                        && ((testPoint.z == p.z) || (!(testPoint.z == testPoint.z)))) {
535
                                return true;
536
                        }
537
                }
538

    
539
                return false;
540
        }
541

    
542
        /***
543
         * 
544
         * @param mpolygon
545
         * @return
546
         */
547
        private static List<LineString3D> getPolygonsEasily(Geometry mpolygon) {
548
                boolean threed = false;
549

    
550
                if (mpolygon instanceof Surface2DZ) {
551
                        threed = true;
552
                }
553

    
554
                int start_ind = 0;
555
                int end_ind = 0;
556
                int ind = 0;
557
                int new_size;
558
                List<Coordinate> arrayCoords = null;
559
                List<LineString3D> resp = new ArrayList<LineString3D>();
560
                Coordinate[] points = null;
561
                int theType = -99;
562
                double[] theData = new double[6];
563
                Coordinate onlyCoord = null;
564
                int numParts = 0;
565

    
566
                PathIterator theIterator = mpolygon.getPathIterator(null, FLATNESS);
567

    
568
                while (!theIterator.isDone()) {
569
                        // while not done
570
                        theType = theIterator.currentSegment(theData);
571

    
572
                        if (onlyCoord == null) {
573
                                onlyCoord = new Coordinate();
574
                                onlyCoord.x = theData[0];
575
                                onlyCoord.y = theData[1];
576
                        }
577

    
578
                        switch (theType) {
579
                        case PathIterator.SEG_MOVETO:
580

    
581
                                if (arrayCoords == null) {
582
                                        arrayCoords = new ArrayList<Coordinate>();
583
                                } else {
584
                                        end_ind = ind - 1;
585

    
586
                                        arrayCoords = getClosedRelevantPolygon(arrayCoords);
587
                                        new_size = arrayCoords.size();
588

    
589
                                        if (arrayCoords != null) {
590
                                                points = CoordinateArrays
591
                                                                .toCoordinateArray(arrayCoords);
592

    
593
                                                try {
594
                                                        LinearRing aux = geomFactory
595
                                                                        .createLinearRing(points);
596
                                                        double[] z = null;
597

    
598
                                                        if (threed) {
599
                                                                z = getZ((Surface2DZ) mpolygon, start_ind,
600
                                                                                end_ind, new_size);
601
                                                        }
602

    
603
                                                        LineString3D ring = new LineString3D(aux, z);
604

    
605
                                                        if (CGAlgorithms.isCCW(points)) {
606
                                                                resp.add(ring);
607
                                                        } else {
608
                                                                resp.add(ring.createReverse());
609
                                                        }
610
                                                } catch (Exception e) {
611
                                                        logger.error("Topology exception: "
612
                                                                        + e.getMessage());
613

    
614
                                                        return null;
615
                                                }
616
                                        }
617

    
618
                                        arrayCoords = new ArrayList<Coordinate>();
619

    
620
                                        start_ind = ind;
621
                                }
622

    
623
                                numParts++;
624

    
625
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
626
                                ind++;
627

    
628
                                break;
629

    
630
                        case PathIterator.SEG_LINETO:
631
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
632
                                ind++;
633

    
634
                                break;
635

    
636
                        case PathIterator.SEG_QUADTO:
637
                                logger.info("SEG_QUADTO Not supported here");
638
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
639
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
640
                                ind++;
641
                                ind++;
642

    
643
                                break;
644

    
645
                        case PathIterator.SEG_CUBICTO:
646
                                logger.info("SEG_CUBICTO Not supported here");
647
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
648
                                arrayCoords.add(new Coordinate(theData[2], theData[3]));
649
                                arrayCoords.add(new Coordinate(theData[4], theData[5]));
650
                                ind++;
651
                                ind++;
652
                                ind++;
653

    
654
                                break;
655

    
656
                        case PathIterator.SEG_CLOSE:
657
                                break;
658
                        }
659

    
660
                        theIterator.next();
661
                }
662

    
663
                end_ind = ind - 1;
664

    
665
                // null shape:
666
                if (arrayCoords == null) {
667
                        arrayCoords = new ArrayList<Coordinate>();
668

    
669
                        Coordinate _c = new Coordinate(0, 0, 0);
670
                        arrayCoords.add(new Coordinate(_c));
671
                        arrayCoords.add(new Coordinate(_c));
672
                }
673

    
674
                // --------------------------------------------
675
                arrayCoords = getClosedRelevantPolygon(arrayCoords);
676
                new_size = arrayCoords.size();
677

    
678
                if (arrayCoords != null) {
679
                        points = CoordinateArrays.toCoordinateArray(arrayCoords);
680

    
681
                        try {
682
                                LinearRing aux = geomFactory.createLinearRing(points);
683
                                double[] z = null;
684

    
685
                                if (threed) {
686
                                        z = getZ((Surface2DZ) mpolygon, start_ind, end_ind,
687
                                                        new_size);
688
                                }
689

    
690
                                LineString3D ring = new LineString3D(aux, z);
691

    
692
                                if (CGAlgorithms.isCCW(points)) {
693
                                        resp.add(ring);
694
                                } else {
695
                                        resp.add(ring.createReverse());
696
                                }
697
                        } catch (Exception e) {
698
                                logger.error("Topology exception: " + e.getMessage());
699

    
700
                                return null;
701
                        }
702
                }
703

    
704
                if (resp.size() == 0) {
705
                        resp.add(new LineString3D(getMinLinearRing(onlyCoord),
706
                                        getMinLinearRingZ()));
707
                }
708

    
709
                return resp;
710
        }
711

    
712
        /**
713
         * Utility method to reverse an array of doubles.
714
         * 
715
         * @param _z
716
         *            an array of doubles to be reversed.
717
         * 
718
         * @return the reversed array of doubles
719
         */
720
        public static double[] reverseArray(double[] _z) {
721
                int size = _z.length;
722
                double[] resp = new double[size];
723

    
724
                for (int i = 0; i < size; i++) {
725
                        resp[i] = _z[size - 1 - i];
726
                }
727

    
728
                return resp;
729
        }
730

    
731
        /**
732
         * Utility method to reverse an array of coordinates
733
         * 
734
         * @param _z
735
         *            an array of coordinaes to be reversed.
736
         * 
737
         * @return the reversed array of coordinates
738
         */
739
        public static Coordinate[] reverseCoordinateArray(Coordinate[] _z) {
740
                int size = _z.length;
741
                Coordinate[] resp = new Coordinate[size];
742

    
743
                for (int i = 0; i < size; i++) {
744
                        resp[i] = _z[size - 1 - i];
745
                }
746

    
747
                return resp;
748
        }
749

    
750
        /**
751
         * 
752
         * @param geom
753
         * @param _str
754
         * @param _end
755
         * @param size
756
         * @return
757
         */
758
        private static double[] getZ(Geometry geom, int _str, int _end, int size) {
759
                double[] resp = new double[size];
760

    
761
                double[] allz = new double[1];
762

    
763
                if (geom instanceof Point2DZ) {
764
                        allz[0] = ((Point2DZ) geom).getCoordinateAt(3);
765
                }
766
                if (geom instanceof Curve2DZ) {
767
                        Curve2DZ curve = (Curve2DZ) geom;
768
                        allz = new double[curve.getNumVertices()];
769
                        for (int i = 0; i < allz.length; i++) {
770
                                allz[i] = curve.getCoordinateAt(i, 3);
771
                        }
772
                }
773
                if (geom instanceof Surface2DZ) {
774
                        Surface2DZ surface = (Surface2DZ) geom;
775
                        allz = new double[surface.getNumVertices()];
776
                        for (int i = 0; i < allz.length; i++) {
777
                                allz[i] = surface.getCoordinateAt(i, 3);
778
                        }
779
                }
780

    
781
                for (int i = _str; ((i <= _end) && ((i - _str) < size)); i++) {
782
                        resp[i - _str] = allz[i];
783
                }
784

    
785
                if ((_end - _str + 1) < size) {
786
                        double repe = allz[_end];
787

    
788
                        for (int i = (_end - _str + 1); i < size; i++) {
789
                                resp[i] = repe;
790
                        }
791
                }
792
                return resp;
793
        }
794

    
795
        /**
796
         * 
797
         * @param mlines
798
         * @return
799
         */
800
        private static List<LineString3D> getLineStrings(Geometry mlines) {
801
                boolean threed = false;
802

    
803
                if (mlines instanceof Curve2DZ) {
804
                        threed = true;
805
                }
806

    
807
                int start_ind = 0;
808
                int end_ind = 0;
809
                int ind = 0;
810
                int new_size = 0;
811

    
812
                LineString3D lin;
813

    
814
                List<LineString3D> arrayLines = new ArrayList<LineString3D>();
815
                PathIterator theIterator = mlines.getPathIterator(null, FLATNESS);
816
                int theType = -99;
817
                double[] theData = new double[6];
818
                List<Coordinate> arrayCoords = null;
819
                int numParts = 0;
820

    
821
                while (!theIterator.isDone()) {
822
                        // while not done
823
                        theType = theIterator.currentSegment(theData);
824

    
825
                        switch (theType) {
826
                        case PathIterator.SEG_MOVETO:
827

    
828
                                if (arrayCoords == null) {
829
                                        arrayCoords = new ArrayList<Coordinate>();
830
                                } else {
831
                                        end_ind = ind - 1;
832
                                        arrayCoords = ensureSensibleLineString(arrayCoords);
833
                                        new_size = arrayCoords.size();
834

    
835
                                        LineString aux = geomFactory
836
                                                        .createLineString(CoordinateArrays
837
                                                                        .toCoordinateArray(arrayCoords));
838
                                        double[] z = null;
839

    
840
                                        if (threed) {
841
                                                z = getZ((Curve2DZ) mlines, start_ind, end_ind,
842
                                                                new_size);
843
                                        }
844

    
845
                                        lin = new LineString3D(aux, z);
846
                                        arrayLines.add(lin);
847
                                        arrayCoords = new ArrayList<Coordinate>();
848

    
849
                                        start_ind = ind;
850
                                }
851

    
852
                                numParts++;
853
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
854

    
855
                                break;
856

    
857
                        case PathIterator.SEG_LINETO:
858
                                arrayCoords.add(new Coordinate(theData[0], theData[1]));
859

    
860
                                break;
861

    
862
                        case PathIterator.SEG_QUADTO:
863
                                logger.info("Not supported here: SEG_QUADTO");
864

    
865
                                break;
866

    
867
                        case PathIterator.SEG_CUBICTO:
868
                                logger.info("Not supported here: SEG_CUBICTO");
869

    
870
                                break;
871

    
872
                        case PathIterator.SEG_CLOSE:
873

    
874
                                Coordinate firstCoord = (Coordinate) arrayCoords.get(0);
875
                                arrayCoords.add(new Coordinate(firstCoord.x, firstCoord.y));
876

    
877
                                break;
878
                        } // end switch
879

    
880
                        theIterator.next();
881
                        ind++;
882
                } // end while loop
883

    
884
                arrayCoords = ensureSensibleLineString(arrayCoords);
885
                new_size = arrayCoords.size();
886

    
887
                LineString aux = geomFactory.createLineString(CoordinateArrays
888
                                .toCoordinateArray(arrayCoords));
889
                double[] z = null;
890

    
891
                if (threed) {
892
                        z = getZ((Curve2DZ) mlines, start_ind, end_ind, new_size);
893
                }
894

    
895
                lin = new LineString3D(aux, z);
896
                arrayLines.add(lin);
897

    
898
                return arrayLines;
899
        }
900

    
901
        /**
902
         * 
903
         * @param ls
904
         * @param threed
905
         * @return
906
         */
907
        private static String lineStringToWKT(LineString3D ls, boolean threed) {
908
                String resp = "(";
909
                Coordinate[] cc = ls.getLs().getCoordinates();
910
                double[] z = ls.getZc();
911
                int size = cc.length;
912

    
913
                if (threed) {
914
                        for (int i = 0; i < size; i++) {
915
                                resp = resp + cc[i].x + " " + cc[i].y + " " + z[i] + ", ";
916
                        }
917

    
918
                        resp = resp.substring(0, resp.length() - 2);
919
                        resp = resp + ")";
920
                } else {
921
                        for (int i = 0; i < size; i++) {
922
                                resp = resp + cc[i].x + " " + cc[i].y + ", ";
923
                        }
924

    
925
                        resp = resp.substring(0, resp.length() - 2);
926
                        resp = resp + ")";
927
                }
928

    
929
                return resp;
930
        }
931

    
932
        /**
933
         * 
934
         * @param ml
935
         * @param threed
936
         * @return
937
         */
938
        private static String multiLineStringToWKT(List<LineString3D> ml,
939
                        boolean threed) {
940
                String resp = "MULTILINESTRING(";
941

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

    
947
                resp = resp.substring(0, resp.length() - 2) + ")";
948

    
949
                return resp;
950
        }
951

    
952
        /**
953
         * 
954
         * @param pols
955
         * @param threed
956
         * @return
957
         */
958
        private static String polygonsToWKT(List<LineString3D> pols, boolean threed) {
959
                String resp = "MULTIPOLYGON(";
960
                LineString3D ls = null;
961

    
962
                for (int i = 0; i < pols.size(); i++) {
963
                        ls = pols.get(i);
964
                        resp = resp + "(" + lineStringToWKT(ls, threed) + "), ";
965
                }
966

    
967
                resp = resp.substring(0, resp.length() - 2) + ")";
968

    
969
                return resp;
970
        }
971

    
972
        /**
973
         * 
974
         * @param shell
975
         * @param holes
976
         * @param threed
977
         * @return
978
         */
979
        private static String shellAndHolesToWKT(LineString3D shell,
980
                        List<LineString3D> holes, boolean threed) {
981
                String resp = "(";
982
                resp = resp + lineStringToWKT(shell, threed);
983

    
984
                if (holes.size() > 0) {
985
                        for (int i = 0; i < holes.size(); i++) {
986
                                LineString3D ls = holes.get(i);
987
                                resp = resp + ", " + lineStringToWKT(ls, threed);
988
                        }
989
                }
990

    
991
                resp = resp + ")";
992

    
993
                return resp;
994
        }
995

    
996
        /**
997
         * 
998
         * @param shells
999
         * @param hFs
1000
         * @param threed
1001
         * @return
1002
         */
1003
        private static String multiPolygonToWKT(List<LineString3D> shells,
1004
                        List<List<LineString3D>> hFs, boolean threed) {
1005
                String resp = "MULTIPOLYGON(";
1006
                LineString3D ls = null;
1007
                List<LineString3D> holes;
1008

    
1009
                for (int i = 0; i < shells.size(); i++) {
1010
                        ls = shells.get(i);
1011
                        holes = hFs.get(i);
1012
                        resp = resp + shellAndHolesToWKT(ls, holes, threed) + ", ";
1013
                }
1014

    
1015
                resp = resp.substring(0, resp.length() - 2) + ")";
1016

    
1017
                return resp;
1018
        }
1019

    
1020
        /**
1021
         * 
1022
         * @param point
1023
         * @param threed
1024
         * @return
1025
         */
1026
        private static String pointToWKT(Point point, boolean threed) {
1027
                String resp = "POINT(" + point.getX() + " " + point.getY();
1028

    
1029
                if ((threed) && (point instanceof Point2DZ)) {
1030
                        resp = resp + " " + ((Point2DZ) point).getCoordinateAt(3);
1031
                }
1032

    
1033
                resp = resp + ")";
1034

    
1035
                return resp;
1036
        }
1037

    
1038
        /**
1039
         * 
1040
         * @param n
1041
         * @param d
1042
         * @return
1043
         */
1044
        private static int twoDIndexToDimsIndex(int n, int d) {
1045
                return ((d * (n - 1)) / 2) + 1;
1046
        }
1047

    
1048
        /**
1049
         * 
1050
         * @param old
1051
         * @param d
1052
         * @return
1053
         * @throws SQLException
1054
         */
1055
        private static ARRAY setSubelementsToDim(ARRAY old, int d)
1056
                        throws SQLException {
1057
                Datum[] infos = (Datum[]) old.getOracleArray();
1058

    
1059
                for (int i = 3; i < infos.length; i = i + 3) {
1060
                        int oldind = infos[i].intValue();
1061
                        oldind = twoDIndexToDimsIndex(oldind, d);
1062
                        infos[i] = new NUMBER(oldind);
1063

    
1064
                        //
1065
                        oldind = infos[i + 1].intValue();
1066
                        infos[i + 1] = new NUMBER(infos[1].intValue());
1067
                }
1068

    
1069
                ARRAY resp = new ARRAY(old.getDescriptor(), old.getOracleConnection(),
1070
                                infos);
1071

    
1072
                return resp;
1073
        }
1074

    
1075
        /**
1076
         * 
1077
         * @param p
1078
         * @param ls
1079
         * @return
1080
         */
1081
        private static boolean isPointInsideLineString(Coordinate p, LineString ls) {
1082
                com.vividsolutions.jts.geom.Envelope env = ls.getEnvelopeInternal();
1083

    
1084
                if (!env.contains(p)) {
1085
                        return false;
1086
                }
1087

    
1088
                return CGAlgorithms.isPointInRing(p, ls.getCoordinates());
1089
        }
1090

    
1091
        /**
1092
         * 
1093
         * @param contained
1094
         * @param container
1095
         * @return
1096
         */
1097
        private static boolean lineString3DIsContainedBy(LineString3D contained,
1098
                        LineString3D container) {
1099
                int samples = 10;
1100
                LineString _in = contained.getLs();
1101
                LineString _out = container.getLs();
1102
                Coordinate[] inc = _in.getCoordinates();
1103
                Coordinate aux;
1104
                int size = inc.length;
1105

    
1106
                if (size <= 10) {
1107
                        for (int i = 0; i < size; i++) {
1108
                                aux = inc[i];
1109

    
1110
                                if (!isPointInsideLineString(aux, _out)) {
1111
                                        return false;
1112
                                }
1113
                        }
1114

    
1115
                        return true;
1116
                } else {
1117
                        for (int i = 0; i < samples; i++) {
1118
                                aux = inc[rnd.nextInt(size)];
1119

    
1120
                                if (!isPointInsideLineString(aux, _out)) {
1121
                                        return false;
1122
                                }
1123
                        }
1124

    
1125
                        return true;
1126
                }
1127
        }
1128

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

    
1149
                if (threed) {
1150
                        geotype = 3007;
1151
                        dim = 3;
1152
                }
1153

    
1154
                NUMBER[] indices = new NUMBER[3 * size];
1155

    
1156
                for (int i = 0; i < size; i++) {
1157
                        indices[3 * i] = new NUMBER(acum + 1);
1158
                        indices[(3 * i) + 1] = new NUMBER(1003);
1159
                        indices[(3 * i) + 2] = new NUMBER(1);
1160
                        acum = acum + (dim * (pols.get(i)).getLs().getNumPoints());
1161
                }
1162

    
1163
                int _ind = 0;
1164
                NUMBER[] ords = new NUMBER[acum];
1165

    
1166
                for (int i = 0; i < size; i++) {
1167
                        LineString3D ls = (LineString3D) pols.get(i);
1168
                        int num_p = ls.getLs().getNumPoints();
1169

    
1170
                        for (int j = 0; j < num_p; j++) {
1171
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1172
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1173

    
1174
                                if (threed) {
1175
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1176
                                }
1177

    
1178
                                _ind = _ind + dim;
1179
                        }
1180
                }
1181

    
1182
                STRUCT resp;
1183
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1184
                                "MDSYS.SDO_GEOMETRY", conn);
1185
                Object[] obj = new Object[5];
1186
                obj[0] = new NUMBER(geotype);
1187

    
1188
                if (hasSrid) {
1189
                        obj[1] = new NUMBER(osrid);
1190
                } else {
1191
                        obj[1] = null;
1192
                }
1193

    
1194
                obj[2] = null;
1195
                obj[3] = indices;
1196
                obj[4] = ords;
1197
                resp = new STRUCT(dsc, conn, obj);
1198

    
1199
                return resp;
1200
        }
1201

    
1202
        /**
1203
         * 
1204
         * @param lines
1205
         * @param srid
1206
         * @param threed
1207
         * @param _conn
1208
         * @param hasSrid
1209
         * @return
1210
         * @throws SQLException
1211
         */
1212
        private static STRUCT getMultiLineAsStruct(List<LineString3D> lines,
1213
                        int osrid, boolean threed, Connection conn, boolean hasSrid)
1214
                        throws SQLException {
1215

    
1216
                int size = lines.size();
1217
                int geotype = 2006;
1218
                int dim = 2;
1219
                int acum = 0;
1220

    
1221
                if (threed) {
1222
                        geotype = 3006;
1223
                        dim = 3;
1224
                }
1225

    
1226
                NUMBER[] indices = new NUMBER[3 * size];
1227

    
1228
                for (int i = 0; i < size; i++) {
1229
                        indices[3 * i] = new NUMBER(acum + 1);
1230
                        indices[(3 * i) + 1] = new NUMBER(2);
1231
                        indices[(3 * i) + 2] = new NUMBER(1);
1232
                        acum = acum + (dim * (lines.get(i)).getLs().getNumPoints());
1233
                }
1234

    
1235
                int _ind = 0;
1236
                NUMBER[] ords = new NUMBER[acum];
1237

    
1238
                for (int i = 0; i < size; i++) {
1239
                        LineString3D ls = lines.get(i);
1240
                        int num_p = ls.getLs().getNumPoints();
1241

    
1242
                        for (int j = 0; j < num_p; j++) {
1243
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1244
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1245

    
1246
                                if (threed) {
1247
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1248
                                }
1249

    
1250
                                _ind = _ind + dim;
1251
                        }
1252
                }
1253

    
1254
                STRUCT resp;
1255
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1256
                                "MDSYS.SDO_GEOMETRY", conn);
1257
                Object[] obj = new Object[5];
1258
                obj[0] = new NUMBER(geotype);
1259

    
1260
                if (hasSrid) {
1261
                        obj[1] = new NUMBER(osrid);
1262
                } else {
1263
                        obj[1] = null;
1264
                }
1265

    
1266
                obj[2] = null;
1267
                obj[3] = indices;
1268
                obj[4] = ords;
1269
                resp = new STRUCT(dsc, conn, obj);
1270

    
1271
                return resp;
1272
        }
1273

    
1274
        /**
1275
         * 
1276
         * @param pnt
1277
         * @param srid
1278
         * @param threed
1279
         * @param _conn
1280
         * @param hasSrid
1281
         * @return
1282
         * @throws SQLException
1283
         */
1284
        private static STRUCT getMultiPointAsStruct(Coordinate pnt, int osrid,
1285
                        boolean threed, Connection conn, boolean hasSrid)
1286
                        throws SQLException {
1287
                int geotype = 2001;
1288
                int dim = 2;
1289

    
1290
                if (threed) {
1291
                        geotype = 3001;
1292
                        dim = 3;
1293
                }
1294

    
1295
                Object[] ords = new Object[3];
1296
                ords[0] = new NUMBER(pnt.x);
1297
                ords[1] = new NUMBER(pnt.y);
1298
                ords[2] = (dim == 3) ? new NUMBER(pnt.z) : null;
1299

    
1300
                StructDescriptor ord_dsc = StructDescriptor.createDescriptor(
1301
                                "MDSYS.SDO_POINT_TYPE", conn);
1302
                STRUCT ords_st = new STRUCT(ord_dsc, conn, ords);
1303

    
1304
                STRUCT resp;
1305

    
1306
                StructDescriptor dsc = StructDescriptor.createDescriptor(
1307
                                "MDSYS.SDO_GEOMETRY", conn);
1308
                Object[] obj = new Object[5];
1309

    
1310
                obj[0] = new NUMBER(geotype);
1311

    
1312
                if (hasSrid) {
1313
                        obj[1] = new NUMBER(osrid);
1314
                } else {
1315
                        obj[1] = null;
1316
                }
1317

    
1318
                obj[2] = ords_st;
1319
                obj[3] = null;
1320
                obj[4] = null;
1321
                resp = new STRUCT(dsc, conn, obj);
1322

    
1323
                return resp;
1324
        }
1325

    
1326
        /**
1327
         * Utility method to compute a circle's center and radius from three given
1328
         * points.
1329
         * 
1330
         * @param points
1331
         *            three points of a circumference
1332
         * @return a 2-item array with the circumference's center (Point2D) and
1333
         *         radius (Double)
1334
         */
1335
        public static Object[] getCenterAndRadiousOfCirc(Point2D[] points) {
1336
                Object[] resp = new Object[2];
1337
                resp[0] = new Point2D.Double(0, 0);
1338
                resp[1] = new Double(0);
1339

    
1340
                double m11;
1341
                double m12;
1342
                double m13;
1343
                double m14;
1344

    
1345
                if (points.length != 3) {
1346
                        logger.error("Needs 3 points (found " + points.length
1347
                                        + ") - circle cannot be computed.");
1348

    
1349
                        // not a circle
1350
                        return resp;
1351
                }
1352

    
1353
                double[][] a = new double[3][3];
1354

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

    
1361
                m11 = determinant(a, 3);
1362

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

    
1370
                m12 = determinant(a, 3);
1371

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

    
1380
                m13 = determinant(a, 3);
1381

    
1382
                for (int i = 0; i < 3; i++) { // find minor 14
1383
                        a[i][0] = (points[i].getX() * points[i].getX())
1384
                                        + (points[i].getY() * points[i].getY());
1385
                        a[i][1] = points[i].getX();
1386
                        a[i][2] = points[i].getY();
1387
                }
1388

    
1389
                m14 = determinant(a, 3);
1390

    
1391
                Double resp_radius = new Double(0);
1392
                Point2D resp_center = new Point2D.Double(0, 0);
1393

    
1394
                if (m11 == 0) {
1395
                        logger.error("Three points aligned - circle cannot be computed."); // not
1396
                        // a
1397
                        // circle
1398
                } else {
1399
                        double x = (0.5 * m12) / m11;
1400
                        double y = (-0.5 * m13) / m11;
1401
                        resp_center.setLocation(x, y);
1402
                        resp_radius = new Double(Math.sqrt((x * x) + (y * y) + (m14 / m11)));
1403
                        resp[0] = resp_center;
1404
                        resp[1] = resp_radius;
1405
                }
1406

    
1407
                return resp;
1408
        }
1409

    
1410
        /**
1411
         * Utility method to compute a matrix determinant
1412
         * 
1413
         * @param a
1414
         *            the matrix
1415
         * @param n
1416
         *            matrix size
1417
         * @return the matrix's determinant
1418
         */
1419
        public static double determinant(double[][] a, int n) {
1420
                double resp = 0;
1421
                double[][] m = new double[3][3];
1422

    
1423
                if (n == 2) { // terminate recursion
1424
                        resp = (a[0][0] * a[1][1]) - (a[1][0] * a[0][1]);
1425
                } else {
1426
                        resp = 0;
1427

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

    
1430
                                for (int i = 1; i < n; i++) { // create minor
1431

    
1432
                                        int j2 = 0;
1433

    
1434
                                        for (int j = 0; j < n; j++) {
1435
                                                if (j == j1) {
1436
                                                        continue;
1437
                                                }
1438

    
1439
                                                m[i - 1][j2] = a[i][j];
1440
                                                j2++;
1441
                                        }
1442
                                }
1443

    
1444
                                // sum (+/-)cofactor * minor
1445
                                resp = resp
1446
                                                + (Math.pow(-1.0, j1) * a[0][j1] * determinant(m, n - 1));
1447
                        }
1448
                }
1449

    
1450
                return resp;
1451
        }
1452

    
1453
        /**
1454
         * 
1455
         * @param ls
1456
         * @param list
1457
         * @param self
1458
         * @return
1459
         */
1460
        private static int getSmallestContainerExcept(LineString3D ls,
1461
                        List<LineString3D> list, int self) {
1462
                int resp = -1;
1463
                List<Integer> provList = new ArrayList<Integer>();
1464

    
1465
                int size = list.size();
1466

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

    
1473
                for (int i = (self + 1); i < size; i++) {
1474
                        if (lineString3DIsContainedBy(ls, (LineString3D) list.get(i))) {
1475
                                provList.add(new Integer(i));
1476
                        }
1477
                }
1478

    
1479
                if (provList.size() == 0) {
1480
                        // logger.debug("LineString is not contained by any other ls.");
1481
                } else {
1482
                        if (provList.size() == 1) {
1483
                                resp = ((Integer) provList.get(0)).intValue();
1484
                        } else {
1485
                                if (provList.size() == 2) {
1486
                                        int ind_1 = ((Integer) provList.get(0)).intValue();
1487
                                        int ind_2 = ((Integer) provList.get(1)).intValue();
1488
                                        LineString3D ls1 = (LineString3D) list.get(ind_1);
1489
                                        LineString3D ls2 = (LineString3D) list.get(ind_2);
1490

    
1491
                                        if (lineString3DIsContainedBy(ls1, ls2)) {
1492
                                                resp = ind_1;
1493
                                        } else {
1494
                                                resp = ind_2;
1495
                                        }
1496
                                } else {
1497
                                        // not so deep, sorry!
1498
                                        // it's going to be a shell: resp = -1;
1499
                                }
1500
                        }
1501
                }
1502

    
1503
                return resp;
1504
        }
1505

    
1506
        /**
1507
         * 
1508
         * @param containings
1509
         * @return
1510
         */
1511
        private static int[] getIndicesOfShells(int[] containings) {
1512
                List<Integer> resp = new ArrayList<Integer>();
1513

    
1514
                for (int i = 0; i < containings.length; i++) {
1515
                        if (containings[i] == -1) {
1516
                                resp.add(new Integer(i));
1517
                        }
1518
                }
1519

    
1520
                int size = resp.size();
1521
                int[] _resp = new int[size];
1522

    
1523
                for (int i = 0; i < size; i++) {
1524
                        _resp[i] = (resp.get(i)).intValue();
1525
                }
1526

    
1527
                return _resp;
1528
        }
1529

    
1530
        /**
1531
         * 
1532
         * @param containings
1533
         * @param shells
1534
         * @return
1535
         */
1536
        private static int[] getIndicesOfHoles(int[] containings, int[] shells) {
1537
                List<Integer> resp = new ArrayList<Integer>();
1538

    
1539
                for (int i = 0; i < containings.length; i++) {
1540
                        int cont_by = containings[i];
1541

    
1542
                        if ((cont_by != -1) && (isOneOf(cont_by, shells))) {
1543
                                resp.add(new Integer(i));
1544
                        }
1545
                }
1546

    
1547
                int size = resp.size();
1548
                int[] _resp = new int[size];
1549

    
1550
                for (int i = 0; i < size; i++) {
1551
                        _resp[i] = (resp.get(i)).intValue();
1552
                }
1553

    
1554
                return _resp;
1555
        }
1556

    
1557
        /**
1558
         * 
1559
         * @param containings
1560
         * @param holes
1561
         * @return
1562
         */
1563
        private static int[] getFinalContainings(int[] containings, int[] holes) {
1564
                List<Integer> resp = new ArrayList<Integer>();
1565

    
1566
                for (int i = 0; i < containings.length; i++) {
1567
                        int cont_by = containings[i];
1568

    
1569
                        if (isOneOf(cont_by, holes)) {
1570
                                resp.add(new Integer(-1));
1571
                        } else {
1572
                                resp.add(new Integer(cont_by));
1573
                        }
1574
                }
1575

    
1576
                int size = resp.size();
1577
                int[] _resp = new int[size];
1578

    
1579
                for (int i = 0; i < size; i++) {
1580
                        _resp[i] = ((Integer) resp.get(i)).intValue();
1581
                }
1582

    
1583
                return _resp;
1584
        }
1585

    
1586
        /**
1587
         * 
1588
         * @param ind
1589
         * @param final_contn
1590
         * @param all
1591
         * @return
1592
         */
1593
        private static List<LineString3D> getHolesOf(int ind, int[] final_contn,
1594
                        List<LineString3D> all) {
1595

    
1596
                List<Integer> resp_ind = new ArrayList<Integer>();
1597

    
1598
                for (int i = 0; i < final_contn.length; i++) {
1599
                        if (final_contn[i] == ind) {
1600
                                resp_ind.add(new Integer(i));
1601
                        }
1602
                }
1603

    
1604
                List<LineString3D> resp = new ArrayList<LineString3D>();
1605

    
1606
                for (int i = 0; i < resp_ind.size(); i++) {
1607
                        Integer aux = (Integer) resp_ind.get(i);
1608
                        resp.add(all.get(aux.intValue()));
1609
                }
1610

    
1611
                return resp;
1612
        }
1613

    
1614
        /**
1615
         * 
1616
         * @param final_contn
1617
         * @param all
1618
         * @return
1619
         */
1620
        private static List<LineString3D> getShellsIn(int[] final_contn,
1621
                        List<LineString3D> all) {
1622
                List<Integer> resp_ind = new ArrayList<Integer>();
1623

    
1624
                for (int i = 0; i < final_contn.length; i++) {
1625
                        if (final_contn[i] == -1) {
1626
                                resp_ind.add(new Integer(i));
1627
                        }
1628
                }
1629

    
1630
                List<LineString3D> resp = new ArrayList<LineString3D>();
1631

    
1632
                for (int i = 0; i < resp_ind.size(); i++) {
1633
                        Integer aux = (Integer) resp_ind.get(i);
1634
                        resp.add(all.get(aux.intValue()));
1635
                }
1636

    
1637
                return resp;
1638
        }
1639

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

    
1659
                for (int i = 0; i < no_of_ls; i++) {
1660
                        LineString3D ls_aux = all_ls.get(i);
1661
                        containedby[i] = getSmallestContainerExcept(ls_aux, all_ls, i);
1662
                }
1663

    
1664
                shells = getIndicesOfShells(containedby);
1665
                holes = getIndicesOfHoles(containedby, shells);
1666
                final_cont = getFinalContainings(containedby, holes);
1667

    
1668
                // true shells:
1669
                shells = getIndicesOfShells(final_cont);
1670

    
1671
                List<LineString3D> resp_shells = new ArrayList<LineString3D>();
1672
                List resp_holes_for_shells = new ArrayList();
1673
                List<LineString3D> aux_holes;
1674

    
1675
                for (int i = 0; i < shells.length; i++) {
1676
                        resp_shells.add(all_ls.get(shells[i]));
1677
                        aux_holes = getHolesOf(i, final_cont, all_ls);
1678
                        resp_holes_for_shells.add(aux_holes);
1679
                }
1680

    
1681
                Object[] _resp = new Object[2];
1682
                _resp[0] = resp_shells;
1683
                _resp[1] = resp_holes_for_shells;
1684

    
1685
                return _resp;
1686
        }
1687

    
1688
        /**
1689
         * 
1690
         * @param listOfLists
1691
         * @return
1692
         */
1693
        private static int getTotalSize(List listOfLists) {
1694
                int resp = 0;
1695

    
1696
                for (int i = 0; i < listOfLists.size(); i++) {
1697
                        resp = resp + ((List) listOfLists.get(i)).size();
1698
                }
1699

    
1700
                return resp;
1701
        }
1702

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

    
1723
                STRUCT st = null;
1724
                
1725
                try {
1726
                        st = getMultiPolygonAsStruct(sh, ho, osrid, threed, conn, agu_bien, hasSrid);
1727
                } catch (Throwable th) {
1728
                        throw new SQLException(th.getMessage());
1729
                }
1730

    
1731
                return st; 
1732
        }
1733

    
1734
        /**
1735
         * 
1736
         * @param hh
1737
         * @return
1738
         */
1739
        private static List reverseHoles(List hh) {
1740
                List resp = new ArrayList();
1741

    
1742
                for (int i = 0; i < hh.size(); i++) {
1743
                        List item = (ArrayList) hh.get(i);
1744
                        List newitem = new ArrayList();
1745

    
1746
                        for (int j = 0; j < item.size(); j++) {
1747
                                LineString3D ls = (LineString3D) item.get(j);
1748
                                newitem.add(ls.createReverse());
1749
                        }
1750

    
1751
                        resp.add(newitem);
1752
                }
1753

    
1754
                return resp;
1755
        }
1756

    
1757
        /**
1758
         * 
1759
         * @param shells
1760
         * @param holes
1761
         * @param srid
1762
         * @param threed
1763
         * @param _conn
1764
         * @param explicito
1765
         * @param hasSrid
1766
         * @return
1767
         * @throws SQLException
1768
         */
1769
        private static STRUCT getMultiPolygonAsStruct(List shells, List holes,
1770
                        int osrid, boolean threed, Connection conn, boolean explicito,
1771
                        boolean hasSrid) throws SQLException {
1772
                int t = 1003;
1773

    
1774
                if (explicito) {
1775
                        t = 2003;
1776
                }
1777

    
1778
                int size = shells.size() + getTotalSize(holes);
1779
                int geotype = 2003;
1780
                if (size > 1)
1781
                        geotype = 2007;
1782

    
1783
                int dim = 2;
1784

    
1785
                if (threed) {
1786
                        geotype = geotype + 1000;
1787
                        dim = 3;
1788
                }
1789

    
1790
                NUMBER[] indices = new NUMBER[3 * size];
1791

    
1792
                int acum = 0;
1793
                int start_ind = 0;
1794

    
1795
                for (int i = 0; i < shells.size(); i++) {
1796
                        indices[start_ind] = new NUMBER(acum + 1);
1797
                        indices[start_ind + 1] = new NUMBER(1003);
1798
                        indices[start_ind + 2] = new NUMBER(1);
1799
                        start_ind = start_ind + 3;
1800
                        acum = acum + (dim * ((LineString3D) shells.get(i)).getLs().getNumPoints());
1801

    
1802
                        List item_holes = (List) holes.get(i);
1803

    
1804
                        for (int j = 0; j < item_holes.size(); j++) {
1805
                                indices[start_ind] = new NUMBER(acum + 1);
1806
                                indices[start_ind + 1] = new NUMBER(t); // 1003
1807
                                indices[start_ind + 2] = new NUMBER(1);
1808
                                start_ind = start_ind + 3;
1809
                                acum = acum
1810
                                                + (dim * ((LineString3D) item_holes.get(j)).getLs()
1811
                                                                .getNumPoints());
1812
                        }
1813
                }
1814

    
1815
                int _ind = 0;
1816
                NUMBER[] ords = new NUMBER[acum];
1817

    
1818
                for (int i = 0; i < shells.size(); i++) {
1819
                        // --------------------------------
1820
                        LineString3D ls = (LineString3D) shells.get(i);
1821
                        int num_p = ls.getLs().getNumPoints();
1822

    
1823
                        for (int j = 0; j < num_p; j++) {
1824
                                ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(j).x);
1825
                                ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(j).y);
1826

    
1827
                                if (threed) {
1828
                                        ords[_ind + 2] = new NUMBER(ls.getZc()[j]);
1829
                                }
1830

    
1831
                                _ind = _ind + dim;
1832
                        }
1833

    
1834
                        // -------------------------------
1835
                        List item_holes = (ArrayList) holes.get(i);
1836

    
1837
                        for (int j = 0; j < item_holes.size(); j++) {
1838
                                ls = (LineString3D) item_holes.get(j);
1839
                                num_p = ls.getLs().getNumPoints();
1840

    
1841
                                for (int k = 0; k < num_p; k++) {
1842
                                        ords[_ind] = new NUMBER(ls.getLs().getCoordinateN(k).x);
1843
                                        ords[_ind + 1] = new NUMBER(ls.getLs().getCoordinateN(k).y);
1844

    
1845
                                        if (threed) {
1846
                                                ords[_ind + 2] = new NUMBER(ls.getZc()[k]);
1847
                                        }
1848

    
1849
                                        _ind = _ind + dim;
1850
                                }
1851
                        }
1852
                }
1853

    
1854
                STRUCT resp;
1855
                StructDescriptor dsc = StructDescriptor.createDescriptor("MDSYS.SDO_GEOMETRY", conn);
1856
                Object[] obj = new Object[5];
1857
                obj[0] = new NUMBER(geotype);
1858

    
1859
                if (hasSrid) {
1860
                        obj[1] = new NUMBER(osrid);
1861
                } else {
1862
                        obj[1] = null;
1863
                }
1864

    
1865
                obj[2] = null;
1866
                obj[3] = indices;
1867
                obj[4] = ords;
1868

    
1869
                resp = new STRUCT(dsc, conn, obj);
1870

    
1871
                return resp;
1872
        }
1873

    
1874
        /**
1875
         * 
1876
         * @param array
1877
         * @return
1878
         */
1879
        public static String printArray(NUMBER[] array) {
1880
                String resp = "[ ";
1881

    
1882
                for (int i = 0; i < array.length; i++) {
1883
                        resp = resp + " " + array[i].doubleValue() + " , ";
1884
                }
1885

    
1886
                resp = resp.substring(0, resp.length() - 2) + "]";
1887

    
1888
                return resp;
1889
        }
1890

    
1891
        /**
1892
         * 
1893
         * @param ind
1894
         * @param list
1895
         * @return
1896
         */
1897
        private static boolean isOneOf(int ind, int[] list) {
1898
                for (int i = 0; i < list.length; i++) {
1899
                        if (list[i] == ind) {
1900
                                return true;
1901
                        }
1902
                }
1903
                return false;
1904
        }
1905

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

    
1933
                for (int i = 0; i < size; i++) {
1934
                        Geometry geom = geoms[i];
1935
                        sts[i] = geometryToSTRUCT(geom, conn, osridd, agu_bien, withSrid);
1936
                }
1937

    
1938
                if (size == 1) {
1939
                        return sts[0];
1940
                }
1941

    
1942
                STRUCT aux = sts[0];
1943

    
1944
                for (int i = 1; i < size; i++) {
1945
                        aux = appendStructs(aux, sts[i], conn);
1946
                }
1947

    
1948
                return aux;
1949
        }
1950

    
1951
        /**
1952
         * 
1953
         * @param st1
1954
         * @param st2
1955
         * @param _conn
1956
         * @return
1957
         */
1958
        private static STRUCT appendStructs(STRUCT st1, STRUCT st2, Connection conn) {
1959
                try {
1960
                        ARRAY _ords = (ARRAY) st1.getOracleAttributes()[4];
1961
                        int length_of_head_ords = _ords.getOracleArray().length;
1962

    
1963
                        NUMBER gtype = new NUMBER(
1964
                                        4 + (((NUMBER) st1.getOracleAttributes()[0]).intValue() / 1000));
1965
                        NUMBER srid = (NUMBER) st1.getOracleAttributes()[1];
1966
                        NUMBER middle = (NUMBER) st1.getOracleAttributes()[2];
1967

    
1968
                        ARRAY info1 = (ARRAY) st1.getOracleAttributes()[3];
1969
                        ARRAY info2 = (ARRAY) st2.getOracleAttributes()[3];
1970
                        ARRAY ords1 = (ARRAY) st1.getOracleAttributes()[4];
1971
                        ARRAY ords2 = (ARRAY) st2.getOracleAttributes()[4];
1972

    
1973
                        Datum[] info = appendDatumArrays(info1.getOracleArray(), info2
1974
                                        .getOracleArray(), length_of_head_ords);
1975

    
1976
                        Datum[] ords = appendDatumArrays(ords1.getOracleArray(), ords2
1977
                                        .getOracleArray(), 0);
1978

    
1979
                        StructDescriptor dsc = st1.getDescriptor();
1980

    
1981
                        Object[] atts = new Object[5];
1982
                        atts[0] = gtype;
1983
                        atts[1] = srid;
1984
                        atts[2] = middle;
1985
                        atts[3] = info;
1986
                        atts[4] = ords;
1987

    
1988
                        STRUCT resp = new STRUCT(dsc, conn, atts);
1989

    
1990
                        return resp;
1991
                } catch (SQLException sqle) {
1992
                        logger.error("While appending structs: " + sqle.getMessage(), sqle);
1993
                }
1994

    
1995
                return null;
1996
        }
1997

    
1998
        /**
1999
         * 
2000
         * @param head
2001
         * @param tail
2002
         * @param offset
2003
         * @return
2004
         */
2005
        private static Datum[] appendDatumArrays(Datum[] head, Datum[] tail,
2006
                        int offset) {
2007
                int head_l = head.length;
2008
                int tail_l = tail.length;
2009
                Datum[] resp = new Datum[head_l + tail_l];
2010

    
2011
                for (int i = 0; i < head_l; i++)
2012
                        resp[i] = head[i];
2013

    
2014
                if (offset == 0) {
2015
                        for (int i = 0; i < tail_l; i++)
2016
                                resp[head_l + i] = tail[i];
2017
                } else {
2018
                        try {
2019
                                for (int i = 0; i < tail_l; i++) {
2020
                                        if ((i % 3) == 0) {
2021
                                                resp[head_l + i] = new NUMBER(tail[i].intValue()
2022
                                                                + offset);
2023
                                        } else {
2024
                                                resp[head_l + i] = tail[i];
2025
                                        }
2026
                                }
2027
                        } catch (SQLException se) {
2028
                                logger.error("Unexpected error: " + se.getMessage());
2029
                        }
2030
                }
2031

    
2032
                return resp;
2033
        }
2034

    
2035
        /**
2036
         * Utility method to get an ineteger as a formatted string.
2037
         * 
2038
         * @param n
2039
         *            the integer
2040
         * @return the formatted string
2041
         */
2042
        public static String getFormattedInteger(int n) {
2043
                df.setGroupingUsed(true);
2044
                df.setGroupingSize(3);
2045
                dfs.setGroupingSeparator('.');
2046
                df.setDecimalFormatSymbols(dfs);
2047

    
2048
                return df.format(n);
2049
        }
2050

    
2051
        /**
2052
         * Tells whether these arrays belong to a rectangle polygon.
2053
         * 
2054
         * @param info
2055
         *            the struct's element info array
2056
         * @param ords
2057
         *            the struct's coordinate array
2058
         * @return true if it is a rectangle polygon. false otherwise.
2059
         */
2060
        public static boolean polStructIsRectStruct(ARRAY info, ARRAY ords) {
2061
                try {
2062
                        int[] infos = info.getIntArray();
2063

    
2064
                        return ((infos[2] == 3) && (infos.length == 3));
2065
                } catch (SQLException se) {
2066
                        logger.error("While ckecking rectangle: " + se.getMessage(), se);
2067
                }
2068

    
2069
                return false;
2070
        }
2071

    
2072
        /**
2073
         * Utility method to deal with oracle info arrays.
2074
         */
2075
        public static ARRAY getDevelopedInfoArray(ARRAY info) {
2076
                ARRAY _resp = null;
2077

    
2078
                try {
2079
                        Datum[] resp = new Datum[3];
2080
                        Datum[] in = info.getOracleArray();
2081
                        resp[0] = in[0];
2082
                        resp[1] = in[1];
2083
                        resp[2] = new NUMBER(1);
2084
                        _resp = new ARRAY(info.getDescriptor(), info
2085
                                        .getInternalConnection(), resp);
2086
                } catch (SQLException se) {
2087
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
2088
                }
2089

    
2090
                return _resp;
2091
        }
2092

    
2093
        /**
2094
         * Utility method to deal with oracle coordinate arrays.
2095
         */
2096
        public static ARRAY getDevelopedOrdsArray(ARRAY ords, int dim) {
2097
                ARRAY _resp = null;
2098

    
2099
                try {
2100
                        int n = 5*2; // dim = 2, ignored parameter dim
2101
                        Datum[] resp = new Datum[n];
2102
                        Datum[] corners = ords.getOracleArray();
2103

    
2104
                        for (int i=0; i<5; i++) {
2105
                                resp[i*2] = ((i==2) || (i==3)) ? corners[dim] : corners[0];
2106
                        }
2107
                        for (int i=0; i<5; i++) {
2108
                                resp[1+i*2] = ((i==1) || (i==2)) ? corners[dim+1] : corners[1];
2109
                        }
2110
                        _resp = new ARRAY(ords.getDescriptor(), ords
2111
                                        .getInternalConnection(), resp);
2112
                } catch (SQLException se) {
2113
                        logger.error("While creating ARRAY: " + se.getMessage(), se);
2114
                }
2115

    
2116
                return _resp;
2117
        }
2118

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

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

    
2142
                        dims = ((NUMBER) aux[0]).intValue() / 1000;
2143

    
2144
                        if (dims == 0) {
2145
                                dims = 2;
2146
                        }
2147

    
2148
                        if (polStructIsRectStruct(infoARRAY, ordsARRAY)) {
2149
                                infoARRAY = getDevelopedInfoArray(infoARRAY);
2150
                                ordsARRAY = getDevelopedOrdsArray(ordsARRAY, dims);
2151
                                // rect is always 2d
2152
                                dims = 2;
2153
                        }
2154

    
2155
                        info_array = (Datum[]) infoARRAY.getOracleArray();
2156
                        ords_array = (Datum[]) ordsARRAY.getOracleArray();
2157
                        info_array_size = info_array.length / 3;
2158

    
2159
                        int last_index = ords_array.length - dims + 1;
2160

    
2161
                        // set indices:
2162
                        start_ind = new int[info_array_size];
2163
                        end_ind = new int[info_array_size];
2164

    
2165
                        for (int i = 0; i < info_array_size; i++)
2166
                                start_ind[i] = ((NUMBER) info_array[3 * i]).intValue();
2167

    
2168
                        for (int i = 0; i < (info_array_size - 1); i++)
2169
                                end_ind[i] = start_ind[i + 1] - 1;
2170

    
2171
                        end_ind[info_array_size - 1] = last_index;
2172

    
2173
                        int lineType = PathIterator.SEG_LINETO;
2174

    
2175
                        if (end_ind[0] == 0) { // collection of paths
2176

    
2177
                                for (int i = 1; i < info_array_size; i++) {
2178
                                        lineType = getLineToType(info_array, i);
2179

    
2180
                                        // -----------------------
2181
                                        if (end_ind[i] == (start_ind[i] - 1))
2182
                                                lineType = PathIterator.SEG_MOVETO;
2183
                                        // -----------------------
2184

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

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

    
2204
                return resp;
2205
        }
2206

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

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

    
2225
                return resp;
2226
        }
2227

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

    
2246
                double x = ((NUMBER) ords[zero_based_start]).doubleValue();
2247
                double y = ((NUMBER) ords[zero_based_start + 1]).doubleValue();
2248

    
2249
                if (must_do_first) {
2250
                        if (do_the_move) {
2251
                                gpx.moveTo(x, y);
2252
                        } else {
2253
                                gpx.lineTo(x, y);
2254
                        }
2255
                }
2256

    
2257
                int ind = 1;
2258

    
2259
                int size = ((zero_based_include_end - zero_based_start) / d) + 1;
2260
                int indx;
2261
                int indx2;
2262

    
2263
                if (ltype == PathIterator.SEG_QUADTO) { // (interpretation = 2)
2264

    
2265
                        double x2;
2266
                        double y2;
2267

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

    
2273
                                indx2 = zero_based_start + ((ind + 1) * d);
2274

    
2275
                                if (indx >= length) {
2276
                                        indx2 = zero_based_start;
2277
                                }
2278

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

    
2286
                        return_following_must_do_first = false;
2287
                } else { // PathIterator.SEG_LINETO (interpretation = 1)
2288

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

    
2298
                return return_following_must_do_first;
2299
        }
2300

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

    
2312
                case OracleValues.ORACLE_GTYPE_POINT:
2313
                case OracleValues.ORACLE_GTYPE_MULTIPOINT:
2314
                        return Geometry.TYPES.POINT;
2315

    
2316
                case OracleValues.ORACLE_GTYPE_LINE:
2317
                case OracleValues.ORACLE_GTYPE_MULTILINE:
2318
                        return Geometry.TYPES.CURVE;
2319

    
2320
                case OracleValues.ORACLE_GTYPE_POLYGON:
2321
                case OracleValues.ORACLE_GTYPE_MULTIPOLYGON:
2322
                        return Geometry.TYPES.SURFACE;
2323

    
2324
                case OracleValues.ORACLE_GTYPE_COLLECTION:
2325
                        return Geometry.TYPES.AGGREGATE;
2326
                }
2327

    
2328
                logger.warn("Unknown oracle geometry type: " + otype);
2329

    
2330
                return Geometry.TYPES.NULL;
2331
        }
2332

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

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

    
2349
                return resp;
2350
        }
2351

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

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

    
2368
                return resp;
2369
        }
2370

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

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

    
2386
                        return false;
2387
                }
2388

    
2389
                if (info == null) {
2390
                        return false;
2391
                }
2392

    
2393
                boolean resp = ((info.length == 3) && (info[2] == 4));
2394

    
2395
                return resp;
2396
        }
2397

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

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

    
2414
                if (resp < 2) {
2415
                        resp = 2;
2416
                }
2417

    
2418
                return resp;
2419
        }
2420
        
2421

    
2422

    
2423

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

    
2434
                try {
2435
                        ARRAY aux = (ARRAY) the_data[4];
2436

    
2437
                        if (aux == null) {
2438
                                return null;
2439
                        }
2440

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

    
2446
                return resp;
2447
        }
2448

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

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

    
2481
                return null;
2482
        }
2483

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

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

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

    
2528
                String qry = "SELECT SDO_CS.TRANSFORM( ?, " + toSrid + ") FROM DUAL";
2529
                STRUCT resp = null;
2530

    
2531
                try {
2532
                        PreparedStatement _st = conn.prepareStatement(qry);
2533
                        _st.setObject(1, fromStruct);
2534
                        ResultSet _rs = _st.executeQuery();
2535

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

    
2548
                if (resp == null) {
2549
                        return fromStruct;
2550
                } else {
2551
                        return resp;
2552
                }
2553
        }
2554

    
2555
        /**
2556
         * 
2557
         * @param st
2558
         */
2559
        public static void printStruct(STRUCT st) {
2560

    
2561
                logger.debug("----------------------------------------------");
2562
                logger.debug("-- 16 FEBRERO 2009 ---------------------------");
2563
                logger.debug("----------------------------------------------");
2564

    
2565
                try {
2566
                        Object[] att = st.getAttributes();
2567
                        int l = att.length;
2568

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

    
2586
        }
2587

    
2588
        /**
2589
         * 
2590
         * @param arr
2591
         * @throws Exception
2592
         */
2593
        private static void printARRAY(ARRAY arr) throws Exception {
2594

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

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

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

    
2627
                int resp = Geometry.TYPES.NULL;
2628

    
2629
                if (complex) {
2630

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

    
2641
                } else {
2642

    
2643
                        // =========== not complex =================
2644
                        switch (otype) {
2645
                        case OracleValues.ORACLE_GTYPE_UNKNOWN:
2646
                                resp = Geometry.TYPES.NULL;
2647
                                break;
2648

    
2649
                        case OracleValues.ORACLE_GTYPE_POINT:
2650
                        case OracleValues.ORACLE_GTYPE_MULTIPOINT:
2651
                                resp = Geometry.TYPES.POINT;
2652
                                break;
2653

    
2654
                        case OracleValues.ORACLE_GTYPE_LINE:
2655
                        case OracleValues.ORACLE_GTYPE_MULTILINE:
2656
                                resp = Geometry.TYPES.CURVE;
2657
                                break;
2658

    
2659
                        case OracleValues.ORACLE_GTYPE_POLYGON:
2660
                        case OracleValues.ORACLE_GTYPE_MULTIPOLYGON:
2661
                                resp = Geometry.TYPES.SURFACE;
2662
                                break;
2663

    
2664
                        case OracleValues.ORACLE_GTYPE_COLLECTION:
2665
                                resp = Geometry.TYPES.AGGREGATE;
2666
                                break;
2667
                        }
2668
                        // =========== not complex =================
2669
                }
2670

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

    
2677
        /**
2678
         * 
2679
         * @param name
2680
         * @param arr
2681
         * @return
2682
         */
2683
        private static boolean isOneOfThese(String name, String[] arr) {
2684

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

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

    
2703
                HashMap m = new HashMap();
2704

    
2705
                for (int i = 0; i < tt.size(); i++) {
2706
                        Integer integ = (Integer) tt.get(i);
2707
                        int val = integ.intValue();
2708

    
2709
                        if ((val == 4) && (!are_dims)) {
2710
                                return true;
2711
                        }
2712

    
2713
                        m.put("" + (val % 4), "a type");
2714
                }
2715

    
2716
                Iterator iter = m.keySet().iterator();
2717
                iter.next();
2718

    
2719
                return iter.hasNext();
2720
        }
2721

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

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

    
2742
                for (int i = 0; i < size; i++) {
2743
                        resp[i] = input[(i * n) + ind];
2744
                }
2745

    
2746
                return resp;
2747
        }
2748

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

    
2761
                for (int i = 0; i < size; i++) {
2762
                        resp[i] = input[(i * n) + ind];
2763
                }
2764

    
2765
                return resp;
2766
        }
2767

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

    
2778
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2779

    
2780
                Geometry geom = null;
2781

    
2782
                if (OracleUtils.isCircle(the_data)) {
2783
                        geom = getCircleFromStruct(the_data);
2784
                } else {
2785
                        GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2786

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

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

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

    
2808
                return geom;
2809
        }
2810

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

    
2820
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2821

    
2822
                double[] threep = null;
2823

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

    
2830
                        return geomManager.createNullGeometry(Geometry.SUBTYPES.GEOM2D);
2831
                }
2832

    
2833
                Point2D[] three = new Point2D.Double[3];
2834
                three[0] = new Point2D.Double(threep[0], threep[1]);
2835
                three[1] = new Point2D.Double(threep[2], threep[3]);
2836
                three[2] = new Point2D.Double(threep[4], threep[5]);
2837

    
2838
                Object[] cent_rad = OracleUtils.getCenterAndRadiousOfCirc(three);
2839

    
2840
                Point2D cent = (Point2D) cent_rad[0];
2841
                double radious = ((Double) cent_rad[1]).doubleValue();
2842

    
2843
                Geometry circ = geomManager.create(Geometry.TYPES.CIRCLE,
2844
                                Geometry.SUBTYPES.GEOM2D);
2845
                ((Circle2D) circ).setPoints(cent, radious);
2846

    
2847
                return circ;
2848
        }
2849

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

    
2860
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2861

    
2862
                GeneralPathX gpx = OracleUtils.structToGPX(the_data);
2863
                Geometry geom = null;
2864
                double[] ords = null;
2865

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

    
2871
                        double[] z = getIndBigDecimalModule(ords, 2, dim);
2872
                        geom = geomManager.createCurve(gpx, Geometry.SUBTYPES.GEOM3D);
2873
                        for (int i = 0; i < z.length; i++) {
2874
                                ((Curve2DZ) geom).setCoordinateAt(i, 2, z[i]);
2875
                        }
2876
                }
2877

    
2878
                return geom;
2879
        }
2880

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

    
2891
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2892

    
2893
                double[] ords = OracleUtils.getOrds(the_data);
2894

    
2895
                if (ords == null) { // sdo_point
2896

    
2897
                        return getFMapGeometrySdoPoint(the_data, dim);
2898
                }
2899

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

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

    
2911
                        if (dim >= 3) {
2912
                                z[i] = ords[(i * dim) + 2];
2913
                        }
2914
                }
2915

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

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

    
2947
                return geom;
2948
        }
2949

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

    
2960
                GeometryManager geomManager = GeometryLocator.getGeometryManager();
2961

    
2962
                double x = 0;
2963
                double y = 0;
2964
                double z = 0;
2965

    
2966
                try {
2967
                        Datum[] aux = ((STRUCT) the_data[2]).getOracleAttributes();
2968
                        x = ((NUMBER) aux[0]).doubleValue();
2969
                        y = ((NUMBER) aux[1]).doubleValue();
2970

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

    
2979
                Geometry geom = null;
2980

    
2981
                if (d == 2) {
2982
                        geom = geomManager.createPoint(x, y, Geometry.SUBTYPES.GEOM2D);
2983
                } else {
2984

    
2985
                        Point2DZ point = (Point2DZ) geomManager.create(
2986
                                        Geometry.TYPES.POINT, Geometry.SUBTYPES.GEOM3D);
2987
                        point.setX(x);
2988
                        point.setY(y);
2989
                        point.setCoordinateAt(2, z);
2990
                        geom = point;
2991
                }
2992

    
2993
                return geom;
2994
        }
2995

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

    
3004
                try {
3005
                        ARRAY aux = (ARRAY) the_data[3];
3006

    
3007
                        if (aux == null) {
3008
                                return false;
3009
                        }
3010

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

    
3017
                if (info == null) {
3018
                        return false; // sdo_point
3019
                }
3020

    
3021
                int size = info.length / 3;
3022

    
3023
                if (size == 1) {
3024
                        return false;
3025
                }
3026

    
3027
                if (size == 2) {
3028
                        return ((info[1] % 1000) != (info[4] % 1000))
3029
                                        && (!((info[1] == 1005) && (info[4] == 2)));
3030
                }
3031

    
3032
                int second = info[4] % 1000;
3033
                int item = 0;
3034

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

    
3042
                return false;
3043
        }
3044

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

    
3054
                try {
3055
                        int rest = info[0].intValue() - 1;
3056

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

    
3066
                return resp;
3067
        }
3068

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

    
3079
                for (int i = first_inc; i <= last_inc; i++) {
3080
                        resp[i - first_inc] = all[i];
3081
                }
3082

    
3083
                return resp;
3084
        }
3085

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

    
3097
                if (resp.length == 1) {
3098
                        resp[0] = all;
3099

    
3100
                        return resp;
3101
                }
3102

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

    
3108
                int _start = _end + 1;
3109
                resp[ind] = ord_aux;
3110
                ind++;
3111

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

    
3121
                // last
3122
                _end = all.length - 1;
3123
                ord_aux = getSubSet(all, _start, _end);
3124
                resp[groups.length - 1] = ord_aux;
3125

    
3126
                return resp;
3127
        }
3128

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

    
3138
                if (resp.length == 1) {
3139
                        resp[0] = all;
3140

    
3141
                        return resp;
3142
                }
3143

    
3144
                int ind = 0;
3145
                int[] aux = (int[]) groups[1];
3146
                int _end = aux[0] - 2;
3147
                double[] ord_aux = getSubSet(all, 0, _end);
3148

    
3149
                int _start = _end + 1;
3150
                resp[ind] = ord_aux;
3151
                ind++;
3152

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

    
3162
                // last
3163
                _end = all.length - 1;
3164
                ord_aux = getSubSet(all, _start, _end);
3165
                resp[groups.length - 1] = ord_aux;
3166

    
3167
                return resp;
3168
        }
3169

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

    
3178
                int size = all_elem.length / 3;
3179

    
3180
                int[] aux = getNthGroupOfThree(all_elem, 0);
3181

    
3182
                int[] newaux;
3183
                int i = 1;
3184

    
3185
                while (i < size) {
3186
                        newaux = getNthGroupOfThree(all_elem, i);
3187

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

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

    
3207
                        i++;
3208
                }
3209

    
3210
                resp.add(aux);
3211

    
3212
                return resp.toArray();
3213
        }
3214

    
3215
        /**
3216
         * 
3217
         * @param all_elem
3218
         * @return
3219
         */
3220
        public static boolean isSimpleCollectionOfLines(Datum[] all_elem) {
3221

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

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

    
3234
                } catch (SQLException ex) {
3235
                        logger.error("While is simple line collection: " + ex.getMessage());
3236
                }
3237

    
3238
                return false;
3239
        }
3240

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

    
3254
        /**
3255
         * 
3256
         * @param all_elem
3257
         * @return
3258
         */
3259
        public static Object[] groupByElement(Datum[] all_elem) {
3260

    
3261
                if (isSimpleCollectionOfLines(all_elem)) {
3262
                        Object[] r = new Object[1];
3263
                        r[0] = removeThreeFirst(all_elem);
3264
                        return r;
3265
                }
3266

    
3267
                List resp = new ArrayList();
3268

    
3269
                int size = all_elem.length / 3;
3270

    
3271
                Datum[] aux = getNthGroupOfThree(all_elem, 0);
3272

    
3273
                Datum[] newaux;
3274
                int i = 1;
3275
                boolean add_last_time = true;
3276

    
3277
                try {
3278
                        while (i < size) {
3279
                                newaux = getNthGroupOfThree(all_elem, i);
3280

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

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

    
3304
                                i++;
3305
                        }
3306
                } catch (SQLException se) {
3307
                        logger.error("Unexpected error: " + se.getMessage());
3308
                }
3309

    
3310
                if (add_last_time) {
3311
                        resp.add(aux);
3312
                }
3313

    
3314
                return resp.toArray();
3315
        }
3316

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

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

    
3337
                STRUCT resp = null;
3338

    
3339
                try {
3340

    
3341
                        int size = 5;
3342
                        Object[] new_obj = new Object[size];
3343

    
3344
                        new_obj[0] = new NUMBER(2003);
3345

    
3346
                        if (hasSrid) {
3347
                                new_obj[1] = new NUMBER(osrid);
3348
                        } else {
3349
                                new_obj[1] = null;
3350
                        }
3351

    
3352
                        new_obj[2] = null;
3353

    
3354
                        NUMBER[] elem_info = new NUMBER[3];
3355
                        elem_info[0] = new NUMBER(1);
3356
                        elem_info[1] = new NUMBER(1003);
3357
                        elem_info[2] = new NUMBER(3);
3358
                        new_obj[3] = elem_info;
3359

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

    
3368
                        StructDescriptor dsc = StructDescriptor.createDescriptor(
3369
                                        "MDSYS.SDO_GEOMETRY", __conn);
3370

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

    
3377
                return resp;
3378
        }
3379

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

    
3391
                if (r2.getMaxX() <= r1.getMinX()) {
3392
                        return null;
3393
                }
3394

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

    
3399
                if (r2.getMaxY() <= r1.getMinY()) {
3400
                        return null;
3401
                }
3402

    
3403
                double minx = Math.max(r1.getMinX(), r2.getMinX());
3404
                double miny = Math.max(r1.getMinY(), r2.getMinY());
3405
                double maxx = Math.min(r1.getMaxX(), r2.getMaxX());
3406
                double maxy = Math.min(r1.getMaxY(), r2.getMaxY());
3407

    
3408
                double w = maxx - minx;
3409
                double h = maxy - miny;
3410

    
3411
                return new Rectangle2D.Double(minx, miny, w, h);
3412
        }
3413

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

    
3426
                if (!thas)
3427
                        return false;
3428
                if (oracleSRID2 == null)
3429
                        return false;
3430

    
3431
                int ora_cs = 0;
3432

    
3433
                try {
3434
                        ora_cs = Integer.parseInt(oracleSRID2);
3435
                } catch (Exception ex) {
3436
                        return false;
3437
                }
3438

    
3439
                if (
3440
                                ((ora_cs >= 8000) && (ora_cs <= 8999))
3441
                                ||
3442
                                (ora_cs == 524288)
3443
                                ||
3444
                                ((ora_cs >= 4000) && (ora_cs <= 4999))
3445
                                ) {
3446
                        return true;
3447
                } else {
3448
                        return false;
3449
                }
3450
        }
3451

    
3452
        /**
3453
         * 
3454
         * @param sample input STRUCT
3455
         * @return type and subtype of geometry
3456
         * @throws SQLException
3457
         */
3458
        public static int[] getGeoTypeSubTypeOfStruct(STRUCT sample) throws SQLException {
3459

    
3460
                int _code = ((NUMBER) sample.getOracleAttributes()[0]).intValue();
3461
                return getGeoTypeSubTypeOfOracleCode(_code);
3462
        }
3463

    
3464
        
3465
        public static int[] getGeoTypeSubTypeOfOracleCode(int code) {
3466

    
3467
                // [TYPES.?, SUBTYPES.?]
3468
                int[] resp = new int[2];
3469
                
3470
                int type_part = code % 10;
3471
                int dim_part = code / 1000;
3472

    
3473
                resp[1] = SUBTYPES.GEOM2D;
3474
                if (dim_part == 3) {
3475
                        resp[1] = SUBTYPES.GEOM3D;
3476
                } else {
3477
                        if (dim_part == 4) {
3478
                                resp[1] = SUBTYPES.GEOM3DM;
3479
                        }
3480
                }
3481

    
3482
                resp[0] = TYPES.GEOMETRY;
3483
                
3484
                switch (type_part) {
3485
                case 1:
3486
                        resp[0] = Geometry.TYPES.POINT;
3487
                        break;
3488
                case 2:
3489
                        resp[0] = Geometry.TYPES.CURVE;
3490
                        break;
3491
                case 3:
3492
                        resp[0] = Geometry.TYPES.SURFACE;
3493
                        break;
3494
                case 4:
3495
                        resp[0] = Geometry.TYPES.AGGREGATE;
3496
                        break;
3497
                case 5:
3498
                        resp[0] = Geometry.TYPES.MULTIPOINT;
3499
                        break;
3500
                case 6:
3501
                        resp[0] = Geometry.TYPES.CURVE;
3502
                        break;
3503
                case 7:
3504
                        resp[0] = Geometry.TYPES.SURFACE;
3505
                        break;
3506
                default:
3507
                        logger.error("Unknown geometry type: " + code);
3508
                break;
3509
                }
3510

    
3511
                return resp;
3512
        }
3513
        /**
3514
         * 
3515
         * @param info
3516
         * @return
3517
         */
3518
        public static int[] updateIndexes(int[] info) {
3519
                int size = info.length / 3;
3520
                int[] resp = new int[3 * size];
3521
                int rest = info[0] - 1;
3522

    
3523
                for (int i = 0; i < size; i++) {
3524
                        resp[3 * i] = info[3 * i] - rest;
3525
                        resp[(3 * i) + 1] = info[(3 * i) + 1];
3526
                        resp[(3 * i) + 2] = info[(3 * i) + 2];
3527
                }
3528

    
3529
                return resp;
3530
        }
3531

    
3532
        /**
3533
         * 
3534
         * @param head
3535
         * @param tail
3536
         * @return
3537
         */
3538
        public static int[] appendIntArrays(int[] head, int[] tail) {
3539
                int[] resp = new int[head.length + tail.length];
3540
                int hsize = head.length;
3541

    
3542
                for (int i = 0; i < hsize; i++) {
3543
                        resp[i] = head[i];
3544
                }
3545

    
3546
                for (int i = 0; i < tail.length; i++) {
3547
                        resp[hsize + i] = tail[i];
3548
                }
3549

    
3550
                return resp;
3551
        }
3552

    
3553
        /**
3554
         * 
3555
         * @param head
3556
         * @param tail
3557
         * @return
3558
         */
3559
        public static Datum[] appendDatArrays(Datum[] head, Datum[] tail) {
3560
                Datum[] resp = new Datum[head.length + tail.length];
3561
                int hsize = head.length;
3562

    
3563
                for (int i = 0; i < hsize; i++) {
3564
                        resp[i] = head[i];
3565
                }
3566

    
3567
                for (int i = 0; i < tail.length; i++) {
3568
                        resp[hsize + i] = tail[i];
3569
                }
3570

    
3571
                return resp;
3572
        }
3573

    
3574
        /**
3575
         * 
3576
         * @param list
3577
         * @param n
3578
         * @return
3579
         */
3580
        public static int[] getNthGroupOfThree(int[] list, int n) {
3581
                int[] resp = new int[3];
3582
                resp[0] = list[3 * n];
3583
                resp[1] = list[(3 * n) + 1];
3584
                resp[2] = list[(3 * n) + 2];
3585

    
3586
                return resp;
3587
        }
3588

    
3589
        /**
3590
         * 
3591
         * @param list
3592
         * @param n
3593
         * @return
3594
         */
3595
        public static Datum[] getNthGroupOfThree(Datum[] list, int n) {
3596
                Datum[] resp = new Datum[3];
3597
                resp[0] = list[3 * n];
3598
                resp[1] = list[(3 * n) + 1];
3599
                resp[2] = list[(3 * n) + 2];
3600

    
3601
                return resp;
3602
        }
3603

    
3604
        /**
3605
         * 
3606
         * @param all
3607
         * @param first_inc
3608
         * @param last_inc
3609
         * @return
3610
         */
3611
        public static Datum[] getSubSet(Datum[] all, int first_inc, int last_inc) {
3612
                Datum[] resp = new Datum[last_inc - first_inc + 1];
3613

    
3614
                for (int i = first_inc; i <= last_inc; i++) {
3615
                        resp[i - first_inc] = all[i];
3616
                }
3617

    
3618
                return resp;
3619
        }
3620

    
3621
        /**
3622
         * 
3623
         * @param _type
3624
         * @return
3625
         */
3626
        public static int maxSizeForFieldType(int _type) {
3627
                switch (_type) {
3628
                case Types.VARCHAR:
3629
                        return OracleValues.VARCHAR2_STANDARD_SIZE;
3630

    
3631
                case Types.LONGVARCHAR:
3632
                        return OracleValues.VARCHAR2_LONG_SIZE;
3633
                }
3634

    
3635
                return -1;
3636
        }
3637

    
3638
        /**
3639
         * 
3640
         * @param tname
3641
         * @param suffix
3642
         * @return
3643
         */
3644
        public static String getDerivedName(String tname, String suffix) {
3645
                int ind = tname.lastIndexOf(".");
3646
                if (ind == -1) {
3647
                        int l = Math.min(28, tname.length());
3648
                        return tname.substring(0, l) + "_" + suffix;
3649
                } else {
3650
                        String pre = tname.substring(0, ind);
3651
                        String post = tname.substring(ind + 1, tname.length());
3652
                        int lpost = Math.min(24, post.length());
3653
                        int lpre = Math.min(3, pre.length());
3654
                        return pre.substring(0, lpre) + "_" + post.substring(0, lpost)
3655
                                        + "_" + suffix;
3656
                }
3657
        }
3658

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

    
3701
        /**
3702
         * Utility method to convert a gvSIG Geometry into a oracle STRUCT
3703
         * 
3704
         * @param geom
3705
         *            the FShape object
3706
         * @param c
3707
         *            the connection
3708
         * @param srid
3709
         *            the SRS (oracle code)
3710
         * @param agu_b
3711
         *            whether to check holes validity
3712
         * @param hasSrid
3713
         *            whether the SRS is non-NULL
3714
         * @return a oracle struct representing the geometry
3715
         * 
3716
         * @throws SQLException
3717
         */
3718
        public static STRUCT geometryToSTRUCT(Geometry geom, Connection conn,
3719
                        int osrid, boolean agu_b, boolean hasSrid) throws SQLException {
3720

    
3721
                boolean three = false;
3722

    
3723
                if (geom.getDimension() == 3) {
3724
                        three = true;
3725
                }
3726

    
3727
                STRUCT resp = null;
3728

    
3729
                if (geom instanceof MultiPoint2D) {
3730
                        resp = multiPoint2DToStruct((MultiPoint2D) geom, conn, osrid,
3731
                                        hasSrid);
3732
                        return resp;
3733
                }
3734

    
3735
                if (geom instanceof Point2D) { // point 2/3d
3736
                        Coordinate p = getSingleCoordinate((Point) geom);
3737
                        resp = getMultiPointAsStruct(p, osrid, three, conn, hasSrid);
3738
                } else {
3739
                        if (geom instanceof Surface2D) { // polygon 2/3d
3740

    
3741
                                if (geom instanceof Circle2D) {
3742
                                        resp = getCircleAsStruct((Circle2D) geom, osrid, conn,
3743
                                                        hasSrid);
3744
                                } else {
3745
                                        // also FEllipse2D
3746
                                        resp = getMultiPolygonAsStruct(geom, osrid, three, conn,
3747
                                                        agu_b, hasSrid);
3748
                                }
3749
                        } else { // line 2/3d
3750

    
3751
                                List<LineString3D> _lines = getLineStrings(geom);
3752
                                resp = getMultiLineAsStruct(_lines, osrid, three, conn, hasSrid);
3753
                        }
3754
                }
3755

    
3756
                return resp;
3757
        }
3758
        
3759
        
3760
        
3761

    
3762

    
3763

    
3764
        public static int getShapeTypeFromArray(ArrayList arrlist) {
3765
                
3766
                int resp = ((Integer) arrlist.get(0)).intValue();
3767
                
3768
                int sz = arrlist.size();
3769
                int aux = 0;
3770
                for (int i=1; i<sz; i++) {
3771
                        aux = ((Integer) arrlist.get(i)).intValue();
3772
                        if (aux != resp) return TYPES.GEOMETRY;
3773
                }
3774
                return resp;
3775
        }
3776

    
3777
        // condition using ROWNUM with growing indexs to do a size-independent sample
3778
    public static String EXPONENTIAL_INDICES_CONDITION = null;
3779
    static {
3780
                EXPONENTIAL_INDICES_CONDITION = "(rownum < 40)";
3781
    }
3782
    
3783
    
3784
        public static void copyFeatureTypeToOracleStoreParams(
3785
                        EditableFeatureType efType, OracleStoreParameters params) {
3786
                
3787
                
3788
                // TODO Auto-generated method stub
3789
                
3790
        }
3791
        
3792

    
3793
    
3794
    /**
3795
     * Utility method to transform a struct into a IGeometry.
3796
     *
3797
     * @param st the struct to be converted
3798
     * @param complex comes from a complex sdo geometry
3799
     * @return the IGeometry
3800
     */
3801
    public static Geometry getGeometry(
3802
                    STRUCT st,
3803
                    boolean complex,
3804
                    boolean __tablehassrid,
3805
                    String __tablesrid,
3806
                    Connection _conn) {
3807

    
3808
            if (st == null) {
3809
                    Geometry aux = null;
3810
                    aux = createNullGeometry(SUBTYPES.GEOM2D);
3811
                    return aux;
3812
            }
3813

    
3814
        Datum[] the_data = null;
3815

    
3816
        try {
3817
            the_data = st.getOracleAttributes();
3818

    
3819
            int jgtype = ((NUMBER) the_data[0]).intValue() % 1000;
3820
            jgtype = oracleGTypeToFShapeType(jgtype, complex);
3821

    
3822
            int dim = ((NUMBER) the_data[0]).intValue() / 1000;
3823

    
3824
            if (dim < 2) {
3825
                dim = 2;
3826
            }
3827

    
3828
            int subty = getSubTypeFromDims(dim);
3829
            Geometry ig = createNullGeometry(subty);
3830

    
3831
            if (isActuallyACollection(the_data)) {
3832
                jgtype = TYPES.AGGREGATE;
3833
            }
3834

    
3835
            switch (jgtype) {
3836
            case TYPES.AGGREGATE:
3837
                ig = getFMapGeometryCollection(the_data, dim, __tablehassrid, __tablesrid, _conn);
3838
                break;
3839

    
3840
            case TYPES.POINT:
3841
                ig = getFMapGeometryPoint(the_data, dim);
3842
                break;
3843

    
3844
            case TYPES.CURVE:
3845
                ig = getFMapGeometryMultiLineString(the_data, dim);
3846
                break;
3847

    
3848
            case TYPES.SURFACE:
3849
                ig = getFMapGeometryMultipolygon(the_data, dim);
3850
                break;
3851
            }
3852

    
3853
            return ig;
3854
        } catch (Exception e) {
3855
            logger.error("While creating Geometry from STRUCT: " + e.getMessage());
3856
        }
3857
        return null;
3858
    }
3859
    
3860
    
3861
    /**
3862
     * Utility method to transform a struct into a IGeometry.
3863
     *
3864
     * @param st the struct to be converted
3865
     * @param complex comes from a complex sdo geometry
3866
     * @return the IGeometry
3867
     */
3868
    public static Primitive getPrimitive(STRUCT st, boolean complex) {
3869

    
3870
            GeometryManager gm = GeometryLocator.getGeometryManager();
3871
            Primitive resp = null;
3872
            
3873
            if (st == null) {
3874
                    try {
3875
                                resp = gm.createNullGeometry(SUBTYPES.GEOM2D);
3876
                        } catch (CreateGeometryException e) {
3877
                                logger.error("While creating null geometry: " + e.getMessage());
3878
                        }
3879
                        return resp;
3880
            }
3881

    
3882
        Datum[] the_data = null;
3883
        try {
3884
            the_data = st.getOracleAttributes();
3885

    
3886
            int jgtype = ((NUMBER) the_data[0]).intValue() % 1000;
3887
            jgtype = oracleGTypeToFShapeType(jgtype, complex);
3888

    
3889
            int dim = ((NUMBER) the_data[0]).intValue() / 1000;
3890

    
3891
            if (dim < 2) {
3892
                dim = 2;
3893
            }
3894

    
3895
                int subty = getSubTypeFromDims(dim);
3896
                Primitive ig = null;
3897
                try {
3898
                                ig = gm.createNullGeometry(subty);
3899
                        } catch (CreateGeometryException e) {
3900
                                logger.error("While creating null geometry: " + e.getMessage());
3901
                        }
3902

    
3903
            if (isActuallyACollection(the_data)) {
3904
                jgtype = TYPES.AGGREGATE;
3905
            }
3906

    
3907
            try {
3908
                switch (jgtype) {
3909
                case TYPES.POINT:
3910
                    ig = (Primitive) getFMapGeometryPoint(the_data, dim);
3911
                    break;
3912

    
3913
                case TYPES.CURVE:
3914
                    ig = (Primitive) getFMapGeometryMultiLineString(the_data, dim);
3915
                    break;
3916

    
3917
                case TYPES.SURFACE:
3918
                    ig = (Primitive) getFMapGeometryMultipolygon(the_data, dim);
3919
                    break;
3920
                default:
3921
                        logger.error("Aggregate of non primitives not supported.");
3922
                    break;
3923
                }
3924
            } catch (Exception ex) {
3925
                    logger.error("While creating primitive: " + ex.getMessage());
3926
            }
3927

    
3928
            return ig;
3929
        } catch (SQLException e) {
3930
            logger.error("While getting primitive: " + e.getMessage());
3931
        }
3932

    
3933
        return null;
3934
    }
3935
    
3936
    
3937
    private static int getSubTypeFromDims(int dim) {
3938
            
3939
            switch (dim) {
3940
            case 3:
3941
                    return SUBTYPES.GEOM3D;
3942
            case 4:
3943
                    return SUBTYPES.GEOM3DM;
3944
            default:
3945
                            return SUBTYPES.GEOM2D;
3946
            }
3947
        }
3948

    
3949
        public static Geometry getFMapGeometryCollection(
3950
                    Datum[] the_data,
3951
                    int dim,
3952
                    boolean tableHasSrid,
3953
                    String table_srid,
3954
                    Connection _conn) {
3955

    
3956
            NUMBER _srid = new NUMBER(0);
3957
        NUMBER main_type = new NUMBER((dim * 1000) + getStructType(the_data));
3958

    
3959

    
3960
        Datum[] all_info_array = null;
3961
        Object[] elems_info_aray = null;
3962
        Datum[] all_ords = null;
3963

    
3964
        Object[] ords_of_groups = null;
3965
        Object[] _elems_info_aray = null;
3966
        try {
3967
            all_info_array = ((ARRAY) the_data[3]).getOracleArray();
3968
            elems_info_aray = groupByElement(all_info_array);
3969
            all_ords = ((ARRAY) the_data[4]).getOracleArray();
3970

    
3971
            ords_of_groups = getOrdOfGroups(all_ords, elems_info_aray);
3972
            _elems_info_aray = new Object[elems_info_aray.length];
3973
        }
3974
        catch (SQLException e) {
3975
            logger.error("Unexpected error: " + e.getMessage());
3976
        }
3977

    
3978

    
3979
        for (int i = 0; i < elems_info_aray.length; i++) {
3980
            _elems_info_aray[i] = updateIndexes((Datum[]) elems_info_aray[i]);
3981
        }
3982

    
3983
        // _elems_info_aray, ords_of_groups
3984
        int no_of_elems = ords_of_groups.length;
3985
        Primitive[] geoms = new Primitive[no_of_elems];
3986

    
3987
        for (int i = 0; i < no_of_elems; i++) {
3988
            Datum[] item_info_array = null;
3989
            Datum[] item_ords = null;
3990
            NUMBER gtype = null;
3991

    
3992
            try {
3993
                item_info_array = (Datum[]) _elems_info_aray[i];
3994
                item_ords = (Datum[]) ords_of_groups[i];
3995

    
3996
                gtype = new NUMBER((dim * 1000) +
3997
                        (item_info_array[1].intValue() % 1000));
3998

    
3999
                if (tableHasSrid) {
4000
                        _srid = new NUMBER(Integer.parseInt(table_srid));
4001
                }
4002
            }
4003
            catch (SQLException se) {
4004
                logger.error("Unexpected error: " + se.getMessage());
4005
            }
4006

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

    
4010
            STRUCT itemst = null;
4011

    
4012
            if (tableHasSrid) {
4013

    
4014
                itemst = createStruct(gtype, _srid,
4015
                        item_info_array, item_ords, _conn);
4016
            }
4017
            else {
4018
                itemst = createStruct(gtype, null,
4019
                        item_info_array, item_ords, _conn);
4020
            }
4021
            geoms[i] = getPrimitive(itemst, true);
4022
        }
4023
        
4024
            GeometryManager gm = GeometryLocator.getGeometryManager();
4025
            int subt = getSubTypeFromDims(dim);
4026
        MultiPrimitive resp = null;
4027
        
4028
        try {
4029
                        resp = (MultiPrimitive) gm.create(TYPES.AGGREGATE, subt);
4030
                for (int i = 0; i < no_of_elems; i++) {
4031
                        resp.addPrimitive(geoms[i]);
4032
                }
4033
                } catch (Exception e) {
4034
                        logger.error("While creating multi primitive: " + e.getMessage());
4035
                }
4036
        return resp;
4037
    }
4038
        
4039
        // ===========================================================
4040
        
4041
        /**
4042
         * Get oracle srid from srs code(EPSG code)
4043
         * 
4044
         * @param epsg
4045
         * @return oraSRID
4046
         */
4047
        public static String epsgToOracleSrid(String epsg) {
4048
                
4049
                DataManager manager = DALLocator.getDataManager();
4050
                int isrs = -1;
4051
                if (epsg != null) {
4052
                        FeatureStore oraSrsStore = (FeatureStore) OracleLibrary
4053
                                        .getSRSDataStore();
4054

    
4055
                        FeatureSet set = null;
4056
                        try {
4057
                                FeatureQuery query = oraSrsStore.createFeatureQuery();
4058
                                query.setFilter(manager.createExpresion("EPSG = " + epsg));
4059
                                set = (FeatureSet) oraSrsStore.getDataSet(query);
4060
                                if (set.getSize() > 0) {
4061
                                        Iterator<Feature> it = set.iterator();
4062
                                        while (it.hasNext()) {
4063
                                                Feature feat = it.next();
4064
                                                Double ora = feat.getDouble("ORACLE");
4065
                                                int iora = ora.intValue();
4066
                                                double prefe = feat.getDouble("PRF_ORACLE");
4067
                                                if (prefe == 1) {
4068
                                                        isrs = iora;
4069
                                                        break;
4070
                                                }
4071
                                        }
4072
                                }
4073
                        } catch (DataException e) {
4074
                                e.printStackTrace();
4075
                        }
4076
                        if (isrs >= 0) {
4077
                                return Integer.toString(isrs);
4078
                        }
4079
                }
4080
                return null;
4081
        }
4082

    
4083
        /**
4084
         * Get EPSG SRS from Oracle SRS
4085
         * 
4086
         * @param oraSRID
4087
         * @return
4088
         */
4089
        public static Integer oracleSridToEpsg(String oraSRID) {
4090

    
4091
                DataManager manager = DALLocator.getDataManager();
4092
                Integer isrs = null;
4093
                
4094
                if (oraSRID != null) {
4095
                        FeatureStore oraSrsStore = (FeatureStore) OracleLibrary
4096
                                        .getSRSDataStore();
4097

    
4098
                        FeatureSet set = null;
4099
                        try {
4100
                                FeatureQuery query = oraSrsStore.createFeatureQuery();
4101
                                query.setFilter(manager.createExpresion("ORACLE = " + oraSRID));
4102
                                set = (FeatureSet) oraSrsStore.getDataSet(query);
4103
                                if (set.getSize() > 0) {
4104
                                        Iterator<Feature> it = set.iterator();
4105
                                        while (it.hasNext()) {
4106
                                                Feature feat = it.next();
4107
                                                isrs = new Integer(Math.round((float) feat.getDouble("EPSG")));
4108
                                        }
4109
                                } else {
4110
                                        logger.warn("Did not find Oracle SRID code: " + oraSRID + ". We'll assume it's an EPSG code.");
4111
                                        isrs = new Integer(Integer.parseInt(oraSRID));
4112
                                }
4113
                        } catch (Exception e) {
4114
                                logger.error("While getting EPSG from oracle srid: " + e.getMessage());
4115
                        }
4116
                        return isrs;
4117
                } else {
4118
                        return null;
4119
                }
4120
        }
4121

    
4122
        /**
4123
         * Get Oracle SRS from gvSIG projection
4124
         * 
4125
         * @param proj
4126
         * @return  
4127
         */
4128
        public static String projectionToOracleSrid(IProjection proj) {
4129
                if (proj != null) {
4130
                        String epsg = proj.getAbrev().trim();
4131
                        int ocu = epsg.indexOf(":");
4132
                        if (ocu != -1) {
4133
                                epsg = epsg.substring(ocu + 1);
4134
                        }
4135
                        return epsgToOracleSrid(epsg);
4136
                } else {
4137
                        return null;
4138
                }
4139
        }
4140

    
4141
        public static int dimensionsFromSubtype(int subtype) {
4142
                
4143
                switch (subtype) {
4144
                
4145
                case SUBTYPES.GEOM2D:
4146
                        return 2;
4147
                case SUBTYPES.GEOM3D:
4148
                case SUBTYPES.GEOM2DM:
4149
                        return 3;
4150
                case SUBTYPES.GEOM3DM:
4151
                        return 4;
4152
                default:
4153
                                logger.error("Unknown subtype: " + subtype + ". Returned 2 as number of dimensions.");
4154
                        return 2;
4155
                }
4156
        }
4157

    
4158
        public static Rectangle2D envelopeToRectangle2D(org.gvsig.fmap.geom.primitive.Envelope envelope) {
4159
                        
4160
                double x = envelope.getMinimum(0);
4161
                double y = envelope.getMinimum(1);
4162
                double w = envelope.getLength(0);
4163
                double h = envelope.getLength(1);
4164
                Rectangle2D resp = new Rectangle2D.Double(x,y,w,h);
4165
                return resp;
4166
        }
4167

    
4168
        public static Geometry createNullGeometry(int stype) {
4169
                
4170
        Geometry ig = null;
4171
        GeometryType nullgt = null;;
4172
                try {
4173
                        GeometryManager gm = GeometryLocator.getGeometryManager();
4174
                        nullgt = ((DefaultGeometryManager) gm).getGeometryType(DefaultNullGeometry.class.getName());
4175
                ig = new DefaultNullGeometry(nullgt);
4176
                } catch (GeometryTypeNotSupportedException e) {
4177
                        logger.error("While creating null geom: " + e.getMessage());
4178
                        return null;
4179
                }
4180
        return ig;
4181

    
4182
        }
4183
        
4184
        
4185
        
4186
    public static String getIntersectsEnvelopeSelect(
4187
                    String geo_col_name,
4188
                    Envelope enve,
4189
                    String ora_srid,
4190
                    boolean is_geo) {
4191
            
4192
        String resp = "";
4193
        String view_sdo = getSdoConstructor(enve, ora_srid, is_geo);
4194

    
4195
        if (is_geo) {
4196
            resp = "(sdo_filter(" + geo_col_name +
4197
                ", SDO_CS.VIEWPORT_TRANSFORM(" + view_sdo + ", " + ora_srid +
4198
                "), 'querytype=window') = 'TRUE')";
4199
        } else {
4200
                resp = "(" + "sdo_relate(" + geo_col_name + ", " + view_sdo +
4201
                ", 'mask=anyinteract querytype=window') = 'TRUE')";
4202
        }
4203
        return resp;
4204
    }
4205
    
4206
    
4207
    public static String getIntersectsGeometrySelect(
4208
                    String geo_col_name,
4209
                    Geometry geome,
4210
                    String ora_srid,
4211
                    boolean is_geo,
4212
                    Connection conn) {
4213
            
4214
        String resp = "";
4215
        String view_sdo = getSdoConstructor(geome, ora_srid, is_geo, conn);
4216

    
4217
        if (is_geo) {
4218
            resp = "(sdo_filter(" + geo_col_name +
4219
                ", SDO_CS.VIEWPORT_TRANSFORM(" + view_sdo + ", " + ora_srid +
4220
                "), 'querytype=window') = 'TRUE')";
4221
        } else {
4222
                resp = "(" + "sdo_relate(" + geo_col_name + ", " + view_sdo +
4223
                ", 'mask=anyinteract querytype=window') = 'TRUE')";
4224
        }
4225
        return resp;
4226
    }
4227

    
4228
    
4229

    
4230
    public static String getSdoConstructor(Envelope enve, String ora_srid, boolean is_geo) {
4231
        String resp = "";
4232

    
4233
        try {
4234
            String mdsys_sdo_elem_info_array = "mdsys.sdo_elem_info_array(1, 1003, 3)";
4235
            String mdsys_sdo_ordinate_array = "";
4236

    
4237
            mdsys_sdo_ordinate_array = mdsys_sdo_ordinate_array + enve.getMinimum(0) + ", ";
4238
            mdsys_sdo_ordinate_array = mdsys_sdo_ordinate_array + enve.getMinimum(1) + ", ";
4239
            mdsys_sdo_ordinate_array = mdsys_sdo_ordinate_array + enve.getMaximum(0) + ", ";
4240
            mdsys_sdo_ordinate_array = mdsys_sdo_ordinate_array + enve.getMaximum(1);
4241

    
4242
            mdsys_sdo_ordinate_array = "mdsys.sdo_ordinate_array(" +
4243
                mdsys_sdo_ordinate_array + ")";
4244

    
4245
            String aux = "";
4246

    
4247
            if (ora_srid != null) {
4248
                aux = ora_srid;
4249

    
4250
                if (is_geo) {
4251
                    aux = "0";
4252
                }
4253
            }
4254
            else {
4255
                aux = "null";
4256
            }
4257

    
4258
            resp = "mdsys.sdo_geometry(2003, " + aux + ", null, " +
4259
                mdsys_sdo_elem_info_array + ", " + mdsys_sdo_ordinate_array +
4260
                ")";
4261
        }
4262
        catch (Exception ex) {
4263
                logger.error("While getting sdo contructor: " +
4264
                ex.getMessage());
4265
        }
4266

    
4267
        return resp;
4268
    }
4269
    
4270
    
4271
    public static String getSdoConstructor(
4272
                    Geometry geome, String ora_srid,
4273
                    boolean is_geo, Connection conn) {
4274
            
4275
            int ora_srid_int = 0;
4276
            STRUCT st = null;
4277
            ARRAY ora_arr = null;
4278

    
4279
            try {
4280
                    ora_srid_int = Integer.parseInt(ora_srid);
4281
                } catch (Exception e) { }
4282
            
4283
            try {
4284
                        st = geometryToSTRUCT(geome, conn, ora_srid_int, false, ora_srid != null);
4285
                        return structToString(st);
4286
                } catch (Exception e) {
4287
                        logger.error("While getting SDO geometry as String: " + e.getMessage());
4288
                        return null;
4289
                }
4290
            
4291
    }
4292

    
4293
        public static String structToString(STRUCT st) throws Exception {
4294
                
4295
                StringBuffer resp = new StringBuffer();
4296
                
4297
                resp.append("MDSYS.SDO_GEOMETRY(");
4298
                NUMBER ora_num = null;
4299
                STRUCT ora_struct = null;
4300
                ARRAY ora_arr = null;
4301
                
4302
                Datum[] dd = st.getOracleAttributes();
4303
                if (dd[0] instanceof NUMBER) {
4304
                        ora_num = (NUMBER) dd[0]; 
4305
                        resp.append(Integer.toString(ora_num.intValue()));
4306
                        resp.append(", ");
4307
                } else {
4308
                        throw new Exception("First component of SDO_GEOMETRY not a number; " + dd[0].getClass().getName());
4309
                }
4310
                
4311
                if (dd[1] instanceof NUMBER) {
4312
                        ora_num = (NUMBER) dd[1]; 
4313
                        resp.append(Integer.toString(ora_num.intValue()));
4314
                        resp.append(", ");
4315
                } else {
4316
                        resp.append("NULL, ");
4317
                }
4318
                
4319
                if (dd[2] instanceof STRUCT) {
4320
                        // special: point
4321
                        ora_struct = (STRUCT) dd[2];
4322
                        Datum[] aux = ora_struct.getOracleAttributes();
4323
                        double x = ((NUMBER) aux[0]).doubleValue();
4324
                        double y = ((NUMBER) aux[1]).doubleValue();
4325
                        resp.append(", SDO_POINT_TYPE(");
4326
                        resp.append(Double.toString(x));
4327
                        resp.append(", ");
4328
                        resp.append(Double.toString(y));
4329
                        resp.append(", NULL), NULL, NULL)");
4330
                        return resp.toString();
4331
                } else {
4332
                        resp.append("NULL, ");
4333
                }
4334
                
4335
                if (dd[3] instanceof ARRAY) {
4336
                        ora_arr = (ARRAY) dd[3];
4337
                        int[] aux = ora_arr.getIntArray();
4338
                        resp.append("MDSYS.SDO_ELEM_INFO_ARRAY(");
4339
                        resp.append(Integer.toString(aux[0]));
4340
                        for (int i=1; i<aux.length; i++) {
4341
                                resp.append(", ");
4342
                                resp.append(Integer.toString(aux[i]));
4343
                        }
4344
                        resp.append("), ");
4345

    
4346
                } else {
4347
                        throw new Exception("Component [3] is not an ARRAY: " + dd[3].getClass().getName());
4348
                }
4349
                
4350
                if (dd[4] instanceof ARRAY) {
4351
                        ora_arr = (ARRAY) dd[4];
4352
                        double[] aux = ora_arr.getDoubleArray();
4353
                        resp.append("MDSYS.SDO_ORDINATE_ARRAY(");
4354
                        resp.append(Double.toString(aux[0]));
4355
                        for (int i=1; i<aux.length; i++) {
4356
                                resp.append(", ");
4357
                                resp.append(Double.toString(aux[i]));
4358
                        }
4359
                        resp.append(")");
4360
                } else {
4361
                        throw new Exception("Component [4] is not an ARRAY: " + dd[4].getClass().getName());
4362
                }
4363

    
4364
                resp.append(")");;
4365
                return resp.toString();
4366
                
4367
        }
4368
        
4369
        
4370
        public static Object getId(FeatureReferenceProviderServices ref, FeatureType ft) {
4371
                
4372
                if (ft.hasOID()) {
4373
                        return ref.getOID();
4374
                } else {
4375
                        
4376
                        if (ref.getKeyNames() == null) {
4377
                                return ref.getOID();
4378
                        } else {
4379
                                FeatureAttributeDescriptor[] fadd = ft.getPrimaryKey();
4380
                                Object resp = ref.getKeyValue(fadd[0].getName());
4381
                                if (resp == null) {
4382
                                        logger.warn("Did not find PK in feat ref: " + fadd[0].getName());
4383
                                }
4384
                                return resp;
4385
                        }
4386
                }
4387

    
4388
        }
4389

    
4390
}