Source Code Cross Referenced for SQLEncoder.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) 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;
009:         *    version 2.1 of the License.
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.io.StringWriter;
020:        import java.io.Writer;
021:        import java.util.Arrays;
022:        import java.util.HashMap;
023:        import java.util.Map;
024:        import java.util.logging.Logger;
025:
026:        import org.geotools.data.jdbc.fidmapper.FIDMapper;
027:        import org.geotools.feature.AttributeType;
028:        import org.geotools.feature.FeatureType;
029:        import org.geotools.util.Converters;
030:        import org.opengis.filter.ExcludeFilter;
031:        import org.opengis.filter.IncludeFilter;
032:
033:        import com.vividsolutions.jts.geom.Geometry;
034:
035:        /**
036:         * Encodes a filter into a SQL WHERE statement.  It should hopefully be generic
037:         * enough that any SQL database will work with it, though it has only been
038:         * tested with MySQL and Postgis.  This generic SQL encoder should eventually
039:         * be able to encode all filters except Geometry Filters (currently
040:         * LikeFilters are not yet fully implemented, but when they are they should be
041:         * generic enough). This is because the OGC's SFS for SQL document specifies
042:         * two ways of doing SQL databases, one with native geometry types and one
043:         * without.  To implement an encoder for one of the two types simply subclass
044:         * off of this encoder and put in the proper GeometryFilter visit method. Then
045:         * add the filter types supported to the capabilities in the static
046:         * capabilities.addType block.
047:         *
048:         * @author Chris Holmes, TOPP
049:         * 
050:         * @deprecated Please use org.geotools.data.jdbc.FilterToSQL which uses
051:         * opengis filters instead of these geotools filters.
052:         *
053:         * @task TODO: Implement LikeFilter encoding, need to figure out escape chars,
054:         *       the rest of the code should work right.  Once fixed be sure to add
055:         *       the LIKE type to capabilities, so others know that they can be
056:         *       encoded.
057:         * @task REVISIT: need to figure out exceptions, we're currently eating io
058:         *       errors, which is bad. Probably need a generic visitor exception.
059:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/jdbc/src/main/java/org/geotools/filter/SQLEncoder.java $
060:         */
061:        public class SQLEncoder implements  org.geotools.filter.FilterVisitor2 {
062:            /** error message for exceptions */
063:            protected static final String IO_ERROR = "io problem writing filter";
064:
065:            /** The filter types that this class can encode */
066:            protected FilterCapabilities capabilities = null;
067:
068:            /** Standard java logger */
069:            private static Logger LOGGER = org.geotools.util.logging.Logging
070:                    .getLogger("org.geotools.filter");
071:
072:            /** Map of comparison types to sql representation */
073:            protected static Map comparisions = new HashMap();
074:
075:            /** Map of spatial types to sql representation */
076:            private static Map spatial = new HashMap();
077:
078:            /** Map of logical types to sql representation */
079:            private static Map logical = new HashMap();
080:
081:            /** Map of expression types to sql representation */
082:            private static Map expressions = new HashMap();
083:
084:            static {
085:                comparisions.put(new Integer(AbstractFilter.COMPARE_EQUALS),
086:                        "=");
087:                comparisions.put(
088:                        new Integer(AbstractFilter.COMPARE_NOT_EQUALS), "!=");
089:                comparisions.put(new Integer(
090:                        AbstractFilter.COMPARE_GREATER_THAN), ">");
091:                comparisions.put(new Integer(
092:                        AbstractFilter.COMPARE_GREATER_THAN_EQUAL), ">=");
093:                comparisions.put(new Integer(AbstractFilter.COMPARE_LESS_THAN),
094:                        "<");
095:                comparisions.put(new Integer(
096:                        AbstractFilter.COMPARE_LESS_THAN_EQUAL), "<=");
097:                comparisions.put(new Integer(AbstractFilter.LIKE), "LIKE");
098:                comparisions.put(new Integer(AbstractFilter.NULL), "IS NULL");
099:                comparisions
100:                        .put(new Integer(AbstractFilter.BETWEEN), "BETWEEN");
101:
102:                expressions.put(new Integer(DefaultExpression.MATH_ADD), "+");
103:                expressions
104:                        .put(new Integer(DefaultExpression.MATH_DIVIDE), "/");
105:                expressions.put(new Integer(DefaultExpression.MATH_MULTIPLY),
106:                        "*");
107:                expressions.put(new Integer(DefaultExpression.MATH_SUBTRACT),
108:                        "-");
109:
110:                //more to come?
111:                spatial.put(new Integer(AbstractFilter.GEOMETRY_EQUALS),
112:                        "Equals");
113:                spatial.put(new Integer(AbstractFilter.GEOMETRY_DISJOINT),
114:                        "Disjoint");
115:                spatial.put(new Integer(AbstractFilter.GEOMETRY_INTERSECTS),
116:                        "Intersects");
117:                spatial.put(new Integer(AbstractFilter.GEOMETRY_TOUCHES),
118:                        "Touches");
119:                spatial.put(new Integer(AbstractFilter.GEOMETRY_CROSSES),
120:                        "Crosses");
121:                spatial.put(new Integer(AbstractFilter.GEOMETRY_WITHIN),
122:                        "Within");
123:                spatial.put(new Integer(AbstractFilter.GEOMETRY_CONTAINS),
124:                        "Contains");
125:                spatial.put(new Integer(AbstractFilter.GEOMETRY_OVERLAPS),
126:                        "Overlaps");
127:                spatial.put(new Integer(AbstractFilter.GEOMETRY_BEYOND),
128:                        "Beyond");
129:                spatial.put(new Integer(AbstractFilter.GEOMETRY_BBOX), "BBOX");
130:
131:                logical.put(new Integer(AbstractFilter.LOGIC_AND), "AND");
132:                logical.put(new Integer(AbstractFilter.LOGIC_OR), "OR");
133:                logical.put(new Integer(AbstractFilter.LOGIC_NOT), "NOT");
134:            }
135:
136:            //use these when Like is implemented.
137:            //The standard SQL multicharacter wild card. 
138:            //private static String SQL_WILD_MULTI = "%";
139:            //The standard SQL single character wild card.
140:            //private static String SQL_WILD_SINGLE = "_";
141:            // The escaped version of the single wildcard for the REGEXP pattern. 
142:            //private static String escapedWildcardSingle = "\\.\\?";
143:            // The escaped version of the multiple wildcard for the REGEXP pattern. 
144:            //private static String escapedWildcardMulti = "\\.\\*";
145:
146:            /** Character used to escape database schema, table and column names */
147:            private String sqlNameEscape = "";
148:
149:            /** where to write the constructed string from visiting the filters. */
150:            protected Writer out;
151:
152:            /** the fid mapper used to encode the fid filters */
153:            protected FIDMapper mapper;
154:
155:            /** the schmema the encoder will be used to be encode sql for */
156:            protected FeatureType featureType;
157:
158:            /** 
159:             * A type to use as context when encoding literal.
160:             * NOTE: when we move to geoapi filter visitor api, this will not be needed.
161:             */
162:            protected Class context = null;
163:
164:            /**
165:             * Empty constructor
166:             */
167:            public SQLEncoder() {
168:            }
169:
170:            /**
171:             * Sets the featuretype the encoder is encoding sql for.
172:             * <p>
173:             * This is used for context for attribute expressions when encoding to sql. 
174:             * </p>
175:             * 
176:             * @param featureType
177:             */
178:            public void setFeatureType(FeatureType featureType) {
179:                this .featureType = featureType;
180:            }
181:
182:            /**
183:             * Convenience constructor to perform the whole encoding process at once.
184:             *
185:             * @param out the writer to encode the SQL to.
186:             * @param filter the Filter to be encoded.
187:             *
188:             * @throws SQLEncoderException If there were problems encoding
189:             */
190:            public SQLEncoder(Writer out, Filter filter)
191:                    throws SQLEncoderException {
192:                if (getCapabilities().fullySupports(filter)) {
193:                    this .out = out;
194:
195:                    try {
196:                        out.write("WHERE ");
197:                        filter.accept(this );
198:
199:                        //out.write(";"); this should probably be added by client.
200:                    } catch (java.io.IOException ioe) {
201:                        throw new SQLEncoderException(
202:                                "Problem writing filter: ", ioe);
203:                    }
204:                } else {
205:                    throw new SQLEncoderException("Filter type not supported");
206:                }
207:            }
208:
209:            /**
210:             * Sets the FIDMapper that will be used in subsequente visit calls. There
211:             * must be a FIDMapper in order to invoke the FIDFilter encoder.
212:             *
213:             * @param mapper
214:             */
215:            public void setFIDMapper(FIDMapper mapper) {
216:                this .mapper = mapper;
217:            }
218:
219:            /**
220:             * Sets the capabilities of this filter.
221:             *
222:             * @return FilterCapabilities for this Filter
223:             */
224:            protected FilterCapabilities createFilterCapabilities() {
225:                FilterCapabilities capabilities = new FilterCapabilities();
226:
227:                capabilities.addType(FilterCapabilities.LOGICAL);
228:                capabilities.addType(FilterCapabilities.SIMPLE_COMPARISONS);
229:                capabilities.addType(FilterCapabilities.NULL_CHECK);
230:                capabilities.addType(FilterCapabilities.BETWEEN);
231:                capabilities.addType(FilterCapabilities.FID);
232:                capabilities.addType(FilterCapabilities.NONE);
233:                capabilities.addType(FilterCapabilities.ALL);
234:
235:                return capabilities;
236:            }
237:
238:            /**
239:             * Performs the encoding, sends the encoded sql to the writer passed in.
240:             *
241:             * @param out the writer to encode the SQL to.
242:             * @param filter the Filter to be encoded.
243:             *
244:             * @throws SQLEncoderException If filter type not supported, or if there
245:             *         were io problems.
246:             */
247:            public void encode(Writer out, org.opengis.filter.Filter filter)
248:                    throws SQLEncoderException {
249:                if (getCapabilities().fullySupports(filter)) {
250:                    this .out = out;
251:
252:                    try {
253:                        out.write("WHERE ");
254:                        Filters.accept(filter, this );
255:
256:                        //out.write(";");
257:                    } catch (java.io.IOException ioe) {
258:                        LOGGER.warning("Unable to export filter" + ioe);
259:                        throw new SQLEncoderException(
260:                                "Problem writing filter: ", ioe);
261:                    }
262:                } else {
263:                    throw new SQLEncoderException("Filter type not supported");
264:                }
265:            }
266:
267:            /**
268:             * Performs the encoding, returns a string of the encoded SQL.
269:             *
270:             * @param filter the Filter to be encoded.
271:             *
272:             * @return the string of the SQL where statement.
273:             *
274:             * @throws SQLEncoderException If filter type not supported, or if there
275:             *         were io problems.
276:             */
277:            public String encode(org.opengis.filter.Filter filter)
278:                    throws SQLEncoderException {
279:                StringWriter output = new StringWriter();
280:                encode(output, filter);
281:
282:                return output.getBuffer().toString();
283:            }
284:
285:            /**
286:             * Describes the capabilities of this encoder.
287:             * 
288:             * <p>
289:             * Performs lazy creation of capabilities.
290:             * </p>
291:             *
292:             * @return The capabilities supported by this encoder.
293:             */
294:            public synchronized FilterCapabilities getCapabilities() {
295:                if (capabilities == null) {
296:                    capabilities = createFilterCapabilities();
297:                }
298:
299:                return capabilities; //maybe clone?  Make immutable somehow
300:            }
301:
302:            /**
303:             * This should never be called. This can only happen if a subclass of
304:             * AbstractFilter failes to implement its own version of
305:             * accept(FilterVisitor);
306:             *
307:             * @param filter The filter to visit
308:             *
309:             * @throws RuntimeException for IO Encoding problems.
310:             *
311:             * @task REVISIT: I don't think Filter.INCLUDE and Filter.EXCLUDE should be
312:             *       handled here.  They should have their own methods, but they don't
313:             *       have interfaces, so I don't know if that's possible.
314:             */
315:            public void visit(Filter filter) {
316:                try {
317:                    if (filter.getFilterType() == FilterType.NONE) {
318:                        out.write("TRUE");
319:                    } else if (filter.getFilterType() == FilterType.ALL) {
320:                        out.write("FALSE");
321:                    } else {
322:                        LOGGER.warning("exporting unknown filter type:"
323:                                + filter.toString());
324:
325:                        //throw new RuntimeException("Do not know how to export filter:"+filter.toString() );
326:                    }
327:                } catch (java.io.IOException ioe) {
328:                    throw new RuntimeException(IO_ERROR, ioe);
329:                }
330:            }
331:
332:            /**
333:             * Writes the SQL for the Between Filter.
334:             *
335:             * @param filter the  Filter to be visited.
336:             *
337:             * @throws RuntimeException for io exception with writer
338:             */
339:            public void visit(BetweenFilter filter) throws RuntimeException {
340:                LOGGER.finer("exporting BetweenFilter");
341:
342:                DefaultExpression left = (DefaultExpression) filter
343:                        .getLeftValue();
344:                DefaultExpression right = (DefaultExpression) filter
345:                        .getRightValue();
346:                DefaultExpression mid = (DefaultExpression) filter
347:                        .getMiddleValue();
348:                LOGGER.finer("Filter type id is " + filter.getFilterType());
349:                LOGGER
350:                        .finer("Filter type text is "
351:                                + comparisions.get(new Integer(filter
352:                                        .getFilterType())));
353:
354:                try {
355:                    mid.accept(this );
356:                    out.write(" BETWEEN ");
357:                    left.accept(this );
358:                    out.write(" AND ");
359:                    right.accept(this );
360:                } catch (java.io.IOException ioe) {
361:                    throw new RuntimeException(IO_ERROR, ioe);
362:                }
363:            }
364:
365:            /**
366:             * Writes the SQL for the Like Filter.  Assumes the current java
367:             * implemented wildcards for the Like Filter: . for multi and .? for
368:             * single. And replaces them with the SQL % and _, respectively. Currently
369:             * does nothing, and should not be called, not included in the
370:             * capabilities.
371:             *
372:             * @param filter the Like Filter to be visited.
373:             *
374:             * @throws UnsupportedOperationException always, as likes aren't
375:             *         implemented yet.
376:             *
377:             * @task REVISIT: Need to think through the escape char, so it works  right
378:             *       when Java uses one, and escapes correctly with an '_'.
379:             */
380:            public void visit(LikeFilter filter)
381:                    throws UnsupportedOperationException {
382:                char esc = filter.getEscape().charAt(0);
383:                char multi = filter.getWildcardMulti().charAt(0);
384:                char single = filter.getWildcardSingle().charAt(0);
385:                String pattern = LikeFilterImpl.convertToSQL92(esc, multi,
386:                        single, filter.getPattern());
387:
388:                DefaultExpression att = (DefaultExpression) filter.getValue();
389:
390:                try {
391:                    att.accept(this );
392:                    out.write(" LIKE '");
393:                    out.write(pattern);
394:                    out.write("' ");
395:                } catch (java.io.IOException ioe) {
396:                    throw new RuntimeException(IO_ERROR, ioe);
397:                }
398:            }
399:
400:            /**
401:             * Writes the SQL for the Logic Filter.
402:             *
403:             * @param filter the logic statement to be turned into SQL.
404:             *
405:             * @throws RuntimeException for io exception with writer
406:             */
407:            public void visit(LogicFilter filter) throws RuntimeException {
408:                LOGGER.finer("exporting LogicFilter");
409:
410:                filter.getFilterType();
411:
412:                String type = (String) logical.get(new Integer(filter
413:                        .getFilterType()));
414:
415:                try {
416:                    java.util.Iterator list = filter.getFilterIterator();
417:
418:                    if (filter.getFilterType() == AbstractFilter.LOGIC_NOT) {
419:                        out.write(" NOT (");
420:                        Filters.accept((org.opengis.filter.Filter) list.next(),
421:                                this );
422:
423:                        out.write(")");
424:                    } else { //AND or OR
425:                        out.write("(");
426:
427:                        while (list.hasNext()) {
428:                            Filters.accept((org.opengis.filter.Filter) list
429:                                    .next(), this );
430:
431:                            if (list.hasNext()) {
432:                                out.write(" " + type + " ");
433:                            }
434:                        }
435:
436:                        out.write(")");
437:                    }
438:                } catch (java.io.IOException ioe) {
439:                    throw new RuntimeException(IO_ERROR, ioe);
440:                }
441:            }
442:
443:            /**
444:             * Writes the SQL for a Compare Filter.
445:             *  
446:             *  DJB: note, postgis overwrites this implementation because of the way
447:             *       null is handled.  This is for <PropertyIsNull> filters and <PropertyIsEqual> filters
448:             *       are handled.  They will come here with "property = null".  
449:             *       NOTE: 
450:             *        SELECT * FROM <table> WHERE <column> isnull;  -- postgresql
451:             *        SELECT * FROM <table> WHERE isnull(<column>); -- oracle???
452:             *
453:             * @param filter the comparison to be turned into SQL.
454:             *
455:             * @throws RuntimeException for io exception with writer
456:             */
457:            public void visit(CompareFilter filter) throws RuntimeException {
458:                LOGGER.finer("exporting SQL ComparisonFilter");
459:
460:                DefaultExpression left = (DefaultExpression) filter
461:                        .getLeftValue();
462:                DefaultExpression right = (DefaultExpression) filter
463:                        .getRightValue();
464:                LOGGER.finer("Filter type id is " + filter.getFilterType());
465:                LOGGER
466:                        .finer("Filter type text is "
467:                                + comparisions.get(new Integer(filter
468:                                        .getFilterType())));
469:
470:                String type = (String) comparisions.get(new Integer(filter
471:                        .getFilterType()));
472:
473:                try {
474:                    left.accept(this );
475:                    out.write(" " + type + " ");
476:                    right.accept(this );
477:                } catch (java.io.IOException ioe) {
478:                    throw new RuntimeException(IO_ERROR, ioe);
479:                }
480:            }
481:
482:            /**
483:             * Writes the SQL for the Null Filter.
484:             *
485:             * @param filter the null filter to be written to SQL.
486:             *
487:             * @throws RuntimeException for io exception with writer
488:             */
489:            public void visit(NullFilter filter) throws RuntimeException {
490:                LOGGER.finer("exporting NullFilter");
491:
492:                DefaultExpression expr = (DefaultExpression) filter
493:                        .getNullCheckValue();
494:
495:                //String type = (String) comparisions.get(new Integer(
496:                //          filter.getFilterType()));
497:                try {
498:                    expr.accept(this );
499:                    out.write(" IS NULL ");
500:                } catch (java.io.IOException ioe) {
501:                    throw new RuntimeException(IO_ERROR, ioe);
502:                }
503:            }
504:
505:            /**
506:             * Encodes an FidFilter.
507:             *
508:             * @param filter
509:             *
510:             * @throws RuntimeException DOCUMENT ME!
511:             *
512:             * @see org.geotools.filter.SQLEncoder#visit(org.geotools.filter.FidFilter)
513:             */
514:            public void visit(FidFilter filter) {
515:                if (mapper == null) {
516:                    throw new RuntimeException(
517:                            "Must set a fid mapper before trying to encode FIDFilters");
518:                }
519:
520:                String[] fids = filter.getFids();
521:                LOGGER.finer("Exporting FID=" + Arrays.asList(fids));
522:
523:                // prepare column name array
524:                String[] colNames = new String[mapper.getColumnCount()];
525:
526:                for (int i = 0; i < colNames.length; i++) {
527:                    colNames[i] = mapper.getColumnName(i);
528:                }
529:
530:                for (int i = 0; i < fids.length; i++) {
531:                    try {
532:                        Object[] attValues = mapper.getPKAttributes(fids[i]);
533:
534:                        out.write("(");
535:
536:                        for (int j = 0; j < attValues.length; j++) {
537:                            out.write(escapeName(colNames[j]));
538:                            out.write(" = '");
539:                            out.write(attValues[j].toString()); //DJB: changed this to attValues[j] from attValues[i].
540:                            out.write("'");
541:
542:                            if (j < (attValues.length - 1)) {
543:                                out.write(" AND ");
544:                            }
545:                        }
546:
547:                        out.write(")");
548:
549:                        if (i < (fids.length - 1)) {
550:                            out.write(" OR ");
551:                        }
552:                    } catch (java.io.IOException e) {
553:                        throw new RuntimeException(IO_ERROR, e);
554:                    }
555:                }
556:            }
557:
558:            /**
559:             * Writes the SQL for the attribute Expression.
560:             *
561:             * @param expression the attribute to turn to SQL.
562:             *
563:             * @throws RuntimeException for io exception with writer
564:             */
565:            public void visit(AttributeExpression expression)
566:                    throws RuntimeException {
567:                LOGGER.finer("exporting ExpressionAttribute");
568:
569:                try {
570:                    //JD: evaluate the expression agains the feature type to get at the attribute, then 
571:                    // encode the namee
572:                    context = null;
573:                    if (featureType != null) {
574:                        AttributeType attributeType = (AttributeType) expression
575:                                .evaluate(featureType);
576:                        if (attributeType != null) {
577:                            out.write(escapeName(attributeType.getName()));
578:
579:                            //provide context for a literal being compared to this attribute
580:                            context = attributeType.getType();
581:                            return;
582:                        }
583:                    }
584:
585:                    //if thigns are sane, we should get here
586:                    out.write(escapeName(expression.getAttributePath()));
587:
588:                } catch (java.io.IOException ioe) {
589:                    throw new RuntimeException(
590:                            "IO problems writing attribute exp", ioe);
591:                }
592:            }
593:
594:            /**
595:             * Writes the SQL for the attribute Expression.
596:             *
597:             * @param expression the attribute to turn to SQL.
598:             */
599:            public void visit(Expression expression) {
600:                LOGGER.warning("exporting unknown (default) expression");
601:            }
602:
603:            /**
604:             * Export the contents of a Literal Expresion
605:             *
606:             * @param expression the Literal to export
607:             *
608:             * @throws RuntimeException for io exception with writer
609:             */
610:            public void visit(LiteralExpression expression)
611:                    throws RuntimeException {
612:                LOGGER.finer("exporting LiteralExpression");
613:
614:                //type to convert the literal to
615:                Class target = null;
616:
617:                if (context != null) {
618:                    //first try to evaluate the expression in the context of a type
619:                    target = (Class) context;
620:                }
621:
622:                if (target == null) {
623:                    //next try and use the filter code
624:                    short type = expression.getType();
625:
626:                    switch (type) {
627:                    case Expression.LITERAL_DOUBLE:
628:                        target = Double.class;
629:                        break;
630:                    case Expression.LITERAL_INTEGER:
631:                        target = Integer.class;
632:                        break;
633:                    case Expression.LITERAL_LONG:
634:                        target = Long.class;
635:                        break;
636:                    case Expression.LITERAL_STRING:
637:                        target = String.class;
638:                        break;
639:                    case Expression.LITERAL_GEOMETRY:
640:                        target = Geometry.class;
641:                        break;
642:                    default:
643:                        throw new RuntimeException("type: " + type
644:                                + "not supported");
645:                    }
646:                }
647:
648:                try {
649:                    if (target == Geometry.class
650:                            && expression.getLiteral() instanceof  Geometry) {
651:                        //call this method for backwards compatability with subclasses
652:                        visitLiteralGeometry(expression);
653:                        return;
654:                    } else {
655:                        //convert the literal to the required type
656:                        //JD except for numerics, let the database do teh converstion
657:                        Object literal = null;
658:                        if (Number.class.isAssignableFrom(target)) {
659:                            //dont convert
660:                        } else {
661:                            //convert
662:                            literal = expression.evaluate(null, target);
663:                        }
664:
665:                        if (literal == null) {
666:                            //just use string
667:                            literal = expression.getLiteral().toString();
668:                        }
669:
670:                        //geometry hook
671:                        //if ( literal instanceof Geometry ) {
672:                        if (Geometry.class.isAssignableFrom(target)) {
673:                            visitLiteralGeometry(expression);
674:                        }
675:                        //else if ( literal instanceof Number ) {
676:                        else if (Number.class.isAssignableFrom(target)) {
677:                            out.write(literal.toString());
678:                        }
679:                        //else if ( literal instanceof String ) {
680:                        else if (String.class.isAssignableFrom(target)) {
681:                            // sigle quotes must be escaped to have a valid sql string
682:                            String escaped = literal.toString().replaceAll("'",
683:                                    "''");
684:                            out.write("'" + escaped + "'");
685:                            return;
686:                        } else {
687:                            //convert back to a string
688:                            String encoding = (String) Converters.convert(
689:                                    literal, String.class, null);
690:                            if (encoding == null) {
691:                                //could not convert back to string, use original l value
692:                                encoding = expression.getLiteral().toString();
693:                            }
694:
695:                            // sigle quotes must be escaped to have a valid sql string
696:                            out.write("'" + encoding.replaceAll("'", "''")
697:                                    + "'");
698:                        }
699:                    }
700:                } catch (IOException e) {
701:                    throw new RuntimeException("IO problems writing literal", e);
702:                }
703:
704:            }
705:
706:            /**
707:             * Subclasses must implement this method in order to encode geometry
708:             * filters according to the specific database implementation
709:             *
710:             * @param expression
711:             *
712:             * @throws IOException DOCUMENT ME!
713:             * @throws RuntimeException DOCUMENT ME!
714:             */
715:            protected void visitLiteralGeometry(LiteralExpression expression)
716:                    throws IOException {
717:                throw new RuntimeException(
718:                        "Subclasses must implement this method in order to handle geometries");
719:            }
720:
721:            /**
722:             * @see org.geotools.filter.FilterVisitor#visit(org.geotools.filter.GeometryFilter)
723:             */
724:            public void visit(GeometryFilter filter) {
725:                throw new RuntimeException(
726:                        "Subclasses must implement this method in order to handle geometries");
727:            }
728:
729:            /**
730:             * Writes the SQL for the Math Expression.
731:             *
732:             * @param expression the Math phrase to be written.
733:             *
734:             * @throws RuntimeException for io problems
735:             */
736:            public void visit(MathExpression expression)
737:                    throws RuntimeException {
738:                LOGGER.finer("exporting Expression Math");
739:
740:                String type = (String) expressions.get(new Integer(expression
741:                        .getType()));
742:
743:                try {
744:                    ((DefaultExpression) expression.getLeftValue())
745:                            .accept(this );
746:                    out.write(" " + type + " ");
747:                    ((DefaultExpression) expression.getRightValue())
748:                            .accept(this );
749:                } catch (java.io.IOException ioe) {
750:                    throw new RuntimeException(
751:                            "IO problems writing expression", ioe);
752:                }
753:            }
754:
755:            /**
756:             * Writes sql for a function expression.  Not currently supported.
757:             *
758:             * @param expression a function expression
759:             *
760:             * @throws UnsupportedOperationException every time, this isn't supported.
761:             */
762:            public void visit(FunctionExpression expression)
763:                    throws UnsupportedOperationException {
764:                String message = "Function expression support not yet added.";
765:                throw new UnsupportedOperationException(message);
766:            }
767:
768:            /**
769:             * Sets the SQL name escape string.
770:             * 
771:             * <p>
772:             * The value of this string is prefixed and appended to table schema names,
773:             * table names and column names in an SQL statement to support mixed-case
774:             * and non-English names. Without this, the DBMS may assume a mixed-case
775:             * name in the query should be treated as upper-case and an SQLCODE of
776:             * -204 or 206 may result if the name is not found.
777:             * </p>
778:             * 
779:             * <p>
780:             * Typically this is the double-quote character, ", but may not be for all
781:             * databases.
782:             * </p>
783:             * 
784:             * <p>
785:             * For example, consider the following query:
786:             * </p>
787:             * 
788:             * <p>
789:             * SELECT Geom FROM Spear.ArchSites May be interpreted by the database as:
790:             * SELECT GEOM FROM SPEAR.ARCHSITES  If the column and table names were
791:             * actually created using mixed-case, the query needs to be specified as:
792:             * SELECT "Geom" from "Spear"."ArchSites"
793:             * </p>
794:             *
795:             * @param escape the character to be used to escape database names
796:             */
797:            public void setSqlNameEscape(String escape) {
798:                sqlNameEscape = escape;
799:            }
800:
801:            /**
802:             * Sets the escape character for the column name.
803:             *
804:             * @param escape The character to be used to escape database names.
805:             *
806:             * @deprecated Use setSqlNameEscape instead, as it is more aptly named.
807:             */
808:            public void setColnameEscape(String escape) {
809:                sqlNameEscape = escape;
810:            }
811:
812:            /**
813:             * Gets the column escape name.
814:             *
815:             * @return the string to be used to properly escape a db's name.
816:             *
817:             * @deprecated the escapeName method is preferred over this, it
818:             *             automatically returns the name properly escaped, since
819:             *             that's all getColnameEscape was being used for.
820:             */
821:            protected String getColnameEscape() {
822:                return sqlNameEscape;
823:            }
824:
825:            /**
826:             * Surrounds a name with the SQL escape character.
827:             *
828:             * @param name
829:             *
830:             * @return DOCUMENT ME!
831:             */
832:            public String escapeName(String name) {
833:                return sqlNameEscape + name + sqlNameEscape;
834:            }
835:
836:            public void visit(IncludeFilter filter) {
837:                try {
838:                    out.write("TRUE");
839:                } catch (java.io.IOException ioe) {
840:                    throw new RuntimeException(IO_ERROR, ioe);
841:                }
842:
843:            }
844:
845:            public void visit(ExcludeFilter filter) {
846:                try {
847:                    out.write("FALSE");
848:                } catch (java.io.IOException ioe) {
849:                    throw new RuntimeException(IO_ERROR, ioe);
850:                }
851:            }
852:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.