/* * The JTS Topology Suite is a collection of Java classes that * implement the fundamental operations required to validate a given * geo-spatial data set to a known topological specification. * * Copyright (C) 2001 Vivid Solutions * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * For more information, contact: * * Vivid Solutions * Suite #1A * 2328 Government Street * Victoria BC V8T 5G5 * Canada * * (250)385-6040 * www.vividsolutions.com */ /* * Geotools2 - OpenSource mapping toolkit * http://geotools.org * (C) 2003, Geotools Project Managment Committee (PMC) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; * version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * */ package com.vividsolutions.jts.io.oracle; import java.sql.SQLException; import java.util.*; import oracle.sql.*; import com.vividsolutions.jts.algorithm.CGAlgorithms; import com.vividsolutions.jts.geom.*; /** * Reads a {@link Geometry} from an Oracle <tt>MDSYS.GEOMETRY</tt> object. * * A {@link GeometryFactory} may be provided, otherwise * a default one will be used. * The provided GeometryFactory will be used, with the exception of the SRID field. * This will be extracted from the Geometry. * <p> * If a {@link PrecisionModel} is supplied it is the callers's responsibility * to ensure that it matches the precision of the incoming data. * If a lower precision for the data is required, a subsequent * process must be run on the data to reduce its precision. * <p> * To use this class a suitable Oracle JDBC driver JAR must be present. * * @version 9i * @author David Zwiers, Vivid Solutions. * @author Martin Davis */ public class OraReader { private GeometryFactory geometryFactory; public static final int NULL_DIMENSION = -1; private int dimension = -1; /** * Creates a new reader, with a default GeometryFactory. * * @see #OraReader(GeometryFactory) */ public OraReader() { this(new GeometryFactory()); } /** * Creates a new reader, with the supplied {@link GeometryFactory}. * It is assumed that the supplied {@link PrecisionModel} * matches the precision of the incoming data - * coordinates are <b>not</b> made precise. * * @param gf A non-null geometry factory for later use. * * @throws NullPointerException when the geometry factory is null. */ public OraReader(GeometryFactory gf) { if (gf == null) throw new NullPointerException("Geometry Factory may not be Null"); this.geometryFactory = gf; } /** * Gets the number of coordinate dimensions which will be read. * * @return the dimension which will be read */ public int getDimension() { return dimension; } /** * Sets the number of coordinate dimensions to read. * * @param dimension the dimension to read */ public void setDimension(int dimension) { this.dimension = dimension; } /** * This method will attempt to create a JTS Geometry for the MDSYS.GEOMETRY * provided. The Type of gemetry returned will depend on the input datum, * where the Geometry type is specified within the STRUCT. * * @param struct The MDSYS.GEOMETRY Object to decode * @return A JTS Geometry if one could be created, null otherwise * @throws SQLException When a read error occured within the struct */ public Geometry read(STRUCT struct) throws SQLException { // Note Returning null for null Datum if (struct == null) return null; Datum data[] = struct.getOracleAttributes(); int gType = asInteger(data[0], 0); int SRID = asInteger(data[1], Constants.SRID_NULL); double point[] = asDoubleArray((STRUCT) data[2], Double.NaN); int elemInfo[] = asIntArray((ARRAY) data[3], 0); double ordinates[] = asDoubleArray((ARRAY) data[4], Double.NaN); GeometryFactory gf = geometryFactory; if(geometryFactory.getSRID() != SRID){ // clone it and use the geom's srid gf = new GeometryFactory(geometryFactory.getPrecisionModel(),SRID,geometryFactory.getCoordinateSequenceFactory()); } return create(gf, gType, point, elemInfo, ordinates); } /** * Decode geometry from provided SDO encoded information. * * <p></p> * * @param gf Used to construct returned Geometry * @param gType SDO_GTEMPLATE represents dimension, LRS, and geometry type * @param point * @param elemInfo * @param ordinates * * @return Geometry as encoded */ private Geometry create(GeometryFactory gf, int gType, double[] point, int[] elemInfo, double[] ordinates) { int lrs = (gType%1000)/100; // find the dimension: represented by the smaller of the two dimensions int dim = 0; if(dimension != NULL_DIMENSION){ dim = dimension; }else{ dim = Math.min(gType/1000,gf.getCoordinateSequenceFactory().create(0,0).getDimension()) ; } if(dim<2){ throw new IllegalArgumentException("Dimension D:" + dim + " is not valid for JTS. " + "Either specify a dimension or use Oracle Locator Version 9i or later"); } // extract the geometry template type // this is represented as the rightmost two digits int geomTemplate = gType - (dim * 1000) - (lrs * 100); CoordinateSequence coords = null; if (lrs == 0 && geomTemplate == 1 && point != null && elemInfo == null) { // Single Point Type Optimization coords = coordinates(gf.getCoordinateSequenceFactory(), dim, lrs, geomTemplate, point); elemInfo = new int[] { 1, Constants.SDO_ETYPE.POINT, 1 }; } else { coords = coordinates(gf.getCoordinateSequenceFactory(), dim, lrs, geomTemplate, ordinates); } switch (geomTemplate) { case Constants.SDO_GTEMPLATE.POINT: return createPoint(gf, dim, lrs, elemInfo, 0, coords); case Constants.SDO_GTEMPLATE.LINE: return createLine(gf, dim, lrs, elemInfo, 0, coords); case Constants.SDO_GTEMPLATE.POLYGON: return createPolygon(gf, dim, lrs, elemInfo, 0, coords); case Constants.SDO_GTEMPLATE.MULTIPOINT: return createMultiPoint(gf, dim, lrs, elemInfo, 0, coords); case Constants.SDO_GTEMPLATE.MULTILINE: return createMultiLine(gf, dim, lrs, elemInfo, 0, coords, -1); case Constants.SDO_GTEMPLATE.MULTIPOLYGON: return createMultiPolygon(gf, dim, lrs, elemInfo, 0, coords, -1); case Constants.SDO_GTEMPLATE.COLLECTION: return createCollection(gf, dim, lrs, elemInfo, 0, coords,-1); default: return null; } } /** * Construct CoordinateList as described by GTYPE. * * The number of ordinates per coordinate are taken to be lrs+dim, and the * number of ordinates should be a multiple of this value. * In the Special case of GTYPE 2001 and a three ordinates are interpreted * as a single Coordinate rather than an error. * * @param f CoordinateSequenceFactory used to encode ordiantes for JTS * @param ordinates * * @return protected * * @throws IllegalArgumentException */ private CoordinateSequence coordinates(CoordinateSequenceFactory f, int dim, int lrs, int gtemplate, double[] ordinates) { if ((ordinates == null) || (ordinates.length == 0)) { return f.create(new Coordinate[0]); } // POINT_TYPE Special Case // if ((dim == 2) && (lrs == 0) && (gtemplate == 01) && (ordinates.length == 3)) { return f.create(new Coordinate[] { new Coordinate(ordinates[0], ordinates[1], ordinates[2]), }); } int len = dim + lrs; if ((len == 0 && ordinates.length!=0 ) || (len != 0 && ((ordinates.length % len) != 0))){ throw new IllegalArgumentException("Dimension D:" + dim + " and L:" + lrs + " denote Coordinates " + "of " + len + " ordinates. This cannot be resolved with" + "an ordinate array of length " + ordinates.length); } int length = (len == 0?0:ordinates.length / len); // we would have to ask for a dimension which represents all the requested // dimension and measures from a mask array in the future CoordinateSequence cs = f.create(length,dim); int actualDim = cs.getDimension(); for(int i=0;i<length;i++){ int j=0; // in the future change this condition to include ignored dimensions from mask array for(;j<actualDim && j<dim;j++){ cs.setOrdinate(i,j,ordinates[i*len+j]); // may not always want to inc. j when we have a mask array } // in the future change this condition to include ignored dimensions from mask array for(int d = j;j<actualDim && (j-d)<lrs;j++){ cs.setOrdinate(i,j,ordinates[i*len+j]); // may not always want to inc. j when we have a mask array } } return cs; } /** * Create MultiGeometry as encoded by elemInfo. * * @param gf Used to construct MultiLineString * @param elemInfo Interpretation of coords * @param elemIndex Triplet in elemInfo to process as a Polygon * @param coords Coordinates to interpret using elemInfo * @param numGeom Number of triplets (or -1 for rest) * * @return GeometryCollection * * @throws IllegalArgumentException DWhen faced with an encoding error */ private GeometryCollection createCollection(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords, int numGeom) { int sOffset = StartingOffset(elemInfo, elemIndex); int length = coords.size()*dim; if (!(sOffset <= length)) throw new IllegalArgumentException("ELEM_INFO STARTING_OFFSET "+sOffset+" inconsistent with ORDINATES length "+coords.size()); int endTriplet = (numGeom != -1) ? elemIndex + numGeom : elemInfo.length / 3 + 1; List list = new LinkedList(); int etype; int interpretation; Geometry geom; boolean cont = true; for (int i = elemIndex; cont && i < endTriplet; i++) { etype = eType(elemInfo, i); interpretation = interpretation(elemInfo, i); switch (etype) { case -1: cont = false; // We are the of the list - get out of here case Constants.SDO_ETYPE.POINT: if (interpretation == 1) { geom = createPoint(gf, dim, lrs, elemInfo, i, coords); } else if (interpretation > 1) { geom = createMultiPoint(gf, dim, lrs, elemInfo, i, coords); } else { throw new IllegalArgumentException( "ETYPE.POINT requires INTERPRETATION >= 1"); } break; case Constants.SDO_ETYPE.LINE: geom = createLine(gf, dim, lrs, elemInfo, i, coords); break; case Constants.SDO_ETYPE.POLYGON: case Constants.SDO_ETYPE.POLYGON_EXTERIOR: geom = createPolygon(gf, dim, lrs, elemInfo, i, coords); i += ((Polygon) geom).getNumInteriorRing(); break; case Constants.SDO_ETYPE.POLYGON_INTERIOR: throw new IllegalArgumentException( "ETYPE 2003 (Polygon Interior) no expected in a GeometryCollection" + "(2003 is used to represent polygon holes, in a 1003 polygon exterior)"); default: throw new IllegalArgumentException("ETYPE " + etype + " not representable as a JTS Geometry." + "(Custom and Compound Straight and Curved Geometries not supported)"); } list.add(geom); } GeometryCollection geoms = gf.createGeometryCollection((Geometry[]) list.toArray(new Geometry[list.size()])); return geoms; } /** * Create MultiPolygon as encoded by elemInfo. * * * @param gf Used to construct MultiLineString * @param elemInfo Interpretation of coords * @param elemIndex Triplet in elemInfo to process as a Polygon * @param coords Coordinates to interpret using elemInfo * @param numGeom Number of triplets (or -1 for rest) * * @return MultiPolygon */ private MultiPolygon createMultiPolygon(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords, int numGeom){ int sOffset = StartingOffset(elemInfo, elemIndex); int etype = eType(elemInfo, elemIndex); int interpretation = interpretation(elemInfo, elemIndex); int length = coords.size()*dim; if (!(sOffset >= 1) || !(sOffset <= length)) throw new IllegalArgumentException("ELEM_INFO STARTING_OFFSET "+sOffset+" inconsistent with ORDINATES length "+coords.size()); if(!(etype == Constants.SDO_ETYPE.POLYGON) && !(etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR)) throw new IllegalArgumentException("ETYPE "+etype+" inconsistent with expected POLYGON or POLYGON_EXTERIOR"); if (interpretation != 1 && interpretation != 3){ return null; } int endTriplet = (numGeom != -1) ? elemIndex + numGeom : (elemInfo.length / 3) + 1; List list = new LinkedList(); boolean cont = true; for (int i = elemIndex; cont && i < endTriplet && (etype = eType(elemInfo, i)) != -1; i++) { if ((etype == Constants.SDO_ETYPE.POLYGON) || (etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR)) { Polygon poly = createPolygon(gf, dim, lrs, elemInfo, i, coords); i += poly.getNumInteriorRing(); // skip interior rings list.add(poly); } else { // not a Polygon - get out here cont = false; } } MultiPolygon polys = gf.createMultiPolygon((Polygon[]) list.toArray(new Polygon[list.size()])); return polys; } /** * Create MultiLineString as encoded by elemInfo. * * * @param gf Used to construct MultiLineString * @param elemInfo Interpretation of coords * @param elemIndex Triplet in elemInfo to process as a Polygon * @param coords Coordinates to interpret using elemInfo * @param numGeom Number of triplets (or -1 for rest) * * @return MultiLineString */ private MultiLineString createMultiLine(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords, int numGeom) { int sOffset = StartingOffset(elemInfo, elemIndex); int etype = eType(elemInfo, elemIndex); int interpretation = interpretation(elemInfo, elemIndex); int length = coords.size()*dim; if (!(sOffset >= 1) || !(sOffset <= length)) throw new IllegalArgumentException("ELEM_INFO STARTING_OFFSET "+sOffset+" inconsistent with ORDINATES length "+coords.size()); if(!(etype == Constants.SDO_ETYPE.LINE)) throw new IllegalArgumentException("ETYPE "+etype+" inconsistent with expected LINE"); if (!(interpretation == 1)){ // we cannot represent INTERPRETATION > 1 return null; } int endTriplet = (numGeom != -1) ? (elemIndex + numGeom) : (elemInfo.length / 3); List list = new LinkedList(); boolean cont = true; for (int i = elemIndex; cont && i < endTriplet && (etype = eType(elemInfo, i)) != -1 ;i++) { if (etype == Constants.SDO_ETYPE.LINE) { list.add(createLine(gf, dim, lrs, elemInfo, i, coords)); } else { // not a LineString - get out of here cont = false; } } MultiLineString lines = gf.createMultiLineString((LineString[]) list.toArray(new LineString[list.size()])); return lines; } /** * Create MultiPoint as encoded by elemInfo. * * * @param gf Used to construct polygon * @param elemInfo Interpretation of coords * @param elemIndex Triplet in elemInfo to process as a Polygon * @param coords Coordinates to interpret using elemInfo * * @return MultiPoint */ private MultiPoint createMultiPoint(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords) { int sOffset = StartingOffset(elemInfo, elemIndex); int etype = eType(elemInfo, elemIndex); int interpretation = interpretation(elemInfo, elemIndex); if (!(sOffset >= 1) || !(sOffset <= coords.size())) throw new IllegalArgumentException("ELEM_INFO STARTING_OFFSET "+sOffset+" inconsistent with ORDINATES length "+coords.size()); if(!(etype == Constants.SDO_ETYPE.POINT)) throw new IllegalArgumentException("ETYPE "+etype+" inconsistent with expected POINT"); if (!(interpretation > 1)){ return null; } int len = dim + lrs; int start = (sOffset - 1) / len; int end = start + interpretation; MultiPoint points = gf.createMultiPoint(subList(gf.getCoordinateSequenceFactory(), coords, start, end)); return points; } /** * Create Polygon as encoded. * * @see #interpretation(int[], int) * * @param gf Used to construct polygon * @param elemInfo Interpretation of coords * @param elemIndex Triplet in elemInfo to process as a Polygon * @param coords Coordinates to interpret using elemInfo * * @return Polygon as encoded by elemInfo, or null when faced with and * encoding that can not be captured by JTS * @throws IllegalArgumentException When faced with an invalid SDO encoding */ private Polygon createPolygon(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords) { int sOffset = StartingOffset(elemInfo, elemIndex); int etype = eType(elemInfo, elemIndex); int interpretation = interpretation(elemInfo, elemIndex); if( !(1 <= sOffset && sOffset <= (coords.size() * dim))){ throw new IllegalArgumentException( "ELEM_INFO STARTING_OFFSET "+sOffset+ "inconsistent with COORDINATES length "+(coords.size() * dim) ); } if(!(etype == Constants.SDO_ETYPE.POLYGON) && !(etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR)){ throw new IllegalArgumentException("ETYPE "+etype+" inconsistent with expected POLYGON or POLYGON_EXTERIOR"); } if (!(interpretation == 1) && !(interpretation == 3)){ return null; } LinearRing exteriorRing = createLinearRing(gf, dim, lrs, elemInfo, elemIndex, coords); List rings = new LinkedList(); boolean cont = true; for (int i = elemIndex + 1; cont && (etype = eType(elemInfo, i)) != -1; i++) { if (etype == Constants.SDO_ETYPE.POLYGON_INTERIOR) { rings.add(createLinearRing(gf, dim, lrs, elemInfo, i, coords)); } else if (etype == Constants.SDO_ETYPE.POLYGON) { // need to test Clockwiseness of Ring to see if it is // interior or not - (use POLYGON_INTERIOR to avoid pain) LinearRing ring = createLinearRing(gf, dim, lrs, elemInfo, i, coords); if (CGAlgorithms.isCCW(ring.getCoordinates())) { // it is an Interior Hole rings.add(ring); } else { // it is the next Polygon! - get out of here cont = false; } } else { // not a LinearRing - get out of here cont = false; } } Polygon poly = gf.createPolygon(exteriorRing, (LinearRing[]) rings.toArray(new LinearRing[rings.size()])); return poly; } /** * Create Linear Ring for exterior/interior polygon ELEM_INFO triplets. * * @param gf * @param elemInfo * @param elemIndex * @param coords * * @return LinearRing * * @throws IllegalArgumentException If circle, or curve is requested */ private LinearRing createLinearRing(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords) { int sOffset = StartingOffset(elemInfo, elemIndex); int etype = eType(elemInfo, elemIndex); int interpretation = interpretation(elemInfo, elemIndex); int length = coords.size()*dim; if (!(sOffset <= length)) throw new IllegalArgumentException("ELEM_INFO STARTING_OFFSET "+sOffset+" inconsistent with ORDINATES length "+coords.size()); if(!(etype == Constants.SDO_ETYPE.POLYGON) && !(etype == Constants.SDO_ETYPE.POLYGON_EXTERIOR) && !(etype == Constants.SDO_ETYPE.POLYGON_INTERIOR)){ throw new IllegalArgumentException("ETYPE "+etype+" inconsistent with expected POLYGON, POLYGON_EXTERIOR or POLYGON_INTERIOR"); } if (!(interpretation == 1) && !(interpretation == 3)){ return null; } LinearRing ring; int len = (dim+lrs); int start = (sOffset - 1) / len; int eOffset = StartingOffset(elemInfo, elemIndex+1); // -1 for end int end = (eOffset != -1) ? ((eOffset - 1) / len) : coords.size(); if (interpretation == 1) { ring = gf.createLinearRing(subList(gf.getCoordinateSequenceFactory(),coords, start,end)); } else { // interpretation == 3 // rectangle does not maintain measures // CoordinateSequence ext = subList(gf.getCoordinateSequenceFactory(),coords, start,end); Coordinate min = ext.getCoordinate(0); Coordinate max = ext.getCoordinate(1); ring = gf.createLinearRing(new Coordinate[] { min, new Coordinate(max.x, min.y), max, new Coordinate(min.x, max.y), min }); } return ring; } /** * Create LineString as encoded. * * @param gf * @param elemInfo * @param coords * * @return LineString * * @throws IllegalArgumentException If asked to create a curve */ private LineString createLine(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords) { int sOffset = StartingOffset(elemInfo, elemIndex); int etype = eType(elemInfo, elemIndex); int interpretation = interpretation(elemInfo, elemIndex); if (etype != Constants.SDO_ETYPE.LINE) return null; if (interpretation != 1) { throw new IllegalArgumentException("ELEM_INFO INTERPRETAION " + interpretation + " not supported" + "by JTS LineString. Straight edges" + "( ELEM_INFO INTERPRETAION 1) is supported"); } int len = (dim+lrs); int start = (sOffset - 1) / len; int eOffset = StartingOffset(elemInfo, elemIndex+1); // -1 for end int end = (eOffset != -1) ? ((eOffset - 1) / len) : coords.size(); LineString line = gf.createLineString(subList(gf.getCoordinateSequenceFactory(),coords, start,end)); return line; } /** * Create Point as encoded. * * @param gf * @param dim The number of Dimensions * @param elemInfo * @param elemIndex * @param coords * * @return Point */ private Point createPoint(GeometryFactory gf, int dim, int lrs, int[] elemInfo, int elemIndex, CoordinateSequence coords) { int sOffset = StartingOffset(elemInfo, elemIndex); int etype = eType(elemInfo, elemIndex); int interpretation = interpretation(elemInfo, elemIndex); if (!(sOffset >= 1) || !(sOffset <= coords.size())) throw new IllegalArgumentException("ELEM_INFO STARTING_OFFSET "+sOffset+" inconsistent with ORDINATES length "+coords.size()); if (etype != Constants.SDO_ETYPE.POINT) throw new IllegalArgumentException("ETYPE "+etype+" inconsistent with expected POINT"); if (interpretation != 1){ return null; } int len = (dim+lrs); int start = (sOffset - 1) / len; int eOffset = StartingOffset(elemInfo, elemIndex+1); // -1 for end Point point = null; if ((sOffset == 1) && (eOffset == -1)) { // Use all Coordinates point = gf.createPoint( coords); }else{ int end = (eOffset != -1) ? ((eOffset - 1) / len) : coords.size(); point = gf.createPoint(subList(gf.getCoordinateSequenceFactory(),coords,start,end)); } return point; } /** * Version of List.subList() that returns a CoordinateSequence. * * <p> * Returns from start (inclusive) to end (exlusive): * </p> * * @param factory Manages CoordinateSequences for JTS * @param coords coords to sublist * @param start starting offset * @param end upper bound of sublist * * @return CoordianteSequence */ private CoordinateSequence subList(CoordinateSequenceFactory factory, CoordinateSequence coords, int start, int end) { if ((start == 0) && (end == coords.size())) { return coords; } if (coords instanceof List) { List sublist = ((List) coords).subList(start, end); if (sublist instanceof CoordinateSequence) { return (CoordinateSequence) sublist; } } CoordinateList list = new CoordinateList(coords.toCoordinateArray()); Coordinate[] array = new Coordinate[end - start]; int index = 0; for (Iterator i = list.subList(start, end).iterator(); i.hasNext(); index++) { array[index] = (Coordinate) i.next(); } return factory.create(array); } /** * ETYPE access for the elemInfo triplet indicated. * <p> * @see Constants.SDO_ETYPE for an indication of possible values * * @param elemInfo * @param tripletIndex * @return ETYPE for indicated triplet */ private int eType(int[] elemInfo, int tripletIndex) { if (((tripletIndex * 3) + 1) >= elemInfo.length) { return -1; } return elemInfo[(tripletIndex * 3) + 1]; } /** * Accesses the interpretation value for the current geometry * * JTS valid interpretation is: 1 for strait edges, 3 for rectangle * * Other interpretations include: 2 for arcs, 4 for circles * * mostly useful for polygons * * @param elemInfo * @param tripletIndex * @return Starting Offset for the ordinates of the geometry */ private int interpretation(int[] elemInfo, int tripletIndex) { if (((tripletIndex * 3) + 2) >= elemInfo.length) { return -1; } return elemInfo[(tripletIndex * 3) + 2]; } /** * Accesses the starting index in the ordinate array for the current geometry * * mostly useful for polygons * * @param elemInfo * @param tripletIndex * @return Starting Offset for the ordinates of the geometry */ private int StartingOffset(int[] elemInfo, int tripletIndex) { if (((tripletIndex * 3) + 0) >= elemInfo.length) { return -1; } return elemInfo[(tripletIndex * 3) + 0]; } /** Presents datum as an int */ private int asInteger(Datum datum, final int DEFAULT) throws SQLException { if (datum == null) return DEFAULT; return ((NUMBER) datum).intValue(); } /** Presents datum as a double */ private double asDouble(Datum datum, final double DEFAULT) { if (datum == null) return DEFAULT; return ((NUMBER) datum).doubleValue(); } /** Presents struct as a double[] */ private double[] asDoubleArray(STRUCT struct, final double DEFAULT) throws SQLException { if (struct == null) return null; return asDoubleArray(struct.getOracleAttributes(), DEFAULT); } /** Presents array as a double[] */ private double[] asDoubleArray(ARRAY array, final double DEFAULT) throws SQLException { if (array == null) return null; if (DEFAULT == 0) return array.getDoubleArray(); return asDoubleArray(array.getOracleArray(), DEFAULT); } /** Presents Datum[] as a double[] */ private double[] asDoubleArray(Datum data[], final double DEFAULT) { if (data == null) return null; double array[] = new double[data.length]; for (int i = 0; i < data.length; i++) { array[i] = asDouble(data[i], DEFAULT); } return array; } private int[] asIntArray(ARRAY array, int DEFAULT) throws SQLException { if (array == null) return null; if (DEFAULT == 0) return array.getIntArray(); return asIntArray(array.getOracleArray(), DEFAULT); } /** Presents Datum[] as a int[] */ private int[] asIntArray(Datum data[], final int DEFAULT) throws SQLException { if (data == null) return null; int array[] = new int[data.length]; for (int i = 0; i < data.length; i++) { array[i] = asInteger(data[i], DEFAULT); } return array; } }