Source Code Cross Referenced for OraReader.java in  » GIS » jts » com » vividsolutions » jts » io » oracle » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » GIS » jts » com.vividsolutions.jts.io.oracle 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * The JTS Topology Suite is a collection of Java classes that
003:         * implement the fundamental operations required to validate a given
004:         * geo-spatial data set to a known topological specification.
005:         *
006:         * Copyright (C) 2001 Vivid Solutions
007:         *
008:         * This library is free software; you can redistribute it and/or
009:         * modify it under the terms of the GNU Lesser General Public
010:         * License as published by the Free Software Foundation; either
011:         * version 2.1 of the License, or (at your option) any later version.
012:         *
013:         * This library is distributed in the hope that it will be useful,
014:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
015:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
016:         * Lesser General Public License for more details.
017:         *
018:         * You should have received a copy of the GNU Lesser General Public
019:         * License along with this library; if not, write to the Free Software
020:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
021:         *
022:         * For more information, contact:
023:         *
024:         *     Vivid Solutions
025:         *     Suite #1A
026:         *     2328 Government Street
027:         *     Victoria BC  V8T 5G5
028:         *     Canada
029:         *
030:         *     (250)385-6040
031:         *     www.vividsolutions.com
032:         */
033:        /*
034:         *    Geotools2 - OpenSource mapping toolkit
035:         *    http://geotools.org
036:         *    (C) 2003, Geotools Project Managment Committee (PMC)
037:         *
038:         *    This library is free software; you can redistribute it and/or
039:         *    modify it under the terms of the GNU Lesser General Public
040:         *    License as published by the Free Software Foundation;
041:         *    version 2.1 of the License.
042:         *
043:         *    This library is distributed in the hope that it will be useful,
044:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
045:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
046:         *    Lesser General Public License for more details.
047:         *
048:         */
049:        package com.vividsolutions.jts.io.oracle;
050:
051:        import java.sql.SQLException;
052:        import java.util.*;
053:
054:        import oracle.sql.*;
055:
056:        import com.vividsolutions.jts.algorithm.CGAlgorithms;
057:        import com.vividsolutions.jts.geom.*;
058:
059:        /**
060:         * Creates a {@link Geometry} from an Oracle MDSYS.GEOMETRY object.
061:         *
062:         * A {@link GeometryFactory} may be provided, otherwise
063:         * a default one will be used.
064:         * The provided GeometryFactory will be used, with the exception of the SRID field.
065:         * This will be extracted from the Geometry.
066:         * <p>
067:         * If a PrecisionModel is supplied it is the callers's responsibility
068:         * to ensure that it matches the precision of the incoming data.
069:         * If a lower precision for the data is required, a subsequent
070:         * process must be run on the data to reduce its precision.
071:         *
072:         * @version 9i
073:         * @author David Zwiers, Vivid Solutions.
074:         */
075:        public class OraReader {
076:            private GeometryFactory geometryFactory;
077:
078:            public static final int NULL_DIMENSION = -1;
079:            private int dimension = -1;
080:
081:            /**
082:             * Creates a new reader, with a default GeometryFactory.
083:             *
084:             * @see #OraReader(GeometryFactory)
085:             */
086:            public OraReader() {
087:                this (new GeometryFactory());
088:            }
089:
090:            /**
091:             * Creates a new reader, with the supplied {@link GeometryFactory}.
092:             * It is assumed that the supplied {@link PrecisionModel}
093:             * matches the precision of the incoming data -
094:             * coordinates are <b>not</b> made precise.
095:             *
096:             * @param gf
097:             *            A non-null geometry factory for later use.
098:             * @throw NullPointerException when the geometry factory is null.
099:             */
100:            public OraReader(GeometryFactory gf) {
101:                if (gf == null)
102:                    throw new NullPointerException(
103:                            "Geometry Factory may not be Null");
104:                this .geometryFactory = gf;
105:            }
106:
107:            /**
108:             * This method will attempt to create a JTS Geometry for the MDSYS.GEOMETRY
109:             * provided. The Type of gemetry returned will depend on the input datum,
110:             * where the Geometry type is specified within the STRUCT.
111:             *
112:             * @param struct The MDSYS.GEOMETRY Object to decode
113:             * @return A JTS Geometry if one could be created, null otherwise
114:             * @throws SQLException When a read error occured within the struct
115:             */
116:            public Geometry read(STRUCT struct) throws SQLException {
117:
118:                // Note Returning null for null Datum
119:                if (struct == null)
120:                    return null;
121:
122:                Datum data[] = struct.getOracleAttributes();
123:                int gType = asInteger(data[0], 0);
124:                int SRID = asInteger(data[1], Constants.SRID_NULL);
125:                double point[] = asDoubleArray((STRUCT) data[2], Double.NaN);
126:                int elemInfo[] = asIntArray((ARRAY) data[3], 0);
127:                double ordinates[] = asDoubleArray((ARRAY) data[4], Double.NaN);
128:                GeometryFactory gf = geometryFactory;
129:                if (geometryFactory.getSRID() != SRID) {
130:                    // clone it and use the geom's srid
131:                    gf = new GeometryFactory(geometryFactory
132:                            .getPrecisionModel(), SRID, geometryFactory
133:                            .getCoordinateSequenceFactory());
134:                }
135:
136:                return create(gf, gType, point, elemInfo, ordinates);
137:            }
138:
139:            /**
140:             * Decode geometry from provided SDO encoded information.
141:             *
142:             * <p></p>
143:             *
144:             * @param gf Used to construct returned Geometry
145:             * @param gType SDO_GTEMPLATE represents dimension, LRS, and geometry type
146:             * @param point
147:             * @param elemInfo
148:             * @param ordinates
149:             *
150:             * @return Geometry as encoded
151:             */
152:            private Geometry create(GeometryFactory gf, int gType,
153:                    double[] point, int[] elemInfo, double[] ordinates) {
154:
155:                int lrs = (gType % 1000) / 100;
156:
157:                // find the dimension: represented by the smaller of the two dimensions
158:                int dim = 0;
159:                if (dimension != NULL_DIMENSION) {
160:                    dim = dimension;
161:                } else {
162:                    dim = Math.min(gType / 1000, gf
163:                            .getCoordinateSequenceFactory().create(0, 0)
164:                            .getDimension());
165:                }
166:
167:                if (dim < 2) {
168:                    throw new IllegalArgumentException(
169:                            "Dimension D:"
170:                                    + dim
171:                                    + " is not valid for JTS. "
172:                                    + "Either specify a dimension or use Oracle Locator Version 9i or later");
173:                }
174:
175:                // extract the geometry template type
176:                // this is represented as the rightmost two digits
177:                int geomTemplate = gType - (dim * 1000) - (lrs * 100);
178:
179:                CoordinateSequence coords = null;
180:
181:                if (lrs == 0 && geomTemplate == 1 && point != null
182:                        && elemInfo == null) {
183:                    // Single Point Type Optimization
184:                    coords = coordinates(gf.getCoordinateSequenceFactory(),
185:                            dim, lrs, geomTemplate, point);
186:                    elemInfo = new int[] { 1, Constants.SDO_ETYPE.POINT, 1 };
187:                } else {
188:                    coords = coordinates(gf.getCoordinateSequenceFactory(),
189:                            dim, lrs, geomTemplate, ordinates);
190:                }
191:
192:                switch (geomTemplate) {
193:                case Constants.SDO_GTEMPLATE.POINT:
194:                    return createPoint(gf, dim, lrs, elemInfo, 0, coords);
195:
196:                case Constants.SDO_GTEMPLATE.LINE:
197:                    return createLine(gf, dim, lrs, elemInfo, 0, coords);
198:
199:                case Constants.SDO_GTEMPLATE.POLYGON:
200:                    return createPolygon(gf, dim, lrs, elemInfo, 0, coords);
201:
202:                case Constants.SDO_GTEMPLATE.MULTIPOINT:
203:                    return createMultiPoint(gf, dim, lrs, elemInfo, 0, coords);
204:
205:                case Constants.SDO_GTEMPLATE.MULTILINE:
206:                    return createMultiLine(gf, dim, lrs, elemInfo, 0, coords,
207:                            -1);
208:
209:                case Constants.SDO_GTEMPLATE.MULTIPOLYGON:
210:                    return createMultiPolygon(gf, dim, lrs, elemInfo, 0,
211:                            coords, -1);
212:
213:                case Constants.SDO_GTEMPLATE.COLLECTION:
214:                    return createCollection(gf, dim, lrs, elemInfo, 0, coords,
215:                            -1);
216:
217:                default:
218:                    return null;
219:                }
220:            }
221:
222:            /**
223:             * Construct CoordinateList as described by GTYPE.
224:             *
225:             * The number of ordinates per coordinate are taken to be lrs+dim, and the
226:             * number of ordinates should be a multiple of this value.
227:
228:             * In the Special case of GTYPE 2001 and a three ordinates are interpreted
229:             * as a single Coordinate rather than an error.
230:             *
231:             * @param f CoordinateSequenceFactory used to encode ordiantes for JTS
232:             * @param ordinates
233:             *
234:             * @return protected
235:             *
236:             * @throws IllegalArgumentException
237:             */
238:            private CoordinateSequence coordinates(CoordinateSequenceFactory f,
239:                    int dim, int lrs, int gtemplate, double[] ordinates) {
240:                if ((ordinates == null) || (ordinates.length == 0)) {
241:                    return f.create(new Coordinate[0]);
242:                }
243:
244:                //      POINT_TYPE Special Case
245:                //
246:                if ((dim == 2) && (lrs == 0) && (gtemplate == 01)
247:                        && (ordinates.length == 3)) {
248:                    return f.create(new Coordinate[] { new Coordinate(
249:                            ordinates[0], ordinates[1], ordinates[2]), });
250:                }
251:
252:                int len = dim + lrs;
253:
254:                if ((len == 0 && ordinates.length != 0)
255:                        || (len != 0 && ((ordinates.length % len) != 0))) {
256:                    throw new IllegalArgumentException("Dimension D:" + dim
257:                            + " and L:" + lrs + " denote Coordinates " + "of "
258:                            + len + " ordinates. This cannot be resolved with"
259:                            + "an ordinate array of length " + ordinates.length);
260:                }
261:
262:                int length = (len == 0 ? 0 : ordinates.length / len);
263:
264:                // we would have to ask for a dimension which represents all the requested
265:                // dimension and measures from a mask array in the future
266:                CoordinateSequence cs = f.create(length, dim);
267:
268:                int actualDim = cs.getDimension();
269:                for (int i = 0; i < length; i++) {
270:                    int j = 0;
271:                    // in the future change this condition to include ignored dimensions from mask array
272:                    for (; j < actualDim && j < dim; j++) {
273:                        cs.setOrdinate(i, j, ordinates[i * len + j]);
274:                        // may not always want to inc. j when we have a mask array
275:                    }
276:                    // in the future change this condition to include ignored dimensions from mask array
277:                    for (int d = j; j < actualDim && (j - d) < lrs; j++) {
278:                        cs.setOrdinate(i, j, ordinates[i * len + j]);
279:                        // may not always want to inc. j when we have a mask array
280:                    }
281:                }
282:                return cs;
283:            }
284:
285:            /**
286:             * Create MultiGeometry as encoded by elemInfo.
287:             *
288:             * @param gf Used to construct MultiLineString
289:             * @param elemInfo Interpretation of coords
290:             * @param elemIndex Triplet in elemInfo to process as a Polygon
291:             * @param coords Coordinates to interpret using elemInfo
292:             * @param numGeom Number of triplets (or -1 for rest)
293:             *
294:             * @return GeometryCollection
295:             *
296:             * @throws IllegalArgumentException DWhen faced with an encoding error
297:             */
298:            private GeometryCollection createCollection(GeometryFactory gf,
299:                    int dim, int lrs, int[] elemInfo, int elemIndex,
300:                    CoordinateSequence coords, int numGeom) {
301:
302:                int sOffset = StartingOffset(elemInfo, elemIndex);
303:
304:                int length = coords.size() * dim;
305:
306:                if (!(sOffset <= length))
307:                    throw new IllegalArgumentException(
308:                            "ELEM_INFO STARTING_OFFSET " + sOffset
309:                                    + " inconsistent with ORDINATES length "
310:                                    + coords.size());
311:
312:                int endTriplet = (numGeom != -1) ? elemIndex + numGeom
313:                        : elemInfo.length / 3 + 1;
314:
315:                List list = new LinkedList();
316:                int etype;
317:                int interpretation;
318:                Geometry geom;
319:
320:                boolean cont = true;
321:                for (int i = elemIndex; cont && i < endTriplet; i++) {
322:                    etype = eType(elemInfo, i);
323:                    interpretation = interpretation(elemInfo, i);
324:
325:                    switch (etype) {
326:                    case -1:
327:                        cont = false; // We are the of the list - get out of here
328:
329:                    case Constants.SDO_ETYPE.POINT:
330:
331:                        if (interpretation == 1) {
332:                            geom = createPoint(gf, dim, lrs, elemInfo, i,
333:                                    coords);
334:                        } else if (interpretation > 1) {
335:                            geom = createMultiPoint(gf, dim, lrs, elemInfo, i,
336:                                    coords);
337:                        } else {
338:                            throw new IllegalArgumentException(
339:                                    "ETYPE.POINT requires INTERPRETATION >= 1");
340:                        }
341:
342:                        break;
343:
344:                    case Constants.SDO_ETYPE.LINE:
345:                        geom = createLine(gf, dim, lrs, elemInfo, i, coords);
346:
347:                        break;
348:
349:                    case Constants.SDO_ETYPE.POLYGON:
350:                    case Constants.SDO_ETYPE.POLYGON_EXTERIOR:
351:                        geom = createPolygon(gf, dim, lrs, elemInfo, i, coords);
352:                        i += ((Polygon) geom).getNumInteriorRing();
353:
354:                        break;
355:
356:                    case Constants.SDO_ETYPE.POLYGON_INTERIOR:
357:                        throw new IllegalArgumentException(
358:                                "ETYPE 2003 (Polygon Interior) no expected in a GeometryCollection"
359:                                        + "(2003 is used to represent polygon holes, in a 1003 polygon exterior)");
360:
361:                    default:
362:                        throw new IllegalArgumentException(
363:                                "ETYPE "
364:                                        + etype
365:                                        + " not representable as a JTS Geometry."
366:                                        + "(Custom and Compound Straight and Curved Geometries not supported)");
367:                    }
368:
369:                    list.add(geom);
370:                }
371:
372:                GeometryCollection geoms = gf
373:                        .createGeometryCollection((Geometry[]) list
374:                                .toArray(new Geometry[list.size()]));
375:
376:                return geoms;
377:            }
378:
379:            /**
380:             * Create MultiPolygon as encoded by elemInfo.
381:             *
382:             *
383:             * @param gf Used to construct MultiLineString
384:             * @param elemInfo Interpretation of coords
385:             * @param elemIndex Triplet in elemInfo to process as a Polygon
386:             * @param coords Coordinates to interpret using elemInfo
387:             * @param numGeom Number of triplets (or -1 for rest)
388:             *
389:             * @return MultiPolygon
390:             */
391:            private MultiPolygon createMultiPolygon(GeometryFactory gf,
392:                    int dim, int lrs, int[] elemInfo, int elemIndex,
393:                    CoordinateSequence coords, int numGeom) {
394:
395:                int sOffset = StartingOffset(elemInfo, elemIndex);
396:                int etype = eType(elemInfo, elemIndex);
397:                int interpretation = interpretation(elemInfo, elemIndex);
398:
399:                int length = coords.size() * dim;
400:
401:                if (!(sOffset >= 1) || !(sOffset <= length))
402:                    throw new IllegalArgumentException(
403:                            "ELEM_INFO STARTING_OFFSET " + sOffset
404:                                    + " inconsistent with ORDINATES length "
405:                                    + coords.size());
406:                if (!(etype == Constants.SDO_ETYPE.POLYGON)
407:                        && !(etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR))
408:                    throw new IllegalArgumentException(
409:                            "ETYPE "
410:                                    + etype
411:                                    + " inconsistent with expected POLYGON or POLYGON_EXTERIOR");
412:                if (interpretation != 1 && interpretation != 3) {
413:                    return null;
414:                }
415:
416:                int endTriplet = (numGeom != -1) ? elemIndex + numGeom
417:                        : (elemInfo.length / 3) + 1;
418:
419:                List list = new LinkedList();
420:                boolean cont = true;
421:
422:                for (int i = elemIndex; cont && i < endTriplet
423:                        && (etype = eType(elemInfo, i)) != -1; i++) {
424:                    if ((etype == Constants.SDO_ETYPE.POLYGON)
425:                            || (etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR)) {
426:                        Polygon poly = createPolygon(gf, dim, lrs, elemInfo, i,
427:                                coords);
428:                        i += poly.getNumInteriorRing(); // skip interior rings
429:                        list.add(poly);
430:                    } else { // not a Polygon - get out here
431:                        cont = false;
432:                    }
433:                }
434:
435:                MultiPolygon polys = gf.createMultiPolygon((Polygon[]) list
436:                        .toArray(new Polygon[list.size()]));
437:
438:                return polys;
439:            }
440:
441:            /**
442:             * Create MultiLineString as encoded by elemInfo.
443:             *
444:             *
445:             * @param gf Used to construct MultiLineString
446:             * @param elemInfo Interpretation of coords
447:             * @param elemIndex Triplet in elemInfo to process as a Polygon
448:             * @param coords Coordinates to interpret using elemInfo
449:             * @param numGeom Number of triplets (or -1 for rest)
450:             *
451:             * @return MultiLineString
452:             */
453:            private MultiLineString createMultiLine(GeometryFactory gf,
454:                    int dim, int lrs, int[] elemInfo, int elemIndex,
455:                    CoordinateSequence coords, int numGeom) {
456:
457:                int sOffset = StartingOffset(elemInfo, elemIndex);
458:                int etype = eType(elemInfo, elemIndex);
459:                int interpretation = interpretation(elemInfo, elemIndex);
460:
461:                int length = coords.size() * dim;
462:
463:                if (!(sOffset >= 1) || !(sOffset <= length))
464:                    throw new IllegalArgumentException(
465:                            "ELEM_INFO STARTING_OFFSET " + sOffset
466:                                    + " inconsistent with ORDINATES length "
467:                                    + coords.size());
468:                if (!(etype == Constants.SDO_ETYPE.LINE))
469:                    throw new IllegalArgumentException("ETYPE " + etype
470:                            + " inconsistent with expected LINE");
471:                if (!(interpretation == 1)) {
472:                    // we cannot represent INTERPRETATION > 1
473:                    return null;
474:                }
475:
476:                int endTriplet = (numGeom != -1) ? (elemIndex + numGeom)
477:                        : (elemInfo.length / 3);
478:
479:                List list = new LinkedList();
480:
481:                boolean cont = true;
482:                for (int i = elemIndex; cont && i < endTriplet
483:                        && (etype = eType(elemInfo, i)) != -1; i++) {
484:                    if (etype == Constants.SDO_ETYPE.LINE) {
485:                        list.add(createLine(gf, dim, lrs, elemInfo, i, coords));
486:                    } else { // not a LineString - get out of here
487:                        cont = false;
488:                    }
489:                }
490:
491:                MultiLineString lines = gf
492:                        .createMultiLineString((LineString[]) list
493:                                .toArray(new LineString[list.size()]));
494:
495:                return lines;
496:            }
497:
498:            /**
499:             * Create MultiPoint as encoded by elemInfo.
500:             *
501:             *
502:             * @param gf Used to construct polygon
503:             * @param elemInfo Interpretation of coords
504:             * @param elemIndex Triplet in elemInfo to process as a Polygon
505:             * @param coords Coordinates to interpret using elemInfo
506:             *
507:             * @return MultiPoint
508:             */
509:            private MultiPoint createMultiPoint(GeometryFactory gf, int dim,
510:                    int lrs, int[] elemInfo, int elemIndex,
511:                    CoordinateSequence coords) {
512:
513:                int sOffset = StartingOffset(elemInfo, elemIndex);
514:                int etype = eType(elemInfo, elemIndex);
515:                int interpretation = interpretation(elemInfo, elemIndex);
516:
517:                if (!(sOffset >= 1) || !(sOffset <= coords.size()))
518:                    throw new IllegalArgumentException(
519:                            "ELEM_INFO STARTING_OFFSET " + sOffset
520:                                    + " inconsistent with ORDINATES length "
521:                                    + coords.size());
522:                if (!(etype == Constants.SDO_ETYPE.POINT))
523:                    throw new IllegalArgumentException("ETYPE " + etype
524:                            + " inconsistent with expected POINT");
525:                if (!(interpretation > 1)) {
526:                    return null;
527:                }
528:
529:                int len = dim + lrs;
530:
531:                int start = (sOffset - 1) / len;
532:                int end = start + interpretation;
533:
534:                MultiPoint points = gf.createMultiPoint(subList(gf
535:                        .getCoordinateSequenceFactory(), coords, start, end));
536:
537:                return points;
538:            }
539:
540:            /**
541:             * Create Polygon as encoded.
542:             *
543:             * @see #interpretation(int[], int)
544:             *
545:             * @param gf Used to construct polygon
546:             * @param elemInfo Interpretation of coords
547:             * @param elemIndex Triplet in elemInfo to process as a Polygon
548:             * @param coords Coordinates to interpret using elemInfo
549:             *
550:             * @return Polygon as encoded by elemInfo, or null when faced with and
551:             *         encoding that can not be captured by JTS
552:             * @throws IllegalArgumentException When faced with an invalid SDO encoding
553:             */
554:            private Polygon createPolygon(GeometryFactory gf, int dim, int lrs,
555:                    int[] elemInfo, int elemIndex, CoordinateSequence coords) {
556:
557:                int sOffset = StartingOffset(elemInfo, elemIndex);
558:                int etype = eType(elemInfo, elemIndex);
559:                int interpretation = interpretation(elemInfo, elemIndex);
560:
561:                if (!(1 <= sOffset && sOffset <= (coords.size() * dim))) {
562:                    throw new IllegalArgumentException(
563:                            "ELEM_INFO STARTING_OFFSET " + sOffset
564:                                    + "inconsistent with COORDINATES length "
565:                                    + (coords.size() * dim));
566:                }
567:
568:                if (!(etype == Constants.SDO_ETYPE.POLYGON)
569:                        && !(etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR)) {
570:                    throw new IllegalArgumentException(
571:                            "ETYPE "
572:                                    + etype
573:                                    + " inconsistent with expected POLYGON or POLYGON_EXTERIOR");
574:                }
575:                if (!(interpretation == 1) && !(interpretation == 3)) {
576:                    return null;
577:                }
578:
579:                LinearRing exteriorRing = createLinearRing(gf, dim, lrs,
580:                        elemInfo, elemIndex, coords);
581:
582:                List rings = new LinkedList();
583:
584:                boolean cont = true;
585:                for (int i = elemIndex + 1; cont
586:                        && (etype = eType(elemInfo, i)) != -1; i++) {
587:                    if (etype == Constants.SDO_ETYPE.POLYGON_INTERIOR) {
588:                        rings.add(createLinearRing(gf, dim, lrs, elemInfo, i,
589:                                coords));
590:                    } else if (etype == Constants.SDO_ETYPE.POLYGON) { // need to test Clockwiseness of Ring to see if it is
591:                        // interior or not - (use POLYGON_INTERIOR to avoid pain)
592:
593:                        LinearRing ring = createLinearRing(gf, dim, lrs,
594:                                elemInfo, i, coords);
595:
596:                        if (CGAlgorithms.isCCW(ring.getCoordinates())) { // it is an Interior Hole
597:                            rings.add(ring);
598:                        } else { // it is the next Polygon! - get out of here
599:                            cont = false;
600:                        }
601:                    } else { // not a LinearRing - get out of here
602:                        cont = false;
603:                    }
604:                }
605:
606:                Polygon poly = gf.createPolygon(exteriorRing,
607:                        (LinearRing[]) rings.toArray(new LinearRing[rings
608:                                .size()]));
609:
610:                return poly;
611:            }
612:
613:            /**
614:             * Create Linear Ring for exterior/interior polygon ELEM_INFO triplets.
615:             *
616:             * @param gf
617:             * @param elemInfo
618:             * @param elemIndex
619:             * @param coords
620:             *
621:             * @return LinearRing
622:             *
623:             * @throws IllegalArgumentException If circle, or curve is requested
624:             */
625:            private LinearRing createLinearRing(GeometryFactory gf, int dim,
626:                    int lrs, int[] elemInfo, int elemIndex,
627:                    CoordinateSequence coords) {
628:
629:                int sOffset = StartingOffset(elemInfo, elemIndex);
630:                int etype = eType(elemInfo, elemIndex);
631:                int interpretation = interpretation(elemInfo, elemIndex);
632:                int length = coords.size() * dim;
633:
634:                if (!(sOffset <= length))
635:                    throw new IllegalArgumentException(
636:                            "ELEM_INFO STARTING_OFFSET " + sOffset
637:                                    + " inconsistent with ORDINATES length "
638:                                    + coords.size());
639:                if (!(etype == Constants.SDO_ETYPE.POLYGON)
640:                        && !(etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR)
641:                        && !(etype == Constants.SDO_ETYPE.POLYGON_INTERIOR)) {
642:                    throw new IllegalArgumentException(
643:                            "ETYPE "
644:                                    + etype
645:                                    + " inconsistent with expected POLYGON, POLYGON_EXTERIOR or POLYGON_INTERIOR");
646:                }
647:                if (!(interpretation == 1) && !(interpretation == 3)) {
648:                    return null;
649:                }
650:                LinearRing ring;
651:
652:                int len = (dim + lrs);
653:                int start = (sOffset - 1) / len;
654:                int eOffset = StartingOffset(elemInfo, elemIndex + 1); // -1 for end
655:                int end = (eOffset != -1) ? ((eOffset - 1) / len) : coords
656:                        .size();
657:
658:                if (interpretation == 1) {
659:                    ring = gf
660:                            .createLinearRing(subList(gf
661:                                    .getCoordinateSequenceFactory(), coords,
662:                                    start, end));
663:                } else { // interpretation == 3
664:                    // rectangle does not maintain measures
665:                    //
666:                    CoordinateSequence ext = subList(gf
667:                            .getCoordinateSequenceFactory(), coords, start, end);
668:                    Coordinate min = ext.getCoordinate(0);
669:                    Coordinate max = ext.getCoordinate(1);
670:                    ring = gf.createLinearRing(new Coordinate[] { min,
671:                            new Coordinate(max.x, min.y), max,
672:                            new Coordinate(min.x, max.y), min });
673:                }
674:
675:                return ring;
676:            }
677:
678:            /**
679:             * Create LineString as encoded.
680:             *
681:             * @param gf
682:             * @param elemInfo
683:             * @param coords
684:             *
685:             * @return LineString
686:             *
687:             * @throws IllegalArgumentException If asked to create a curve
688:             */
689:            private LineString createLine(GeometryFactory gf, int dim, int lrs,
690:                    int[] elemInfo, int elemIndex, CoordinateSequence coords) {
691:
692:                int sOffset = StartingOffset(elemInfo, elemIndex);
693:                int etype = eType(elemInfo, elemIndex);
694:                int interpretation = interpretation(elemInfo, elemIndex);
695:
696:                if (etype != Constants.SDO_ETYPE.LINE)
697:                    return null;
698:
699:                if (interpretation != 1) {
700:                    throw new IllegalArgumentException(
701:                            "ELEM_INFO INTERPRETAION "
702:                                    + interpretation
703:                                    + " not supported"
704:                                    + "by JTS LineString.  Straight edges"
705:                                    + "( ELEM_INFO INTERPRETAION 1) is supported");
706:                }
707:
708:                int len = (dim + lrs);
709:                int start = (sOffset - 1) / len;
710:                int eOffset = StartingOffset(elemInfo, elemIndex + 1); // -1 for end
711:                int end = (eOffset != -1) ? ((eOffset - 1) / len) : coords
712:                        .size();
713:
714:                LineString line = gf.createLineString(subList(gf
715:                        .getCoordinateSequenceFactory(), coords, start, end));
716:
717:                return line;
718:            }
719:
720:            /**
721:             * Create Point as encoded.
722:             *
723:             * @param gf
724:             * @param dim The number of Dimensions
725:             * @param elemInfo
726:             * @param elemIndex
727:             * @param coords
728:             *
729:             * @return Point
730:             */
731:            private Point createPoint(GeometryFactory gf, int dim, int lrs,
732:                    int[] elemInfo, int elemIndex, CoordinateSequence coords) {
733:                int sOffset = StartingOffset(elemInfo, elemIndex);
734:                int etype = eType(elemInfo, elemIndex);
735:                int interpretation = interpretation(elemInfo, elemIndex);
736:
737:                if (!(sOffset >= 1) || !(sOffset <= coords.size()))
738:                    throw new IllegalArgumentException(
739:                            "ELEM_INFO STARTING_OFFSET " + sOffset
740:                                    + " inconsistent with ORDINATES length "
741:                                    + coords.size());
742:                if (etype != Constants.SDO_ETYPE.POINT)
743:                    throw new IllegalArgumentException("ETYPE " + etype
744:                            + " inconsistent with expected POINT");
745:                if (interpretation != 1) {
746:                    return null;
747:                }
748:
749:                int len = (dim + lrs);
750:                int start = (sOffset - 1) / len;
751:                int eOffset = StartingOffset(elemInfo, elemIndex + 1); // -1 for end
752:
753:                Point point = null;
754:                if ((sOffset == 1) && (eOffset == -1)) {
755:                    // Use all Coordinates
756:                    point = gf.createPoint(coords);
757:                } else {
758:                    int end = (eOffset != -1) ? ((eOffset - 1) / len) : coords
759:                            .size();
760:                    point = gf
761:                            .createPoint(subList(gf
762:                                    .getCoordinateSequenceFactory(), coords,
763:                                    start, end));
764:                }
765:
766:                return point;
767:            }
768:
769:            /**
770:             * Version of List.subList() that returns a CoordinateSequence.
771:             *
772:             * <p>
773:             * Returns from start (inclusive) to end (exlusive):
774:             * </p>
775:             *
776:             * @param factory Manages CoordinateSequences for JTS
777:             * @param coords coords to sublist
778:             * @param start starting offset
779:             * @param end upper bound of sublist
780:             *
781:             * @return CoordianteSequence
782:             */
783:            private CoordinateSequence subList(
784:                    CoordinateSequenceFactory factory,
785:                    CoordinateSequence coords, int start, int end) {
786:                if ((start == 0) && (end == coords.size())) {
787:                    return coords;
788:                }
789:
790:                if (coords instanceof  List) {
791:                    List sublist = ((List) coords).subList(start, end);
792:
793:                    if (sublist instanceof  CoordinateSequence) {
794:                        return (CoordinateSequence) sublist;
795:                    }
796:                }
797:
798:                CoordinateList list = new CoordinateList(coords
799:                        .toCoordinateArray());
800:
801:                Coordinate[] array = new Coordinate[end - start];
802:                int index = 0;
803:
804:                for (Iterator i = list.subList(start, end).iterator(); i
805:                        .hasNext(); index++) {
806:                    array[index] = (Coordinate) i.next();
807:                }
808:
809:                return factory.create(array);
810:            }
811:
812:            /**
813:             * ETYPE access for the elemInfo triplet indicated.
814:             * <p>
815:             * @see Constants.SDO_ETYPE for an indication of possible values
816:             *
817:             * @param elemInfo
818:             * @param tripletIndex
819:             * @return ETYPE for indicated triplet
820:             */
821:            private int eType(int[] elemInfo, int tripletIndex) {
822:                if (((tripletIndex * 3) + 1) >= elemInfo.length) {
823:                    return -1;
824:                }
825:
826:                return elemInfo[(tripletIndex * 3) + 1];
827:            }
828:
829:            /**
830:             * Accesses the interpretation value for the current geometry
831:             *
832:             * JTS valid interpretation is: 1 for strait edges, 3 for rectangle
833:             *
834:             * Other interpretations include: 2 for arcs, 4 for circles
835:             *
836:             * mostly useful for polygons
837:             *
838:             * @param elemInfo
839:             * @param tripletIndex
840:             * @return Starting Offset for the ordinates of the geometry
841:             */
842:            private int interpretation(int[] elemInfo, int tripletIndex) {
843:                if (((tripletIndex * 3) + 2) >= elemInfo.length) {
844:                    return -1;
845:                }
846:
847:                return elemInfo[(tripletIndex * 3) + 2];
848:            }
849:
850:            /**
851:             * Accesses the starting index in the ordinate array for the current geometry
852:             *
853:             * mostly useful for polygons
854:             *
855:             * @param elemInfo
856:             * @param tripletIndex
857:             * @return Starting Offset for the ordinates of the geometry
858:             */
859:            private int StartingOffset(int[] elemInfo, int tripletIndex) {
860:                if (((tripletIndex * 3) + 0) >= elemInfo.length) {
861:                    return -1;
862:                }
863:
864:                return elemInfo[(tripletIndex * 3) + 0];
865:            }
866:
867:            /** Presents datum as an int */
868:            private int asInteger(Datum datum, final int DEFAULT)
869:                    throws SQLException {
870:                if (datum == null)
871:                    return DEFAULT;
872:                return ((NUMBER) datum).intValue();
873:            }
874:
875:            /** Presents datum as a double */
876:            private double asDouble(Datum datum, final double DEFAULT) {
877:                if (datum == null)
878:                    return DEFAULT;
879:                return ((NUMBER) datum).doubleValue();
880:            }
881:
882:            /** Presents struct as a double[] */
883:            private double[] asDoubleArray(STRUCT struct, final double DEFAULT)
884:                    throws SQLException {
885:                if (struct == null)
886:                    return null;
887:                return asDoubleArray(struct.getOracleAttributes(), DEFAULT);
888:            }
889:
890:            /** Presents array as a double[] */
891:            private double[] asDoubleArray(ARRAY array, final double DEFAULT)
892:                    throws SQLException {
893:                if (array == null)
894:                    return null;
895:                if (DEFAULT == 0)
896:                    return array.getDoubleArray();
897:
898:                return asDoubleArray(array.getOracleArray(), DEFAULT);
899:            }
900:
901:            /** Presents Datum[] as a double[] */
902:            private double[] asDoubleArray(Datum data[], final double DEFAULT) {
903:                if (data == null)
904:                    return null;
905:                double array[] = new double[data.length];
906:                for (int i = 0; i < data.length; i++) {
907:                    array[i] = asDouble(data[i], DEFAULT);
908:                }
909:                return array;
910:            }
911:
912:            private int[] asIntArray(ARRAY array, int DEFAULT)
913:                    throws SQLException {
914:                if (array == null)
915:                    return null;
916:                if (DEFAULT == 0)
917:                    return array.getIntArray();
918:
919:                return asIntArray(array.getOracleArray(), DEFAULT);
920:            }
921:
922:            /** Presents Datum[] as a int[] */
923:            private int[] asIntArray(Datum data[], final int DEFAULT)
924:                    throws SQLException {
925:                if (data == null)
926:                    return null;
927:                int array[] = new int[data.length];
928:                for (int i = 0; i < data.length; i++) {
929:                    array[i] = asInteger(data[i], DEFAULT);
930:                }
931:                return array;
932:            }
933:
934:            public int getDimension() {
935:                return dimension;
936:            }
937:
938:            public void setDimension(int dimension) {
939:                this.dimension = dimension;
940:            }
941:
942:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.