Source Code Cross Referenced for OracleDataStore.java in  » GIS » GeoTools-2.4.1 » org » geotools » data » 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 » GeoTools 2.4.1 » org.geotools.data.oracle 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2002-2006, Geotools Project Managment Committee (PMC)
005:         *
006:         *    This library is free software; you can redistribute it and/or
007:         *    modify it under the terms of the GNU Lesser General Public
008:         *    License as published by the Free Software Foundation; either
009:         *    version 2.1 of the License, or (at your option) any later version.
010:         *
011:         *    This library is distributed in the hope that it will be useful,
012:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014:         *    Lesser General Public License for more details.
015:         *
016:         *    Created on 16/10/2003
017:         */
018:        package org.geotools.data.oracle;
019:
020:        import java.io.IOException;
021:        import java.sql.Connection;
022:        import java.sql.ResultSet;
023:        import java.sql.SQLException;
024:        import java.sql.Statement;
025:        import java.util.ArrayList;
026:        import java.util.Arrays;
027:        import java.util.Iterator;
028:        import java.util.List;
029:        import java.util.Map;
030:        import java.util.logging.Level;
031:        import java.util.logging.Logger;
032:
033:        import javax.sql.DataSource;
034:        import oracle.jdbc.OracleConnection;
035:        import oracle.sql.ARRAY;
036:        import oracle.sql.Datum;
037:        import oracle.sql.STRUCT;
038:
039:        import org.geotools.data.DataSourceException;
040:        import org.geotools.data.DataUtilities;
041:        import org.geotools.data.DefaultQuery;
042:        import org.geotools.data.DefaultTransaction;
043:        import org.geotools.data.FeatureReader;
044:        import org.geotools.data.FeatureSource;
045:        import org.geotools.data.Query;
046:        import org.geotools.data.Transaction;
047:        import org.geotools.data.jdbc.DefaultSQLBuilder;
048:        import org.geotools.data.jdbc.FeatureTypeInfo;
049:        import org.geotools.data.jdbc.JDBCDataStore;
050:        import org.geotools.data.jdbc.JDBCDataStoreConfig;
051:        import org.geotools.data.jdbc.JDBCFeatureWriter;
052:        import org.geotools.data.jdbc.JDBCUtils;
053:        import org.geotools.data.jdbc.QueryData;
054:        import org.geotools.data.jdbc.SQLBuilder;
055:        import org.geotools.data.jdbc.attributeio.AttributeIO;
056:        import org.geotools.data.jdbc.datasource.DataSourceFinder;
057:        import org.geotools.data.jdbc.datasource.UnWrapper;
058:        import org.geotools.data.oracle.attributeio.SDOAttributeIO;
059:        import org.geotools.data.oracle.referencing.OracleAuthorityFactory;
060:        import org.geotools.data.oracle.sdo.GeometryConverter;
061:        import org.geotools.data.oracle.sdo.TT;
062:        import org.geotools.feature.AttributeType;
063:        import org.geotools.feature.AttributeTypeFactory;
064:        import org.geotools.feature.FeatureType;
065:        import org.geotools.feature.GeometryAttributeType;
066:        import org.geotools.feature.SchemaException;
067:        import org.geotools.filter.SQLEncoder;
068:        import org.geotools.filter.SQLEncoderException;
069:        import org.geotools.filter.SQLEncoderOracle;
070:        import org.geotools.geometry.jts.ReferencedEnvelope;
071:        import org.geotools.referencing.CRS;
072:        import org.opengis.filter.Filter;
073:        import org.opengis.referencing.FactoryException;
074:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
075:        import org.opengis.referencing.crs.GeodeticCRS;
076:
077:        import com.vividsolutions.jts.geom.Envelope;
078:        import com.vividsolutions.jts.geom.Geometry;
079:        import com.vividsolutions.jts.geom.GeometryFactory;
080:        import com.vividsolutions.jts.io.ParseException;
081:
082:        /**
083:         * @author Sean Geoghegan, Defence Science and Technology Organisation.
084:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/oracle-spatial/src/main/java/org/geotools/data/oracle/OracleDataStore.java $
085:         */
086:        public class OracleDataStore extends JDBCDataStore {
087:            private static final Logger LOGGER = org.geotools.util.logging.Logging
088:                    .getLogger("org.geotools.data.oracle");
089:            private OracleAuthorityFactory af;
090:
091:            /**
092:             * @param connectionPool
093:             * @param config
094:             * @throws IOException
095:             */
096:            public OracleDataStore(DataSource dataSource,
097:                    JDBCDataStoreConfig config) throws IOException {
098:                super (dataSource, config);
099:            }
100:
101:            /**
102:             * @param connectionPool
103:             * @throws DataSourceException
104:             */
105:            public OracleDataStore(DataSource dataSource, String schemaName,
106:                    Map fidGeneration) throws IOException {
107:                this (dataSource, schemaName, schemaName, fidGeneration);
108:            }
109:
110:            /**
111:             * @param connectionPool
112:             * @param namespace
113:             * @throws DataSourceException
114:             */
115:            public OracleDataStore(DataSource dataSource, String namespace,
116:                    String schemaName, Map fidGeneration) throws IOException {
117:                //Ok, this needs more investigation, since the config constructor being
118:                //used seems to ignoe the fid map stuff.  I don't quite understand it,
119:                //and I think it may get picked up later, or at least auto-generated
120:                //later - maybe this is for the user specified stuff that never got
121:                //implemented.  Point being this needs to be looked into, I'm just 
122:                //setting it like this to get things working. -ch
123:                this (dataSource, new JDBCDataStoreConfig(namespace, schemaName,
124:                        null, fidGeneration));
125:
126:            }
127:
128:            /** Crops non feature type tables. 
129:             * There are alot of additional tables in a Oracle tablespace. This tries
130:             * to remove some of them.  If the schemaName is provided in the Constructor
131:             * then the job of narrowing down tables will be mush easier.  Otherwise
132:             * there are alot of Meta tables and SDO tables to cull.  This method tries
133:             * to remove as many as possible. 
134:             * 
135:             * @see org.geotools.data.jdbc.JDBCDataStore#allowTable(java.lang.String)
136:             */
137:            protected boolean allowTable(String tablename) {
138:                LOGGER.finer("checking table name: " + tablename);
139:                if (tablename.endsWith("$")) {
140:                    return false;
141:                } else if (tablename.startsWith("BIN$")) { // Added to ignore some Oracle 10g tables
142:                    return false;
143:                } else if (tablename.startsWith("XDB$")) {
144:                    return false;
145:                } else if (tablename.startsWith("DR$")) {
146:                    return false;
147:                } else if (tablename.startsWith("DEF$")) {
148:                    return false;
149:                } else if (tablename.startsWith("SDO_")) {
150:                    return false;
151:                } else if (tablename.startsWith("WM$")) {
152:                    return false;
153:                } else if (tablename.startsWith("WK$")) {
154:                    return false;
155:                } else if (tablename.startsWith("AW$")) {
156:                    return false;
157:                } else if (tablename.startsWith("AQ$")) {
158:                    return false;
159:                } else if (tablename.startsWith("APPLY$")) {
160:                    return false;
161:                } else if (tablename.startsWith("REPCAT$")) {
162:                    return false;
163:                } else if (tablename.startsWith("CWM$")) {
164:                    return false;
165:                } else if (tablename.startsWith("CWM2$")) {
166:                    return false;
167:                } else if (tablename.startsWith("EXF$")) {
168:                    return false;
169:                } else if (tablename.startsWith("DM$")) {
170:                    return false;
171:                }
172:                LOGGER.finer("returning true for tablename: " + tablename);
173:                return true;
174:            }
175:
176:            /**
177:             * Overrides the buildAttributeType method to check for SDO_GEOMETRY columns.
178:             * 
179:             * @see <a href="http://download-west.oracle.com/docs/cd/B14117_01/appdev.101/b10826.pdf">A doc from Oracle.</a>
180:             * 
181:             *  TODO: Determine the specific type of the geometry.
182:             */
183:            protected AttributeType buildAttributeType(ResultSet rs)
184:                    throws IOException {
185:                final int TABLE_NAME = 3;
186:                final int COLUMN_NAME = 4;
187:                final int TYPE_NAME = 6;
188:                final int IS_NULLABLE = 18; // "NO", "YES" or ""
189:                try {
190:                    if (rs.getString(TYPE_NAME).equals("SDO_GEOMETRY")) {
191:                        String tableName = rs.getString(TABLE_NAME);
192:                        String columnName = rs.getString(COLUMN_NAME);
193:                        String isNullable = rs.getString(IS_NULLABLE);
194:                        return getSDOGeometryAttribute(tableName, columnName,
195:                                "YES".equals(isNullable));
196:                    } else {
197:                        return super .buildAttributeType(rs);
198:                    }
199:                } catch (SQLException e) {
200:                    throw new DataSourceException("Sql error occurred", e);
201:                }
202:            }
203:
204:            /**
205:             * Construct and SDO_GEOMETRY attribute.
206:             * 
207:             * @see org.geotools.data.jdbc.JDBCDataStore#buildAttributeType(java.sql.ResultSet) 
208:             * @param tableName
209:             * @param columnName
210:             * @param isNillable 
211:             */
212:            private AttributeType getSDOGeometryAttribute(String tableName,
213:                    String columnName, boolean isNullable) {
214:                int srid = 0; // aka NULL
215:                CoordinateReferenceSystem crs = null;
216:                // here we have two separate point of failure, better keep them separated, 
217:                try {
218:                    srid = determineSRID(tableName, columnName);
219:                    try {
220:                        crs = CRS.decode("EPSG:" + srid);
221:                    } catch (Exception e) {
222:                        // decode failed, let's try the internal authority
223:                        crs = determineCRS(srid);
224:                    }
225:                } catch (Exception e) {
226:                    LOGGER.warning("Could not map SRID " + srid + " to CRS:"
227:                            + e);
228:                }
229:                try {
230:                    Class geomClass = determineGeometryClass(tableName,
231:                            columnName);
232:                    return AttributeTypeFactory.newAttributeType(columnName,
233:                            geomClass, isNullable, 0, null, crs);
234:                } catch (IOException e) {
235:                    LOGGER.warning("Could not determine geometry class for ["
236:                            + tableName + "." + columnName + "]");
237:                }
238:                return AttributeTypeFactory.newAttributeType(columnName,
239:                        Geometry.class, isNullable);
240:            }
241:
242:            private Class determineGeometryClass(String tableName,
243:                    String columnName) throws IOException {
244:                Connection conn = null;
245:                Statement statement = null;
246:                ResultSet result = null;
247:                try {
248:                    String sqlStatement = //
249:                    "select meta.sdo_layer_gtype \n"
250:                            + "from mdsys.ALL_SDO_INDEX_INFO info \n"
251:                            + " inner join mdsys.user_sdo_index_metadata meta \n"
252:                            + " on info.index_name = meta.sdo_index_name \n" //
253:                            + "where info.table_name = '" + tableName + "' \n" //
254:                            + "and info.column_name = '" + columnName + "'";
255:                    String schema = config.getDatabaseSchemaName();
256:                    if (schema != null && !"".equals(schema)) {
257:                        sqlStatement += " and info.table_owner = '" + schema
258:                                + "'";
259:                    }
260:                    conn = getConnection(Transaction.AUTO_COMMIT);
261:                    LOGGER
262:                            .finer("the sql statement for geometry type check is "
263:                                    + sqlStatement);
264:                    statement = conn.createStatement();
265:                    result = statement.executeQuery(sqlStatement);
266:
267:                    if (result.next()) {
268:                        String gType = result.getString(1);
269:                        Class geometryClass = (Class) TT.GEOM_CLASSES
270:                                .get(gType);
271:                        if (geometryClass == null)
272:                            geometryClass = Geometry.class;
273:
274:                        return geometryClass;
275:                    } else {
276:                        return Geometry.class;
277:                    }
278:                } catch (SQLException sqle) {
279:                    String message = sqle.getMessage();
280:                    LOGGER
281:                            .fine("Could not determine geometry class due to an error_: "
282:                                    + sqle);
283:
284:                    throw new DataSourceException(message, sqle);
285:                } finally {
286:                    JDBCUtils.close(result);
287:                    JDBCUtils.close(statement);
288:                    JDBCUtils.close(conn, Transaction.AUTO_COMMIT, null);
289:                }
290:
291:            }
292:
293:            protected CoordinateReferenceSystem determineCRS(int srid)
294:                    throws IOException {
295:                try {
296:                    return getOracleAuthorityFactory().createCRS(srid);
297:                } catch (FactoryException e) {
298:                    return null;
299:                }
300:            }
301:
302:            /**
303:             * @see org.geotools.data.jdbc.JDBCDataStore#determineSRID(java.lang.String, java.lang.String)
304:             */
305:            protected int determineSRID(String tableName,
306:                    String geometryColumnName) throws IOException {
307:                Connection conn = null;
308:                try {
309:                    String sqlStatement = "SELECT SRID FROM MDSYS.ALL_SDO_GEOM_METADATA "
310:                            + "WHERE TABLE_NAME='"
311:                            + tableName
312:                            + "' AND COLUMN_NAME='" + geometryColumnName + "'";
313:                    String schema = config.getDatabaseSchemaName();
314:                    if (schema != null && !"".equals(schema)) {
315:                        sqlStatement += " and OWNER = '" + schema + "'";
316:                    }
317:                    conn = getConnection(Transaction.AUTO_COMMIT);
318:                    LOGGER.finer("the sql statement for srid is "
319:                            + sqlStatement);
320:                    Statement statement = conn.createStatement();
321:                    ResultSet result = statement.executeQuery(sqlStatement);
322:
323:                    if (result.next()) {
324:                        int retSrid = result.getInt("srid");
325:                        JDBCUtils.close(statement);
326:
327:                        return retSrid;
328:                    } else {
329:                        String mesg = "No geometry column row for srid in table: "
330:                                + tableName
331:                                + ", geometry column "
332:                                + geometryColumnName
333:                                + ", be sure column is defined in USER_SDO_GEOM_METADATA";
334:                        throw new DataSourceException(mesg);
335:                    }
336:                } catch (SQLException sqle) {
337:                    String message = sqle.getMessage();
338:
339:                    throw new DataSourceException(message, sqle);
340:                } finally {
341:                    JDBCUtils.close(conn, Transaction.AUTO_COMMIT, null);
342:                }
343:            }
344:
345:            private OracleAuthorityFactory getOracleAuthorityFactory() {
346:                if (af == null) {
347:                    af = new OracleAuthorityFactory(dataSource);
348:                }
349:
350:                return af;
351:            }
352:
353:            /**
354:             * @see org.geotools.data.jdbc.JDBCDataStore#getSqlBuilder(java.lang.String)
355:             */
356:            public SQLBuilder getSqlBuilder(String typeName) throws IOException {
357:                FeatureTypeInfo info = typeHandler.getFeatureTypeInfo(typeName);
358:                SQLEncoder encoder = new SQLEncoderOracle(info.getSRIDs());
359:                encoder.setFIDMapper(getFIDMapper(typeName));
360:                return new DefaultSQLBuilder(encoder, info.getSchema(), null);
361:            }
362:
363:            /**
364:             * @see org.geotools.data.jdbc.JDBCDataStore#getGeometryAttributeIO(org.geotools.feature.AttributeType, org.geotools.data.jdbc.QueryData)
365:             */
366:            protected AttributeIO getGeometryAttributeIO(AttributeType type,
367:                    QueryData queryData) throws IOException {
368:                return new SDOAttributeIO(type, queryData);
369:            }
370:
371:            /**
372:             * Returns a Oracle text based feature writer that just issues the sql
373:             * statements directly, as text.  Jody and Sean say things will go faster 
374:             * if we use updatable resultsets and all that jazz, but I can't get
375:             * those to work, and this does, so I'm going forth with it.
376:             *
377:             * @task TODO: Comment out this method and try out the default JDBC
378:             *             FeatureWriter - Jody thinks it will go faster.  It will
379:             *             need to be debugged, however, as it would not work.
380:             */
381:            protected JDBCFeatureWriter createFeatureWriter(
382:                    FeatureReader fReader, QueryData queryData)
383:                    throws IOException {
384:                return new OracleFeatureWriter(fReader, queryData);
385:            }
386:
387:            /**
388:             * Retrieve approx bounds of all Features.
389:             * <p>
390:             * This result is suitable for a quick map display, illustrating the data.
391:             * This value is often stored as metadata in databases such as oraclespatial.
392:             * </p>
393:             * @return null as a generic implementation is not provided.
394:             */
395:
396:            public Envelope getEnvelope(String typeName) {
397:                try {
398:                    return bounds(new DefaultQuery(typeName));
399:                } catch (IOException e) {
400:                    LOGGER.log(Level.WARNING,
401:                            "Could not compute feature type bounds", e);
402:                    return null;
403:                }
404:            }
405:
406:            /** This is used by helper classes to hammer sql back to the database */
407:            public boolean sql(Transaction t, String sql) throws IOException,
408:                    SQLException {
409:                Connection conn = getConnection(t);
410:                Statement st = conn.createStatement();
411:                LOGGER.info(sql);
412:                return st.execute(sql);
413:            }
414:
415:            public void createSchema(FeatureType featureType)
416:                    throws IOException {
417:                String tableName = featureType.getTypeName();
418:                Transaction t = new DefaultTransaction("createSchema");
419:
420:                //CoordinateReferenceSystem crs = featureType.getDefaultGeometry().getCoordinateSystem();
421:                // TODO: lookup srid for crs
422:                Envelope bounds = new Envelope();
423:                bounds.expandToInclude(-180, -90);
424:                bounds.expandToInclude(180, 90);
425:                int srid = -1;
426:
427:                SQLEncoderOracle encoder = new SQLEncoderOracle("fid", srid); // should figure out from encoding
428:                SqlStatementEncoder statements = new SqlStatementEncoder(
429:                        encoder, tableName, "fid");
430:
431:                try {
432:                    sql(t, "DROP TABLE " + tableName);
433:                    sql(t,
434:                            "DELETE FROM user_sdo_geom_metadata WHERE TABLE_NAME='"
435:                                    + tableName + "'");
436:                } catch (SQLException ignore) {
437:                    // table probably did not exist
438:                }
439:                try {
440:                    sql(t, statements.makeCreateTableSQL(featureType));
441:
442:                    sql(t, statements.makeAddGeomMetadata(featureType, bounds,
443:                            srid));
444:                    //sql( t, statements.makeCreateFidIndex() );
445:                    //sql( t, statements.makeCreateGeomIndex( featureType ) );
446:
447:                    t.commit();
448:
449:                } catch (SQLException e) {
450:                    t.rollback();
451:                    throw (IOException) new IOException(e.getLocalizedMessage())
452:                            .initCause(e);
453:                } finally {
454:                    t.close();
455:                }
456:            }
457:
458:            /**
459:             * Default implementation based on getFeatureReader and getFeatureWriter.
460:             *
461:             * <p>
462:             * We should be able to optimize this to only get the RowSet once
463:             * </p>
464:             *
465:             * @see org.geotools.data.DataStore#getFeatureSource(java.lang.String)
466:             */
467:            public FeatureSource getFeatureSource(String typeName)
468:                    throws IOException {
469:                if (!typeHandler.getFIDMapper(typeName).isVolatile()
470:                        || allowWriteOnVolatileFIDs) {
471:                    if (getLockingManager() != null) {
472:                        // Use default JDBCFeatureLocking that delegates all locking
473:                        // the getLockingManager
474:                        //
475:                        return new OracleFeatureLocking(this ,
476:                                getSchema(typeName));
477:                    } else {
478:                        // subclass should provide a FeatureLocking implementation
479:                        // but for now we will simply forgo all locking
480:                        return new OracleFeatureStore(this , getSchema(typeName));
481:                    }
482:                } else {
483:                    return new OracleFeatureSource(this , getSchema(typeName));
484:                }
485:            }
486:
487:            /**
488:             * This is (unfortunately) a copy and paste from PostgisFeatureStore, I simply did not
489:             * know a better place to put this...
490:             * @param query
491:             * @return
492:             * @throws IOException
493:             */
494:            protected ReferencedEnvelope bounds(Query query) throws IOException {
495:                Filter filter = query.getFilter();
496:
497:                if (filter == Filter.EXCLUDE) {
498:                    return new ReferencedEnvelope(new Envelope(), query
499:                            .getCoordinateSystem());
500:                }
501:
502:                FeatureType schema = getSchema(query.getTypeName());
503:                SQLBuilder sqlBuilder = getSqlBuilder(schema.getTypeName());
504:
505:                Filter postQueryFilter = sqlBuilder.getPostQueryFilter(query
506:                        .getFilter());
507:                if (postQueryFilter != null
508:                        && !postQueryFilter.equals(Filter.INCLUDE)) {
509:                    // this would require postprocessing the filter
510:                    // so we cannot optimize
511:                    return null;
512:                }
513:
514:                Connection conn = null;
515:                try {
516:                    conn = getConnection(Transaction.AUTO_COMMIT);
517:
518:                    Envelope retEnv = new Envelope();
519:                    Filter preFilter = sqlBuilder.getPreQueryFilter(query
520:                            .getFilter());
521:                    AttributeType[] attributeTypes = schema.getAttributeTypes();
522:                    FeatureType schemaNew = schema;
523:                    if (!query.retrieveAllProperties()) {
524:                        try {
525:                            schemaNew = DataUtilities.createSubType(schema,
526:                                    query.getPropertyNames());
527:                            if (schemaNew.getDefaultGeometry() == null) // does the sub-schema have a
528:                            // geometry in it?
529:                            {
530:                                // uh-oh better get one!
531:                                if (schema.getDefaultGeometry() != null) // does the entire schema have a
532:                                // geometry in it?
533:                                {
534:                                    // buff-up the sub-schema so it has the default geometry in it.
535:                                    ArrayList al = new ArrayList(Arrays
536:                                            .asList(query.getPropertyNames()));
537:                                    al.add(schema.getDefaultGeometry()
538:                                            .getName());
539:                                    schemaNew = DataUtilities.createSubType(
540:                                            schema, (String[]) al
541:                                                    .toArray(new String[1]));
542:                                }
543:                            }
544:                        } catch (SchemaException e1) {
545:                            throw new DataSourceException(
546:                                    "Could not create subtype", e1);
547:                        }
548:                    }
549:                    // at this point, the query should have a geometry in it.
550:                    // BUT, if there's no geometry in the table, then the query will not (obviously) have a
551:                    // geometry in it.
552:
553:                    attributeTypes = schemaNew.getAttributeTypes();
554:
555:                    for (int j = 0, n = schemaNew.getAttributeCount(); j < n; j++) {
556:                        if (Geometry.class.isAssignableFrom(attributeTypes[j]
557:                                .getType())) // same as
558:                        // .isgeometry()
559:                        // - see new
560:                        // featuretype
561:                        // javadoc
562:                        {
563:                            String attName = attributeTypes[j].getName();
564:                            Envelope curEnv = getEnvelope(conn, schemaNew,
565:                                    attName, sqlBuilder, filter);
566:
567:                            if (curEnv == null) {
568:                                return null;
569:                            }
570:
571:                            retEnv.expandToInclude(curEnv);
572:                        }
573:                    }
574:
575:                    LOGGER.finer("returning bounds " + retEnv);
576:
577:                    if ((schemaNew != null)
578:                            && (schemaNew.getDefaultGeometry() != null))
579:                        return new ReferencedEnvelope(retEnv, schemaNew
580:                                .getDefaultGeometry().getCoordinateSystem());
581:                    if (query.getCoordinateSystem() != null)
582:                        return new ReferencedEnvelope(retEnv, query
583:                                .getCoordinateSystem());
584:                    return new ReferencedEnvelope(retEnv, null);
585:                } catch (SQLException sqlException) {
586:                    JDBCUtils
587:                            .close(conn, Transaction.AUTO_COMMIT, sqlException);
588:                    conn = null;
589:                    throw new DataSourceException("Could not count "
590:                            + query.getHandle(), sqlException);
591:                } catch (SQLEncoderException e) {
592:                    // could not encode count
593:                    // but at least we did not break the connection
594:                    return null;
595:                } catch (ParseException parseE) {
596:                    String message = "Could not read geometry: "
597:                            + parseE.getMessage();
598:
599:                    return null;
600:                } finally {
601:                    JDBCUtils.close(conn, Transaction.AUTO_COMMIT, null);
602:                }
603:            }
604:
605:            protected Envelope getEnvelope(Connection conn, FeatureType schema,
606:                    String geomName, SQLBuilder sqlBuilder, Filter filter)
607:                    throws SQLException, SQLEncoderException, IOException,
608:                    ParseException {
609:
610:                StringBuffer sql = new StringBuffer();
611:                GeometryAttributeType gat = (GeometryAttributeType) schema
612:                        .getAttributeType(geomName);
613:                // from the Oracle docs: "The SDO_TUNE.EXTENT_OF function has better performance than the
614:                // SDO_AGGR_MBR function if the data is non-geodetic and if a spatial index is defined
615:                // on the geometry column; however, the SDO_TUNE.EXTENT_OF function is limited to
616:                // two-dimensional geometries, whereas the SDO_AGGR_MBR function is not".
617:                // And also: "In addition, the SDO_TUNE.EXTENT_OF function computes the extent for all
618:                // geometries in a table; by contrast, the SDO_AGGR_MBR function can operate on
619:                // subsets of rows. The SDO_TUNE.EXTENT_OF function returns NULL if the data is inconsistent."
620:                // Long story short: under restrictive conditions SDO_TUNE.EXTENT_OF works, but we have
621:                // to be prepared to fall back on SDO_AGGR_MBR.
622:                List queries = new ArrayList();
623:                if (Filter.INCLUDE.equals(filter)
624:                        && !(gat.getCoordinateSystem() instanceof  GeodeticCRS)) {
625:                    sql.append("SELECT SDO_TUNE.EXTENT_OF('").append(
626:                            schema.getTypeName()).append("', '");
627:                    sql.append(geomName).append("') from dual");
628:                    queries.add(sql.toString());
629:                    sql = new StringBuffer();
630:                }
631:                sql.append("SELECT SDO_AGGR_MBR(").append(geomName)
632:                        .append(") ");
633:                sqlBuilder.sqlFrom(sql, schema.getTypeName());
634:                sqlBuilder.sqlWhere(sql, filter);
635:                queries.add(sql.toString());
636:
637:                LOGGER.fine("SQL: " + sql);
638:
639:                // loop over the (eventual) two sql statements, so that if the first does not provide
640:                // an answer, we fall back on the second
641:                Statement statement = null;
642:                ResultSet results = null;
643:                Envelope result = null;
644:                for (Iterator it = queries.iterator(); it.hasNext();) {
645:                    String query = (String) it.next();
646:                    try {
647:                        statement = conn.createStatement();
648:                        results = statement.executeQuery(query);
649:
650:                        results.next();
651:
652:                        Geometry geom = null;
653:                        Object struct = results.getObject(1);
654:                        UnWrapper unwrapper = DataSourceFinder
655:                                .getUnWrapper(conn);
656:                        OracleConnection oraConn = (OracleConnection) unwrapper
657:                                .unwrap(conn);
658:                        GeometryConverter converter = new GeometryConverter(
659:                                oraConn, new GeometryFactory());
660:                        geom = converter.asGeometry((STRUCT) struct);
661:
662:                        // Oracle may return a point, a line or a polygon
663:                        if (geom != null)
664:                            return geom.getEnvelopeInternal();
665:                    } finally {
666:                        JDBCUtils.close(results);
667:                        JDBCUtils.close(statement);
668:                    }
669:                }
670:                return result;
671:            }
672:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.