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


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2003-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:        package org.geotools.filter;
017:
018:        import java.io.IOException;
019:        import java.util.Arrays;
020:        import java.util.HashMap;
021:        import java.util.Map;
022:        import java.util.Set;
023:        import java.util.logging.Logger;
024:
025:        import org.geotools.data.oracle.sdo.SDO;
026:        import org.geotools.data.DataSourceException;
027:        import org.opengis.filter.ExcludeFilter;
028:        import org.opengis.filter.Id;
029:        import org.opengis.filter.IncludeFilter;
030:        import org.opengis.filter.PropertyIsBetween;
031:        import org.opengis.filter.PropertyIsLike;
032:        import org.opengis.filter.PropertyIsNull;
033:        import org.opengis.filter.spatial.BBOX;
034:        import org.opengis.filter.spatial.Beyond;
035:        import org.opengis.filter.spatial.Contains;
036:        import org.opengis.filter.spatial.Crosses;
037:        import org.opengis.filter.spatial.DWithin;
038:        import org.opengis.filter.spatial.Disjoint;
039:        import org.opengis.filter.spatial.Equals;
040:        import org.opengis.filter.spatial.Intersects;
041:        import org.opengis.filter.spatial.Overlaps;
042:        import org.opengis.filter.spatial.Touches;
043:        import org.opengis.filter.spatial.Within;
044:
045:        import com.vividsolutions.jts.geom.Coordinate;
046:        import com.vividsolutions.jts.geom.CoordinateSequence;
047:        import com.vividsolutions.jts.geom.CoordinateSequenceFactory;
048:        import com.vividsolutions.jts.geom.Envelope;
049:        import com.vividsolutions.jts.geom.Geometry;
050:        import com.vividsolutions.jts.geom.LineString;
051:        import com.vividsolutions.jts.geom.MultiLineString;
052:        import com.vividsolutions.jts.geom.MultiPolygon;
053:        import com.vividsolutions.jts.geom.Point;
054:        import com.vividsolutions.jts.geom.Polygon;
055:
056:        /**
057:         * Encodes Geometry filters into valid oracle SDO statements.
058:         * 
059:         * <p>
060:         * At this stage it only supports the GEOMETRY_BBOX types.
061:         * </p>
062:         * 
063:         * <p>
064:         * Encoded filters get written to the protected Writer called <code>out</code>
065:         * </p>
066:         *
067:         * @author $Author: seangeo $
068:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/unsupported/oracle-spatial/src/main/java/org/geotools/filter/SQLEncoderOracle.java $
069:         * @version $Id: SQLEncoderOracle.java 27862 2007-11-12 19:51:19Z desruisseaux $
070:         */
071:        public class SQLEncoderOracle extends SQLEncoder {
072:
073:            /** Logger - for logging */
074:            private static final Logger LOGGER = org.geotools.util.logging.Logging
075:                    .getLogger("org.geotools.filter.SQLEncoderOracle");
076:
077:            /** Contains filter type to SDO_RELATE mask type mappings */
078:            private static final Map SDO_RELATE_MASK_MAP = new HashMap();
079:
080:            /** The standard SQL multicharacter wild card. */
081:            private static final String SQL_WILD_MULTI = "%";
082:
083:            /** The standard SQL single character wild card. */
084:            private static final String SQL_WILD_SINGLE = "_";
085:
086:            /** Default tolerance for spatial queries. */
087:            private static final String TOLERANCE = "0.001";
088:
089:            static {
090:                SDO_RELATE_MASK_MAP.put(new Short(
091:                        AbstractFilter.GEOMETRY_CONTAINS), "contains");
092:                SDO_RELATE_MASK_MAP.put(new Short(
093:                        AbstractFilter.GEOMETRY_CROSSES), "overlapbydisjoint");
094:                SDO_RELATE_MASK_MAP.put(new Short(
095:                        AbstractFilter.GEOMETRY_EQUALS), "equal");
096:                SDO_RELATE_MASK_MAP
097:                        .put(new Short(AbstractFilter.GEOMETRY_OVERLAPS),
098:                                "overlapbyintersect");
099:                SDO_RELATE_MASK_MAP.put(new Short(
100:                        AbstractFilter.GEOMETRY_TOUCHES), "touch");
101:                SDO_RELATE_MASK_MAP.put(new Short(
102:                        AbstractFilter.GEOMETRY_WITHIN), "inside");
103:                SDO_RELATE_MASK_MAP.put(new Short(
104:                        AbstractFilter.GEOMETRY_DISJOINT), "anyinteract");
105:
106:                //Ok, back to using these, as the not disjoint turned out to be a big
107:                //performance hit.  I would really like to see some solid testing on 
108:                //these though, as with a trivial case it really did not seem to work
109:                //right, not disjoint was giving different answers than anyinteract.
110:                SDO_RELATE_MASK_MAP.put(
111:                        new Short(AbstractFilter.GEOMETRY_BBOX), "anyinteract");
112:
113:                SDO_RELATE_MASK_MAP.put(new Short(
114:                        AbstractFilter.GEOMETRY_INTERSECTS), "anyinteract");
115:            }
116:
117:            /** The escaped version of the multiple wildcard for the REGEXP pattern. */
118:            //private String escapedWildcardMulti = "\W.\\*"; // "\\*"
119:            /** The escaped version of the single wildcard for the REGEXP pattern. */
120:            //private String escapedWildcardSingle = "\\.\\?";
121:            /**
122:             * The Spatial Reference System IDs  Keyed by ColumnName, value is Integer
123:             * SRID number
124:             */
125:            private Map srids;
126:            private String fidColumn;
127:            private String currentGeomColumnName = null;
128:            boolean inGeomFilter = false;
129:
130:            public SQLEncoderOracle(String fidColumn, int defaultSRID) {
131:                this (new HashMap());
132:                this .fidColumn = fidColumn;
133:                srids.put(null, new Integer(defaultSRID));
134:
135:                setSqlNameEscape("\"");
136:            }
137:
138:            public SQLEncoderOracle(int defaultSRID) {
139:                this (null, new HashMap());
140:                srids.put(null, new Integer(defaultSRID));
141:            }
142:
143:            /**
144:             * Creates a new SQLEncoderOracle with a specified SRID.
145:             *
146:             * @param fidColumn DOCUMENT ME!
147:             * @param srids The Spatial Reference ID to use when generating SDO SQL
148:             *        statements.
149:             */
150:            public SQLEncoderOracle(String fidColumn, Map srids) {
151:                currentGeomColumnName = null;
152:                this .fidColumn = fidColumn;
153:                this .srids = srids;
154:
155:                Set geomCols = srids.keySet();
156:
157:                if (geomCols.size() > 0) {
158:                    currentGeomColumnName = (String) geomCols.iterator().next();
159:                }
160:
161:                LOGGER.fine("SQLEncoderOracle: Geometric Column is: "
162:                        + currentGeomColumnName);
163:
164:                setSqlNameEscape("\"");
165:            }
166:
167:            /**
168:             * Creates a new SQLEncoderOracle with a specified SRID.
169:             *
170:             * @param srids The Spatial Reference ID to use when generating SDO SQL
171:             *        statements.
172:             */
173:            public SQLEncoderOracle(Map srids) {
174:                this (null, srids);
175:            }
176:
177:            /**
178:             * Sets the capabilities of this filter.
179:             *
180:             * @return FilterCapabilities for this Filter
181:             */
182:            protected FilterCapabilities createFilterCapabilities() {
183:                FilterCapabilities capabilities = new FilterCapabilities();
184:
185:                capabilities.addType(FilterCapabilities.LOGICAL);
186:                capabilities.addAll(FilterCapabilities.LOGICAL_OPENGIS);
187:                capabilities.addType(FilterCapabilities.SIMPLE_COMPARISONS);
188:                capabilities
189:                        .addAll(FilterCapabilities.SIMPLE_COMPARISONS_OPENGIS);
190:                capabilities.addType(FilterCapabilities.NULL_CHECK);
191:                capabilities.addType(PropertyIsNull.class);
192:                capabilities.addType(FilterCapabilities.BETWEEN);
193:                capabilities.addType(PropertyIsBetween.class);
194:                capabilities.addType(FilterCapabilities.FID);
195:                capabilities.addType(Id.class);
196:                capabilities.addType(FilterCapabilities.NONE);
197:                capabilities.addType(IncludeFilter.class);
198:                capabilities.addType(FilterCapabilities.ALL);
199:                capabilities.addType(ExcludeFilter.class);
200:                capabilities.addType(FilterCapabilities.LIKE);
201:                capabilities.addType(PropertyIsLike.class);
202:                capabilities.addType(FilterCapabilities.SPATIAL_BBOX);
203:                capabilities.addType(BBOX.class);
204:                capabilities.addType(FilterCapabilities.SPATIAL_CONTAINS);
205:                capabilities.addType(Contains.class);
206:                capabilities.addType(FilterCapabilities.SPATIAL_CROSSES);
207:                capabilities.addType(Crosses.class);
208:                capabilities.addType(FilterCapabilities.SPATIAL_DISJOINT);
209:                capabilities.addType(Disjoint.class);
210:                capabilities.addType(FilterCapabilities.SPATIAL_EQUALS);
211:                capabilities.addType(Equals.class);
212:                capabilities.addType(FilterCapabilities.SPATIAL_INTERSECT);
213:                capabilities.addType(Intersects.class);
214:                capabilities.addType(FilterCapabilities.SPATIAL_OVERLAPS);
215:                capabilities.addType(Overlaps.class);
216:                capabilities.addType(FilterCapabilities.SPATIAL_TOUCHES);
217:                capabilities.addType(Touches.class);
218:                capabilities.addType(FilterCapabilities.SPATIAL_WITHIN);
219:                capabilities.addType(Within.class);
220:                capabilities.addType(FilterCapabilities.SPATIAL_DWITHIN);
221:                capabilities.addType(DWithin.class);
222:                capabilities.addType(FilterCapabilities.SPATIAL_BEYOND);
223:                capabilities.addType(Beyond.class);
224:
225:                return capabilities;
226:            }
227:
228:            /**
229:             * Reverting back to just using anyinteract, as Thijs says this is a bad
230:             * performance hit
231:             * This is a special case for bbox and intersects filters, as the former
232:             * using of 'anyinteract' does not seem to be exactly a not disjoint, 
233:             * which is what is needed according to ogc specs.  
234:             *
235:             * @param geomFilter DOCUMENT ME!
236:             *
237:             * @throws IOException DOCUMENT ME!
238:             */
239:            /* private void doNotDisjointFilter(GeometryFilter geomFilter)
240:                throws IOException {
241:                //String mask = (String) SDO_RELATE_MASK_MAP.get(new Short(
242:                //            geomFilter.getFilterType()));
243:                Expression left = geomFilter.getLeftGeometry();
244:                Expression right = geomFilter.getRightGeometry();
245:
246:                if (((left != null) || (currentGeomColumnName != null))
247:                        && (right != null)) {
248:                    inGeomFilter = true;
249:                    out.write("NOT SDO_RELATE(");
250:
251:                    if (left != null) {
252:                        left.accept(this);
253:                    } else {
254:                        out.write(currentGeomColumnName);
255:                    }
256:
257:                    out.write(",");
258:                    right.accept(this);
259:                    out.write(",'mask=disjoint querytype=WINDOW') = 'TRUE' ");
260:                    inGeomFilter = false;
261:                } else {
262:                    LOGGER.warning("Invalid filter. Cannot have a Geometry filter "
263:                        + "with only one expression.");
264:                }        
265:            }*/
266:
267:            private void doSdoRelate(GeometryFilter geomFilter)
268:                    throws IOException {
269:                String mask = (String) SDO_RELATE_MASK_MAP.get(new Short(
270:                        geomFilter.getFilterType()));
271:                AttributeExpression attExpr;
272:                LiteralExpression geomExpr;
273:                Expression left = geomFilter.getLeftGeometry();
274:                Expression right = geomFilter.getRightGeometry();
275:                if (left instanceof  AttributeExpression
276:                        && right instanceof  LiteralExpression) {
277:                    attExpr = (AttributeExpression) left;
278:                    geomExpr = (LiteralExpression) right;
279:                } else if (right instanceof  AttributeExpression
280:                        && left instanceof  LiteralExpression) {
281:                    attExpr = (AttributeExpression) right;
282:                    geomExpr = (LiteralExpression) left;
283:                } else {
284:                    String err = "Oracle currently supports one geometry and one "
285:                            + "attribute expr.  You gave: "
286:                            + left
287:                            + ", "
288:                            + right;
289:                    throw new DataSourceException(err);
290:                }
291:
292:                if (((attExpr != null) || (currentGeomColumnName != null))
293:                        && (geomExpr != null) && (mask != null)) {
294:                    inGeomFilter = true;
295:                    out.write("SDO_RELATE(");
296:
297:                    if (attExpr != null) {
298:                        attExpr.accept(this );
299:                    } else {
300:                        out.write("\"" + currentGeomColumnName + "\"");
301:                    }
302:
303:                    out.write(",");
304:                    geomExpr.accept(this );
305:                    // for disjoint we ask for no interaction, anyinteract == false
306:                    if (geomFilter.getFilterType() == AbstractFilter.GEOMETRY_DISJOINT) {
307:                        out.write(",'mask=" + mask
308:                                + " querytype=WINDOW') <> 'TRUE' ");
309:                    } else {
310:                        out.write(",'mask=" + mask
311:                                + " querytype=WINDOW') = 'TRUE' ");
312:                    }
313:
314:                    inGeomFilter = false;
315:                } else {
316:                    LOGGER
317:                            .warning("Invalid filter. Cannot have a Geometry filter "
318:                                    + "with only one expression.");
319:                }
320:            }
321:
322:            /**
323:             * Performs a geometry distance filter, must be either a dwithin or a 
324:             * a beyond filter.  Uses the SDO_WITHIN_DISTANCE function, dwithin matches
325:             * for true, beyond for false.  
326:             * 
327:             * @param geomFilter the filter to use, must be a dwithin or beyond
328:             */
329:            private void doSdoDistance(GeometryDistanceFilter geomFilter)
330:                    throws IOException {
331:                //  String mask = (String) SDO_RELATE_MASK_MAP.get(new Short(
332:                //             geomFilter.getFilterType()));
333:                //TODO: don't assume left and right are correct order, see doSdoRelate
334:                Expression left = geomFilter.getLeftGeometry();
335:                Expression right = geomFilter.getRightGeometry();
336:                double distance = geomFilter.getDistance();
337:                //only dwithin and beyond, dwithin matches true for sdo_within_distance
338:                boolean isDWithin = geomFilter.getFilterType() == AbstractFilter.GEOMETRY_DWITHIN;
339:                String boolValue = isDWithin ? "TRUE" : "FALSE";
340:
341:                if ((left != null) && (right != null)) {
342:                    inGeomFilter = true;
343:                    out.write("SDO_WITHIN_DISTANCE(");
344:                    left.accept(this );
345:                    out.write(",");
346:                    right.accept(this );
347:                    out.write(",'distance=" + distance + "') = '" + boolValue
348:                            + "' ");
349:                    inGeomFilter = false;
350:                } else {
351:                    LOGGER
352:                            .warning("Invalid filter for DWithin. Cannot have a Geometry filter "
353:                                    + "with only one expression.");
354:                }
355:            }
356:
357:            /**
358:             * Converts JTS Geometry to a String version of a SDO Geometry.  This
359:             * should move to a utility class, as we now have more than  one class
360:             * using this (which is why it changed to public static)
361:             * 
362:             * TODO: Multi eometries
363:             *
364:             * @param geometry The JTS Geometry to convert.
365:             * @param srid DOCUMENT ME!
366:             *
367:             * @return A String representation of the SDO Geometry.
368:             */
369:            public static String toSDOGeom(Geometry geometry, int srid) {
370:                if (Point.class.isAssignableFrom(geometry.getClass())) {
371:                    return toSDOGeom((Point) geometry, srid);
372:                } else if (LineString.class.isAssignableFrom(geometry
373:                        .getClass())) {
374:                    return toSDOGeom((LineString) geometry, srid);
375:                } else if (Polygon.class.isAssignableFrom(geometry.getClass())) {
376:                    if (geometry.equals(geometry.getEnvelope())) {
377:                        return toSDOGeom(geometry.getEnvelopeInternal(), srid);
378:                    } else {
379:                        return toSDOGeom((Polygon) geometry, srid);
380:                    }
381:                } else if (MultiLineString.class.isAssignableFrom(geometry
382:                        .getClass())) {
383:                    return toSDOGeom((MultiLineString) geometry, srid);
384:                } else if (MultiPolygon.class.isAssignableFrom(geometry
385:                        .getClass())) {
386:                    return toSDOGeom((MultiPolygon) geometry, srid);
387:                } else {
388:                    LOGGER
389:                            .warning("Got a literal geometry that I can't handle: "
390:                                    + geometry.getClass().getName());
391:
392:                    return "";
393:                }
394:            }
395:
396:            /**
397:             * TODO: Encode more then 1
398:             * @param line
399:             * @param srid
400:             */
401:            private static String toSDOGeom(MultiLineString line, int srid) {
402:                if (line.getNumGeometries() == 1) {
403:                    return toSDOGeom(line.getGeometryN(0), srid);
404:                }
405:                throw new UnsupportedOperationException(
406:                        "Cannot encode MultiLineString (yet)");
407:            }
408:
409:            /**
410:             * TODO: Encode more then 1
411:             * @param line
412:             * @param srid
413:             */
414:            private static String toSDOGeom(MultiPolygon polygon, int srid) {
415:                if (polygon.getNumGeometries() == 1) {
416:                    return toSDOGeom(polygon.getGeometryN(0), srid);
417:                }
418:                throw new UnsupportedOperationException(
419:                        "Cannot encode MultiPolygon (yet)");
420:            }
421:
422:            /**
423:             * Converts a LineString Geometry in an SDO SQL geometry construction
424:             * statement.
425:             * 
426:             * <p>
427:             * 2D geometries is assumed. If higher dimensional geometries are used the
428:             * query will be encoded as a 2D geometry.
429:             * </p>
430:             *
431:             * @param line The line to encode.
432:             * @param srid DOCUMENT ME!
433:             *
434:             * @return An SDO SQL geometry object construction statement
435:             */
436:            private static String toSDOGeom(LineString line, int srid) {
437:                if (SDO.D(line) > 2) {
438:                    LOGGER
439:                            .warning(""
440:                                    + SDO.D(line)
441:                                    + " dimensioned geometry provided."
442:                                    + " This encoder only supports 2D geometries. The query will be constructed as"
443:                                    + " a 2D query.");
444:                }
445:
446:                StringBuffer buffer = new StringBuffer("MDSYS.SDO_GEOMETRY(");
447:
448:                buffer.append(SDO.D(line));
449:                buffer.append("002,");
450:
451:                if (srid > 0) {
452:                    LOGGER.fine("Using layer SRID: " + srid);
453:                    buffer.append(srid);
454:                } else {
455:                    LOGGER.fine("Using NULL SRID: ");
456:                    buffer.append("NULL");
457:                }
458:
459:                buffer.append(",NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,2,1),");
460:                buffer.append("MDSYS.SDO_ORDINATE_ARRAY(");
461:
462:                Coordinate[] coordinates = line.getCoordinates();
463:
464:                for (int i = 0; i < coordinates.length; i++) {
465:                    buffer.append(coordinates[i].x);
466:                    buffer.append(",");
467:                    buffer.append(coordinates[i].y);
468:
469:                    if (i != (coordinates.length - 1)) {
470:                        buffer.append(",");
471:                    }
472:                }
473:
474:                buffer.append("))");
475:
476:                return buffer.toString();
477:            }
478:
479:            /**
480:             * Converts a Point Geometry in an SDO SQL geometry construction statement.
481:             * 
482:             * <p>
483:             * 2D geometries is assumed. If higher dimensional geometries are used the
484:             * query will be encoded as a 2D geometry.
485:             * </p>
486:             *
487:             * @param point The point to encode.
488:             * @param srid DOCUMENT ME!
489:             *
490:             * @return An SDO SQL geometry object construction statement
491:             */
492:            private static String toSDOGeom(Point point, int srid) {
493:                if (SDO.D(point) > 2) {
494:                    LOGGER
495:                            .warning(""
496:                                    + SDO.D(point)
497:                                    + " dimensioned geometry provided."
498:                                    + " This encoder only supports 2D geometries. The query will be constructed as"
499:                                    + " a 2D query.");
500:                }
501:
502:                StringBuffer buffer = new StringBuffer("MDSYS.SDO_GEOMETRY(");
503:
504:                buffer.append(SDO.D(point));
505:                buffer.append("001,");
506:
507:                if (srid > 0) {
508:                    LOGGER.fine("Using layer SRID: " + srid);
509:                    buffer.append(srid);
510:                } else {
511:                    LOGGER.fine("Using NULL SRID: ");
512:                    buffer.append("NULL");
513:                }
514:
515:                buffer.append(",MDSYS.SDO_POINT_TYPE(");
516:                buffer.append(point.getX());
517:                buffer.append(",");
518:                buffer.append(point.getY());
519:                buffer.append(",NULL),NULL,NULL)");
520:
521:                return buffer.toString();
522:            }
523:
524:            /**
525:             * Converts a Polygon Geometry in an SDO SQL geometry construction
526:             * statement.
527:             * 
528:             * <p>
529:             * 2D geometries is assumed. If higher dimensional geometries are used the
530:             * query will be encoded as a 2D geometry.
531:             * </p>
532:             *
533:             * @param polygon The polygon to encode.
534:             * @param srid DOCUMENT ME!
535:             *
536:             * @return An SDO SQL geometry object construction statement
537:             */
538:            private static String toSDOGeom(Polygon polygon, int srid) {
539:                StringBuffer buffer = new StringBuffer();
540:
541:                if (SDO.D(polygon) > 2) {
542:                    LOGGER
543:                            .warning(""
544:                                    + SDO.D(polygon)
545:                                    + " dimensioned geometry provided."
546:                                    + " This encoder only supports 2D geometries. The query will be constructed as"
547:                                    + " a 2D query.");
548:                }
549:
550:                if (polygon.getExteriorRing() != null) {
551:                    buffer.append("MDSYS.SDO_GEOMETRY(");
552:                    buffer.append(SDO.D(polygon));
553:                    buffer.append("003,");
554:
555:                    if (srid > 0) {
556:                        LOGGER.fine("Using layer SRID: " + srid);
557:                        buffer.append(srid);
558:                    } else {
559:                        LOGGER.fine("Using NULL SRID: ");
560:                        buffer.append("NULL");
561:                    }
562:
563:                    buffer.append(",NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,1),");
564:                    buffer.append("MDSYS.SDO_ORDINATE_ARRAY(");
565:
566:                    CoordinateSequenceFactory fact = polygon.getFactory()
567:                            .getCoordinateSequenceFactory();
568:                    CoordinateSequence exterior = polygon.getExteriorRing()
569:                            .getCoordinateSequence();
570:                    CoordinateSequence coordSeq = SDO.counterClockWise(fact,
571:                            exterior);
572:
573:                    for (int i = 0, size = coordSeq.size(); i < size; i++) {
574:                        Coordinate cur = coordSeq.getCoordinate(i);
575:                        buffer.append(cur.x);
576:                        buffer.append(",");
577:                        buffer.append(cur.y);
578:
579:                        if (i != (size - 1)) {
580:                            buffer.append(",");
581:                        }
582:                    }
583:
584:                    /* This could be expensive if coordSeq implementation is not an
585:                       an array.  Leaving in for now as I can't test, and this is
586:                       more likely to work right.
587:                        Coordinate[] coordinates = coordSeq.toCoordinateArray();
588:                        for (int i = 0; i < coordinates.length; i++) {
589:                            buffer.append(coordinates[i].x);
590:                            buffer.append(",");
591:                            buffer.append(coordinates[i].y);
592:
593:                            if (i != (coordinates.length - 1)) {
594:                                buffer.append(",");
595:                            }
596:                    }*/
597:
598:                    buffer.append("))");
599:                } else {
600:                    LOGGER
601:                            .warning("No Exterior ring on polygon.  "
602:                                    + "This encode only supports Polygons with exterior rings.");
603:                }
604:
605:                if (polygon.getNumInteriorRing() > 0) {
606:                    LOGGER.warning("Polygon contains Interior Rings. "
607:                            + "These rings will not be included in the query.");
608:                }
609:
610:                return buffer.toString();
611:            }
612:
613:            /**
614:             * Converts an Envelope in an SDO SQL geometry construction statement.
615:             *
616:             * @param envelope The envelope to encode.
617:             * @param srid DOCUMENT ME!
618:             *
619:             * @return An SDO SQL geometry object construction statement
620:             */
621:            private static String toSDOGeom(Envelope envelope, int srid) {
622:                StringBuffer buffer = new StringBuffer();
623:                buffer.append("MDSYS.SDO_GEOMETRY(");
624:                buffer.append("2003,");
625:
626:                if (srid > 0) {
627:                    LOGGER.fine("Using layer SRID: " + srid);
628:                    buffer.append(srid);
629:                } else {
630:                    LOGGER.fine("Using NULL SRID: ");
631:                    buffer.append("NULL");
632:                }
633:
634:                buffer.append(",NULL,MDSYS.SDO_ELEM_INFO_ARRAY(1,1003,3),");
635:                buffer.append("MDSYS.SDO_ORDINATE_ARRAY(");
636:                buffer.append(envelope.getMinX());
637:                buffer.append(",");
638:                buffer.append(envelope.getMinY());
639:                buffer.append(",");
640:                buffer.append(envelope.getMaxX());
641:                buffer.append(",");
642:                buffer.append(envelope.getMaxY());
643:                buffer.append("))");
644:
645:                return buffer.toString();
646:            }
647:
648:            /**
649:             * Handles Geometry Filter encoding. Currently only supports the encoding
650:             * of GEOMETRY_BBOX filters. If a GEOMETRY_BBOX filter is encounter it
651:             * will be converted into an SDO_RELATE() function. If another filter is
652:             * found, nothing will happen.
653:             *
654:             * @param geomFilter The geometry filter to encode.
655:             *
656:             * @see org.geotools.filter.FilterVisitor#visit(org.geotools.filter.GeometryFilter)
657:             */
658:            public void visit(GeometryFilter geomFilter) {
659:                LOGGER.finer("Visiting a Geometry filter");
660:
661:                try {
662:                    short filterType = geomFilter.getFilterType();
663:                    if ((filterType == AbstractFilter.GEOMETRY_DWITHIN)
664:                            || (filterType == AbstractFilter.GEOMETRY_BEYOND)) {
665:                        doSdoDistance((GeometryDistanceFilter) geomFilter);
666:                        //} else if (filterType == AbstractFilter.GEOMETRY_INTERSECTS
667:                        //|| filterType == AbstractFilter.GEOMETRY_BBOX) {
668:                        //doNotDisjointFilter(geomFilter);
669:                    } else if (SDO_RELATE_MASK_MAP.get(new Short(geomFilter
670:                            .getFilterType())) != null) {
671:                        doSdoRelate(geomFilter);
672:                    } else {
673:                        LOGGER.warning("Unknown filter type: "
674:                                + geomFilter.getFilterType());
675:                    }
676:                } catch (IOException e) {
677:                    LOGGER.warning("IO Error exporting geometry filter");
678:                }
679:            }
680:
681:            /**
682:             * Writes the SQL for the Like Filter.  Assumes the current java
683:             * implemented wildcards for the Like Filter: . for multi and .? for
684:             * single. And replaces them with the SQL % and _, respectively. Currently
685:             * does nothing, and should not be called, not included in the
686:             * capabilities.
687:             *
688:             * @param filter the Like Filter to be visited.
689:             *
690:             * @task TODO: LikeFilter doesn't work right...revisit this when it does.
691:             *       Need to think through the escape char, so it works right when
692:             *       Java uses one, and escapes correctly with an '_'.
693:             */
694:            public void visit(LikeFilter filter) {
695:                try {
696:                    String pattern = filter.getPattern();
697:
698:                    String multi = "\\Q" + filter.getWildcardMulti() + "\\E";
699:                    pattern = pattern.replaceAll(multi, SQL_WILD_MULTI);
700:
701:                    String single = "\\Q" + filter.getWildcardSingle() + "\\E";
702:                    pattern = pattern.replaceAll(single, SQL_WILD_SINGLE);
703:
704:                    //pattern = pattern.replace('\\', ''); //get rid of java escapes.
705:                    out.write("UPPER(");
706:                    ((Expression) filter.getValue()).accept(this );
707:                    out.write(") LIKE ");
708:                    out.write("UPPER('" + pattern + "')");
709:
710:                    String esc = filter.getEscape();
711:
712:                    if (pattern.indexOf(esc) != -1) { //if it uses the escape char
713:                        out.write(" ESCAPE " + "'" + esc + "'"); //this needs testing
714:                    }
715:
716:                    //TODO figure out when to add ESCAPE clause, probably just for the
717:                    // '_' char.
718:                } catch (java.io.IOException ioe) {
719:                    LOGGER.warning("Unable to export filter" + ioe);
720:                }
721:            }
722:
723:            /**
724:             * Converts a literal expression into a valid SDO object. Only handles
725:             * Literal Geometries, all other literals are passed up to the parent.
726:             *
727:             * @param literal The Literal expression to encode.
728:             *
729:             * @see org.geotools.filter.FilterVisitor#visit(org.geotools.filter.LiteralExpression)
730:             */
731:            public void visit(LiteralExpression literal) {
732:                if (literal.getType() == DefaultExpression.LITERAL_GEOMETRY) {
733:                    Geometry geometry = (Geometry) literal.getLiteral();
734:
735:                    try {
736:                        int srid = -1;
737:                        Integer sridO = (Integer) srids
738:                                .get(currentGeomColumnName);
739:
740:                        if (sridO == null) {
741:                            // try for default
742:                            sridO = (Integer) srids.get(null);
743:                        }
744:
745:                        if (sridO != null) {
746:                            srid = sridO.intValue();
747:                        }
748:
749:                        out.write(toSDOGeom(geometry, srid));
750:                    } catch (IOException e) {
751:                        LOGGER.warning("IO Error exporting Literal Geometry");
752:                    }
753:                } else {
754:                    // can't do it, send it off to the parent
755:                    super .visit(literal);
756:                }
757:            }
758:
759:            /**
760:             * DOCUMENT ME!
761:             *
762:             * @param filter
763:             *
764:             * @see org.geotools.filter.SQLEncoder#visit(org.geotools.filter.FidFilter)
765:             */
766:            public void visit(FidFilter filter) {
767:                if (fidColumn != null) {
768:                    String[] fids = filter.getFids();
769:                    LOGGER.finer("Exporting FID=" + Arrays.asList(fids));
770:
771:                    for (int i = 0; i < fids.length; i++) {
772:                        try {
773:                            out.write(fidColumn);
774:                            out.write(" = '");
775:
776:                            int pos;
777:
778:                            if ((pos = fids[i].indexOf('.')) != -1) {
779:                                out.write(fids[i].substring(pos + 1));
780:                            } else {
781:                                out.write(fids[i]);
782:                            }
783:
784:                            out.write("'");
785:
786:                            if (i < (fids.length - 1)) {
787:                                out.write(" OR ");
788:                            }
789:                        } catch (IOException e) {
790:                            LOGGER.warning("IO Error exporting FID Filter.");
791:                        }
792:                    }
793:                } else {
794:                    super .visit(filter);
795:                }
796:            }
797:
798:            /*
799:             * (non-Javadoc)
800:             *
801:             * @see org.geotools.filter.SQLEncoder#visit(org.geotools.filter.AttributeExpression)
802:             */
803:            public void visit(AttributeExpression ae) throws RuntimeException {
804:                super.visit(ae);
805:
806:                if (inGeomFilter) {
807:                    currentGeomColumnName = ae.getAttributePath();
808:                }
809:            }
810:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.