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


0001:        /*
0002:         *    GeoTools - OpenSource mapping toolkit
0003:         *    http://geotools.org
0004:         *    (C) 2002-2006, GeoTools Project Managment Committee (PMC)
0005:         *
0006:         *    This library is free software; you can redistribute it and/or
0007:         *    modify it under the terms of the GNU Lesser General Public
0008:         *    License as published by the Free Software Foundation;
0009:         *    version 2.1 of the License.
0010:         *
0011:         *    This library is distributed in the hope that it will be useful,
0012:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014:         *    Lesser General Public License for more details.
0015:         */
0016:        package org.geotools.data.h2;
0017:
0018:        import java.sql.Connection;
0019:        import java.sql.SQLException;
0020:        import java.sql.Statement;
0021:        import java.util.ArrayList;
0022:        import java.util.Iterator;
0023:        import java.util.List;
0024:        import java.util.logging.Level;
0025:
0026:        import org.geotools.data.Query;
0027:        import org.geotools.data.jdbc.JDBCState;
0028:        import org.geotools.data.jdbc.JDBCUtils;
0029:        import org.geotools.data.jdbc.PrimaryKey;
0030:        import org.geotools.feature.AttributeType;
0031:        import org.geotools.feature.FeatureType;
0032:        import org.geotools.filter.LikeFilterImpl;
0033:        import org.geotools.geometry.jts.JTS;
0034:        import org.geotools.referencing.CRS;
0035:        import org.geotools.util.Converters;
0036:        import org.opengis.filter.And;
0037:        import org.opengis.filter.BinaryComparisonOperator;
0038:        import org.opengis.filter.BinaryLogicOperator;
0039:        import org.opengis.filter.ExcludeFilter;
0040:        import org.opengis.filter.Filter;
0041:        import org.opengis.filter.FilterFactory;
0042:        import org.opengis.filter.FilterVisitor;
0043:        import org.opengis.filter.Id;
0044:        import org.opengis.filter.IncludeFilter;
0045:        import org.opengis.filter.Not;
0046:        import org.opengis.filter.Or;
0047:        import org.opengis.filter.PropertyIsBetween;
0048:        import org.opengis.filter.PropertyIsEqualTo;
0049:        import org.opengis.filter.PropertyIsGreaterThan;
0050:        import org.opengis.filter.PropertyIsGreaterThanOrEqualTo;
0051:        import org.opengis.filter.PropertyIsLessThan;
0052:        import org.opengis.filter.PropertyIsLessThanOrEqualTo;
0053:        import org.opengis.filter.PropertyIsLike;
0054:        import org.opengis.filter.PropertyIsNotEqualTo;
0055:        import org.opengis.filter.PropertyIsNull;
0056:        import org.opengis.filter.expression.Add;
0057:        import org.opengis.filter.expression.BinaryExpression;
0058:        import org.opengis.filter.expression.Divide;
0059:        import org.opengis.filter.expression.ExpressionVisitor;
0060:        import org.opengis.filter.expression.Function;
0061:        import org.opengis.filter.expression.Literal;
0062:        import org.opengis.filter.expression.Multiply;
0063:        import org.opengis.filter.expression.NilExpression;
0064:        import org.opengis.filter.expression.PropertyName;
0065:        import org.opengis.filter.expression.Subtract;
0066:        import org.opengis.filter.sort.SortBy;
0067:        import org.opengis.filter.sort.SortOrder;
0068:        import org.opengis.filter.spatial.BBOX;
0069:        import org.opengis.filter.spatial.Beyond;
0070:        import org.opengis.filter.spatial.BinarySpatialOperator;
0071:        import org.opengis.filter.spatial.Contains;
0072:        import org.opengis.filter.spatial.Crosses;
0073:        import org.opengis.filter.spatial.DWithin;
0074:        import org.opengis.filter.spatial.Disjoint;
0075:        import org.opengis.filter.spatial.DistanceBufferOperator;
0076:        import org.opengis.filter.spatial.Equals;
0077:        import org.opengis.filter.spatial.Intersects;
0078:        import org.opengis.filter.spatial.Overlaps;
0079:        import org.opengis.filter.spatial.Touches;
0080:        import org.opengis.filter.spatial.Within;
0081:        import org.opengis.metadata.Identifier;
0082:        import org.opengis.referencing.crs.CoordinateReferenceSystem;
0083:
0084:        import com.vividsolutions.jts.geom.Envelope;
0085:        import com.vividsolutions.jts.geom.Geometry;
0086:        import com.vividsolutions.jts.io.WKTWriter;
0087:
0088:        /**
0089:         * Encodes an sql statement.
0090:         * <p>
0091:         *
0092:         * </p>
0093:         * <p>
0094:         * This class is not thread safe.
0095:         * </p>
0096:         * @author Justin Deoliveira, The Open Planning Project
0097:         */
0098:        public class H2SQLBuilder implements  FilterVisitor, ExpressionVisitor {
0099:            /**
0100:             * Filter factory used to create filters
0101:             */
0102:            FilterFactory filterFactory;
0103:
0104:            /**
0105:             * The state of the entry to create statements for
0106:             */
0107:            JDBCState state;
0108:
0109:            /**
0110:             * SQl Statement buffer
0111:             */
0112:            StringBuffer sql;
0113:
0114:            /**
0115:             * Post-processing filter
0116:             */
0117:            Filter postFilter;
0118:
0119:            /**
0120:             * Creates the sql builder.
0121:             *
0122:             * @param state The state of the entry the builder will create statements for.
0123:             * @param filterFactory A factory used to create filter objects.
0124:             */
0125:            public H2SQLBuilder(JDBCState state, FilterFactory filterFactory) {
0126:                this .state = state;
0127:                this .filterFactory = filterFactory;
0128:
0129:                sql = new StringBuffer();
0130:            }
0131:
0132:            public Statement createTable() throws SQLException {
0133:                FeatureType featureType = featureType();
0134:
0135:                init();
0136:
0137:                sql.append("CREATE TABLE ");
0138:
0139:                //table name
0140:                table();
0141:
0142:                //table definition
0143:                String[] sqlTypeNames = null;
0144:
0145:                try {
0146:                    sqlTypeNames = JDBCUtils.sqlTypeNames(
0147:                            state.getMemberType(), null);
0148:                } catch (Exception e) {
0149:                    throw new RuntimeException(e);
0150:                }
0151:
0152:                sql.append(" ( ");
0153:
0154:                for (int i = 0; i < sqlTypeNames.length; i++) {
0155:                    AttributeType type = featureType.getAttributeType(i);
0156:
0157:                    //the column name
0158:                    name(type.getName());
0159:                    sql.append(" ");
0160:
0161:                    //sql type name
0162:                    sql.append(sqlTypeNames[i]);
0163:
0164:                    if (i < (sqlTypeNames.length - 1)) {
0165:                        sql.append(", ");
0166:                    }
0167:                }
0168:
0169:                sql.append(" )");
0170:
0171:                Connection conn = null;//state.getDataStore().connection();
0172:
0173:                return conn.prepareStatement(sql.toString());
0174:            }
0175:
0176:            FeatureType featureType() {
0177:                try {
0178:                    return state.getMemberType();
0179:                } catch (Exception e) {
0180:                    throw new RuntimeException(e);
0181:                }
0182:            }
0183:
0184:            /**
0185:             * Initializes the state of the encoder.
0186:             *
0187:             */
0188:            protected void init() {
0189:                sql = new StringBuffer();
0190:                postFilter = null;
0191:            }
0192:
0193:            //
0194:            // Methods for encoding entire statements
0195:            //
0196:
0197:            /**
0198:             * Encodes an entire "CREATE TABLE" statement.
0199:             */
0200:            public String create() {
0201:                FeatureType featureType = featureType();
0202:
0203:                init();
0204:
0205:                sql.append("CREATE TABLE ");
0206:
0207:                //table name
0208:                table();
0209:
0210:                //table definition
0211:                String[] sqlTypeNames = null;
0212:
0213:                try {
0214:                    //sqlTypeNames = H2Utils.sqlTypeNames(state);
0215:                } catch (Exception e) {
0216:                    throw new RuntimeException(e);
0217:                }
0218:
0219:                sql.append(" ( ");
0220:
0221:                for (int i = 0; i < sqlTypeNames.length; i++) {
0222:                    AttributeType type = featureType.getAttributeType(i);
0223:
0224:                    //the column name
0225:                    name(type.getName());
0226:                    sql.append(" ");
0227:
0228:                    //sql type name
0229:                    sql.append(sqlTypeNames[i]);
0230:
0231:                    if (i < (sqlTypeNames.length - 1)) {
0232:                        sql.append(", ");
0233:                    }
0234:                }
0235:
0236:                sql.append(" )");
0237:
0238:                return sql.toString();
0239:            }
0240:
0241:            /**
0242:             * Encodes an entire sql SELECT statement of the form
0243:             *         "SELECT count(*) FROM ...".
0244:             *
0245:             * @param filter The filter describing the where class of the select statement.
0246:             *
0247:             */
0248:            public String count(Filter filter) {
0249:                init();
0250:
0251:                //select
0252:                sql.append("SELECT count(*) ");
0253:
0254:                //from
0255:                from();
0256:
0257:                //where
0258:                if ((filter != null) && (filter != Filter.INCLUDE)) {
0259:                    where(filter);
0260:                }
0261:
0262:                return sql.toString();
0263:            }
0264:
0265:            /**
0266:             * Encodes an entire sql SELECT statement.
0267:             *
0268:             * @param query The query defining the select.
0269:             *
0270:             */
0271:            public String select(Query query) {
0272:                init();
0273:
0274:                //select
0275:                select(query.getPropertyNames());
0276:
0277:                //from
0278:                from();
0279:
0280:                //where
0281:                if ((query.getFilter() != null)
0282:                        && (query.getFilter() != Filter.INCLUDE)) {
0283:                    where(query.getFilter());
0284:                }
0285:
0286:                //order by
0287:                if ((query.getSortBy() != null)
0288:                        && (query.getSortBy().length > 0)) {
0289:                    sortBy(query.getSortBy());
0290:                }
0291:
0292:                return sql.toString();
0293:            }
0294:
0295:            /**
0296:             * Encodes an entire sql DELETE statement.
0297:             * <p>
0298:             * In the event that the filter cannot be entirely encoded, no sql is encoded at all.
0299:             * </p>
0300:             * @param filter The filter dtermining what is to be deleted.
0301:             *
0302:             */
0303:            public String delete(Filter filter) {
0304:                init();
0305:
0306:                sql.append("DELETE");
0307:                from();
0308:                where(filter);
0309:
0310:                return sql.toString();
0311:            }
0312:
0313:            /**
0314:             * Encodes an entire sql UPDATE statement.
0315:             * <p>
0316:             * In the event that the query filter cannot be entirly encoded no sql is encoded at all.
0317:             * </p>
0318:             * @param query The query defining the properties to change and filter.
0319:             * @param values The new values.
0320:             *
0321:             */
0322:            public String update(Query query, Object[] values) {
0323:                init();
0324:                sql.append("UPDATE ");
0325:
0326:                //table name
0327:                table();
0328:
0329:                sql.append(" SET ");
0330:
0331:                for (int i = 0; i < values.length; i++) {
0332:                    //encode the name
0333:                    PropertyName propertyName = filterFactory.property(query
0334:                            .getPropertyNames()[i]);
0335:                    Class type = (Class) propertyName.accept(this , null);
0336:
0337:                    sql.append(" = ");
0338:
0339:                    //encode the value
0340:                    Literal literal = filterFactory.literal(values[i]);
0341:                    literal.accept(this , type);
0342:
0343:                    if (i < (values.length - 1)) {
0344:                        sql.append(", ");
0345:                    }
0346:                }
0347:
0348:                //filter
0349:                if (query.getFilter() != null) {
0350:                    where(query.getFilter());
0351:                }
0352:
0353:                return sql.toString();
0354:            }
0355:
0356:            /**
0357:             * Encodes an entire sql INSERT statement.
0358:             *
0359:             * @param names The names of attributes ( columns )
0360:             * @param values The values to insert
0361:             *
0362:             */
0363:            public String insert(String[] names, Object[] values) {
0364:                FeatureType featureType = featureType();
0365:
0366:                sql = new StringBuffer();
0367:                sql.append("INSERT INTO ");
0368:
0369:                //table name
0370:                table();
0371:
0372:                //column names
0373:                sql.append(" ( ");
0374:
0375:                if (names == null) {
0376:                    //assume all, 
0377:                    names = new String[featureType.getAttributeCount()];
0378:
0379:                    for (int i = 0; i < names.length; i++) {
0380:                        names[i] = featureType.getAttributeType(i).getName();
0381:                    }
0382:                }
0383:
0384:                if (names.length != values.length) {
0385:                    String msg = "Specified " + names.length + " names, but "
0386:                            + values.length + " values";
0387:                    throw new IllegalArgumentException(msg);
0388:                }
0389:
0390:                AttributeType[] types = new AttributeType[names.length];
0391:
0392:                for (int i = 0; i < names.length; i++) {
0393:                    PropertyName propertyName = filterFactory
0394:                            .property(names[i]);
0395:                    propertyName.accept(this , null);
0396:
0397:                    if (i < (names.length - 1)) {
0398:                        sql.append(", ");
0399:                    }
0400:
0401:                    //evaluate to get attribute, used for encoding values
0402:                    types[i] = (AttributeType) propertyName
0403:                            .evaluate(featureType);
0404:                }
0405:
0406:                sql.append(" ) VALUES ( ");
0407:
0408:                for (int i = 0; i < values.length; i++) {
0409:                    Literal literal = filterFactory.literal(values[i]);
0410:                    AttributeType type = types[i];
0411:
0412:                    literal.accept(this , type.getType());
0413:
0414:                    if (i < (values.length - 1)) {
0415:                        sql.append(", ");
0416:                    }
0417:                }
0418:
0419:                sql.append(" )");
0420:
0421:                return sql.toString();
0422:            }
0423:
0424:            //
0425:            // Methods for encoding partial statements
0426:            //
0427:            /**
0428:             * Encodes the select clause of a query.
0429:             * <p>
0430:             * If <param>propertyNames</param> is null or empty then "*" is used.
0431:             * </p>
0432:             * @param propertyNames The array of properties / columns in the select.
0433:             */
0434:            public void select(String[] propertyNames) {
0435:                sql.append("SELECT ");
0436:
0437:                if ((propertyNames == null) || (propertyNames.length == 0)) {
0438:                    sql.append("*");
0439:                } else {
0440:                    for (int i = 0; i < propertyNames.length; i++) {
0441:                        PropertyName propertyName = filterFactory
0442:                                .property(propertyNames[i]);
0443:                        selectColumn(propertyName);
0444:
0445:                        if (i < (propertyNames.length - 1)) {
0446:                            sql.append(", ");
0447:                        }
0448:                    }
0449:                }
0450:            }
0451:
0452:            private void selectColumn(PropertyName propertyName) {
0453:                //get the feature type
0454:                FeatureType featureType = featureType();
0455:
0456:                //get the attribute type
0457:                AttributeType attributeType = (AttributeType) propertyName
0458:                        .evaluate(featureType);
0459:
0460:                if (attributeType != null) {
0461:                    //check for geometry, because it is encided differnently
0462:                    if (Geometry.class
0463:                            .isAssignableFrom(attributeType.getType())) {
0464:                        propertyName.accept(this , null);
0465:                    } else {
0466:                        //normal property , nothign special
0467:                        propertyName.accept(this , null);
0468:                    }
0469:                }
0470:            }
0471:
0472:            /**
0473:             * Encodes the FROM clause of a query.
0474:             * <p>
0475:             * The encoded sql is of the form 'FROM <table>', table is generated from {@link #table()}.
0476:             * </p>
0477:             */
0478:            public void from() {
0479:                sql.append(" FROM ");
0480:                table();
0481:            }
0482:
0483:            /**
0484:             * Encodes the table name of a query.
0485:             * <p>
0486:             * The table name is obtained from {@link #featureType}.
0487:             * </p>
0488:             *
0489:             */
0490:            public void table() {
0491:                //name(state.getDataStore().getDatabaseSchema());
0492:                sql.append(".");
0493:                name(state.getEntry().getTypeName());
0494:            }
0495:
0496:            /**
0497:             * Encodes the WHERE clause of a query.
0498:             *
0499:             * @param filter The filter defining the where clause, non-null.
0500:             *
0501:             */
0502:            public void where(Filter filter) {
0503:                sql.append(" WHERE ");
0504:                filter.accept(this , null);
0505:            }
0506:
0507:            /**
0508:             * Encodes the SORT BY clause of a query.
0509:             *
0510:             * @param sortBy The elements definining the columns to sort by.
0511:             */
0512:            public void sortBy(SortBy[] sortBy) {
0513:                sql.append(" ORDER BY ");
0514:
0515:                for (int i = 0; i < sortBy.length; i++) {
0516:                    SortBy sort = sortBy[i];
0517:                    sort.getPropertyName().accept(this , null);
0518:
0519:                    if (sort.getSortOrder() == SortOrder.DESCENDING) {
0520:                        sql.append(" DESC");
0521:                    }
0522:
0523:                    if (i < (sortBy.length - 1)) {
0524:                        sql.append(", ");
0525:                    }
0526:                }
0527:            }
0528:
0529:            /**
0530:             * @return The String buffer being used to encode the sql statement.
0531:             */
0532:            public StringBuffer getSQL() {
0533:                return sql;
0534:            }
0535:
0536:            //
0537:            // Start of non-public api
0538:            //
0539:            //
0540:            public Object visitNullFilter(Object data) {
0541:                return null;
0542:            }
0543:
0544:            public Object visit(ExcludeFilter exclude, Object data) {
0545:                sql.append("1 = 0");
0546:
0547:                return data;
0548:            }
0549:
0550:            public Object visit(IncludeFilter include, Object data) {
0551:                sql.append("1 = 1");
0552:
0553:                return data;
0554:            }
0555:
0556:            //
0557:            // logical operators
0558:            //
0559:            public Object visit(Not not, Object data) {
0560:                sql.append("NOT ( ");
0561:                data = not.getFilter().accept(this , data);
0562:                sql.append(" )");
0563:
0564:                return data;
0565:            }
0566:
0567:            public Object visit(And and, Object data) {
0568:                return visit(and, data, "AND");
0569:            }
0570:
0571:            public Object visit(Or or, Object data) {
0572:                return visit(or, data, "OR");
0573:            }
0574:
0575:            protected Object visit(BinaryLogicOperator logic, Object data,
0576:                    String operator) {
0577:                boolean parentheses = logic.getChildren().size() > 1;
0578:
0579:                //encode each child
0580:                for (Iterator f = logic.getChildren().iterator(); f.hasNext();) {
0581:                    Filter filter = (Filter) f.next();
0582:
0583:                    if (parentheses) {
0584:                        sql.append("( ");
0585:                    }
0586:
0587:                    data = filter.accept(this , data);
0588:
0589:                    if (parentheses) {
0590:                        sql.append(" )");
0591:                    }
0592:
0593:                    if (f.hasNext()) {
0594:                        sql.append(" " + operator + " ");
0595:                    }
0596:                }
0597:
0598:                return data;
0599:            }
0600:
0601:            //
0602:            //id filter
0603:            //
0604:            public Object visit(Id id, Object data) {
0605:                try {
0606:                    //get the primary key
0607:                    PrimaryKey key = null;//state.primaryKey();
0608:
0609:                    //prepare each column as a property name
0610:                    PropertyName[] columnNames = new PropertyName[key.columns.length];
0611:
0612:                    for (int i = 0; i < columnNames.length; i++) {
0613:                        columnNames[i] = filterFactory
0614:                                .property(key.columns[i].name);
0615:                    }
0616:
0617:                    //process each fid, creating an OR filter
0618:                    List or = new ArrayList();
0619:
0620:                    for (Iterator f = id.getIDs().iterator(); f.hasNext();) {
0621:                        String fid = (String) f.next();
0622:
0623:                        //map to values
0624:                        Object[] values = key.decode(fid);
0625:
0626:                        //create an "AND" filter for each property name
0627:                        List and = new ArrayList();
0628:
0629:                        for (int i = 0; i < values.length; i++) {
0630:                            //create an equalTo filter
0631:                            PropertyName name = columnNames[i];
0632:                            Literal literal = filterFactory.literal(values[i]);
0633:                            and.add(filterFactory.equals(name, literal));
0634:                        }
0635:
0636:                        //add to or
0637:                        or.add(filterFactory.and(and));
0638:                    }
0639:
0640:                    //encode it
0641:                    return filterFactory.or(or).accept(this , data);
0642:                } catch (Exception e) {
0643:                    throw new RuntimeException(e);
0644:                }
0645:            }
0646:
0647:            //
0648:            // binary comparison operators
0649:            //
0650:            public Object visit(PropertyIsBetween between, Object data) {
0651:                sql.append("( ");
0652:
0653:                data = between.getExpression().accept(this , data);
0654:                sql.append(" ) BETWEEN ( ");
0655:
0656:                data = between.getLowerBoundary().accept(this , data);
0657:                sql.append(" ) AND ( ");
0658:
0659:                data = between.getUpperBoundary().accept(this , data);
0660:                sql.append(" )");
0661:
0662:                return data;
0663:            }
0664:
0665:            public Object visit(PropertyIsEqualTo equalTo, Object data) {
0666:                return visit(equalTo, data, "=");
0667:            }
0668:
0669:            public Object visit(PropertyIsNotEqualTo notEqualTo, Object data) {
0670:                return visit(notEqualTo, data, "!=");
0671:            }
0672:
0673:            public Object visit(PropertyIsGreaterThan greaterThan, Object data) {
0674:                return visit(greaterThan, data, ">");
0675:            }
0676:
0677:            public Object visit(
0678:                    PropertyIsGreaterThanOrEqualTo greaterThanOrEqualTo,
0679:                    Object data) {
0680:                return visit(greaterThanOrEqualTo, data, ">=");
0681:            }
0682:
0683:            public Object visit(PropertyIsLessThan lessThan, Object data) {
0684:                return visit(lessThan, data, "<");
0685:            }
0686:
0687:            public Object visit(PropertyIsLessThanOrEqualTo lessThanOrEqualTo,
0688:                    Object data) {
0689:                return visit(lessThanOrEqualTo, data, "<=");
0690:            }
0691:
0692:            protected Object visit(BinaryComparisonOperator comparison,
0693:                    Object data, String operator) {
0694:                sql.append("( ");
0695:
0696:                //left
0697:                data = comparison.getExpression1().accept(this , data);
0698:
0699:                //operator
0700:                sql.append(" ) " + operator + " ( ");
0701:
0702:                //right
0703:                data = comparison.getExpression2().accept(this , data);
0704:
0705:                sql.append(" )");
0706:
0707:                return data;
0708:            }
0709:
0710:            public Object visit(PropertyIsLike like, Object data) {
0711:                String pattern = LikeFilterImpl.convertToSQL92(like.getEscape()
0712:                        .charAt(0), like.getWildCard().charAt(0), like
0713:                        .getSingleChar().charAt(0), like.getLiteral());
0714:
0715:                //evaluate left hande
0716:                data = like.getExpression().accept(this , data);
0717:
0718:                sql.append(" LIKE ");
0719:
0720:                //encode pattern as string
0721:                string(pattern, sql);
0722:
0723:                return data;
0724:            }
0725:
0726:            public Object visit(PropertyIsNull isNull, Object data) {
0727:                data = isNull.getExpression().accept(this , data);
0728:                sql.append(" IS ");
0729:                nil(sql);
0730:
0731:                return data;
0732:            }
0733:
0734:            //
0735:            // spatial operators
0736:            //
0737:            public Object visit(BBOX bbox, Object data) {
0738:                //create a property name + geometry
0739:                PropertyName name = filterFactory.property(bbox
0740:                        .getPropertyName());
0741:                Envelope e = new Envelope(bbox.getMinX(), bbox.getMaxX(), bbox
0742:                        .getMinY(), bbox.getMaxY());
0743:
0744:                if (bbox.getSRS() != null) {
0745:                    CoordinateReferenceSystem crs;
0746:
0747:                    try {
0748:                        crs = CRS.decode(bbox.getSRS());
0749:                        data = crs;
0750:                    } catch (Exception ex) {
0751:                        //H2DataStore.LOGGER.log(Level.WARNING, ex.getLocalizedMessage(), ex);
0752:                    }
0753:                }
0754:
0755:                return visit(name, JTS.toGeometry(e), data);
0756:            }
0757:
0758:            protected Object visit(PropertyName name, Geometry geometry,
0759:                    Object data) {
0760:                //encode the property ( dont carry back data )
0761:                name.accept(this , data);
0762:
0763:                //bbox operator
0764:                sql.append(" && ");
0765:
0766:                //encode the geometry
0767:                Literal literal = filterFactory.literal(geometry);
0768:
0769:                return literal.accept(this , data);
0770:            }
0771:
0772:            public Object visit(Beyond beyond, Object data) {
0773:                return visit(beyond, data, ">", false);
0774:            }
0775:
0776:            public Object visit(DWithin dwithin, Object data) {
0777:                return visit(dwithin, data, "<=", true);
0778:            }
0779:
0780:            protected Object visit(DistanceBufferOperator distance,
0781:                    Object data, String operator, boolean index) {
0782:                data = visit((BinarySpatialOperator) distance, data,
0783:                        "distance", index);
0784:                sql.append(" " + operator + " " + distance.getDistance());
0785:
0786:                return data;
0787:            }
0788:
0789:            public Object visit(Disjoint disjoint, Object data) {
0790:                return visit(disjoint, data, "disjoint", false);
0791:            }
0792:
0793:            public Object visit(Contains contains, Object data) {
0794:                return visit(contains, data, "contains", true);
0795:            }
0796:
0797:            public Object visit(Crosses crosses, Object data) {
0798:                return visit(crosses, data, "crosses", true);
0799:            }
0800:
0801:            public Object visit(Equals equals, Object data) {
0802:                return visit(equals, data, "equals", true);
0803:            }
0804:
0805:            public Object visit(Intersects intersects, Object data) {
0806:                return visit(intersects, data, "intersects", true);
0807:            }
0808:
0809:            public Object visit(Overlaps overlaps, Object data) {
0810:                return visit(overlaps, data, "overlaps", true);
0811:            }
0812:
0813:            public Object visit(Touches touches, Object data) {
0814:                return visit(touches, data, "touches", true);
0815:            }
0816:
0817:            public Object visit(Within within, Object data) {
0818:                return visit(within, data, "within", true);
0819:            }
0820:
0821:            protected Object visit(BinarySpatialOperator comparison,
0822:                    Object data, String operator, boolean index) {
0823:                //use the index for this comparison?
0824:                if (index) {
0825:                    //figure out the property name, and geometry
0826:                    PropertyName propertyName = null;
0827:                    Geometry geometry = null;
0828:
0829:                    if (comparison.getExpression1() instanceof  PropertyName) {
0830:                        propertyName = (PropertyName) comparison
0831:                                .getExpression1();
0832:                        geometry = (Geometry) comparison.getExpression2()
0833:                                .evaluate(null, Geometry.class);
0834:                    } else if (comparison.getExpression2() instanceof  PropertyName) {
0835:                        propertyName = (PropertyName) comparison
0836:                                .getExpression2();
0837:                        geometry = (Geometry) comparison.getExpression1()
0838:                                .evaluate(null, Geometry.class);
0839:                    }
0840:
0841:                    if ((propertyName != null) && (geometry != null)) {
0842:                        data = visit(propertyName, geometry, data);
0843:                        sql.append(" AND ");
0844:                    }
0845:                }
0846:
0847:                //operator
0848:                sql.append(operator + "( ( ");
0849:
0850:                //left
0851:                data = comparison.getExpression1().accept(this , data);
0852:
0853:                sql.append(" ) , ( ");
0854:
0855:                //right
0856:                data = comparison.getExpression2().accept(this , data);
0857:
0858:                sql.append(" ) )");
0859:
0860:                return data;
0861:            }
0862:
0863:            public Object visit(NilExpression nil, Object data) {
0864:                // TODO Auto-generated method stub
0865:                return null;
0866:            }
0867:
0868:            //
0869:            // Arithmetic operators
0870:            //
0871:            public Object visit(Add add, Object data) {
0872:                return visit(add, data, "+");
0873:            }
0874:
0875:            public Object visit(Subtract subtract, Object data) {
0876:                return visit(subtract, data, "-");
0877:            }
0878:
0879:            public Object visit(Multiply multiply, Object data) {
0880:                return visit(multiply, data, "*");
0881:            }
0882:
0883:            public Object visit(Divide divide, Object data) {
0884:                return visit(divide, data, "/");
0885:            }
0886:
0887:            protected Object visit(BinaryExpression expression, Object data,
0888:                    String operator) {
0889:                sql.append("( ");
0890:                data = expression.getExpression1().accept(this , data);
0891:
0892:                sql.append(" ) " + operator + " ( ");
0893:                data = expression.getExpression2().accept(this , data);
0894:
0895:                sql.append(" )");
0896:
0897:                return data;
0898:            }
0899:
0900:            public Object visit(Function function, Object data) {
0901:                // TODO Auto-generated method stub
0902:                return null;
0903:            }
0904:
0905:            /**
0906:             * Encodes a literal.
0907:             * <p>
0908:             *
0909:             * </p>
0910:             */
0911:            public Object visit(Literal literal, Object data) {
0912:                Object value = null;
0913:
0914:                //was the type passed in as a hint?
0915:                if (data instanceof  Class) {
0916:                    //special case for numerics, let the database do the conversions
0917:                    // it needs to
0918:                    if (Number.class.isAssignableFrom((Class) data)) {
0919:                        //value = literal.evaluate( null, BigDecimal.class );
0920:                        value = literal.evaluate(null, Number.class);
0921:                    } else {
0922:                        //non numeric, just convert
0923:                        value = literal.evaluate(null, (Class) data);
0924:                    }
0925:                } else {
0926:                    //just evaluate
0927:                    value = literal.evaluate(null);
0928:                }
0929:
0930:                //check for string
0931:                if (value instanceof  String) {
0932:                    string((String) value, sql);
0933:
0934:                    return data;
0935:                }
0936:
0937:                FeatureType featureType = featureType();
0938:
0939:                //check for geometry
0940:                if (value instanceof  Geometry) {
0941:                    //figure out srid
0942:                    CoordinateReferenceSystem crs = null;
0943:
0944:                    //passed in?
0945:                    if (data instanceof  CoordinateReferenceSystem) {
0946:                        crs = (CoordinateReferenceSystem) data;
0947:                    } else {
0948:                        //check the feature type
0949:                        if (featureType.getDefaultGeometry() != null) {
0950:                            crs = featureType.getDefaultGeometry()
0951:                                    .getCoordinateSystem();
0952:                        }
0953:                    }
0954:
0955:                    //convert to a postgis srid
0956:                    String srid = null;
0957:
0958:                    if (crs != null) {
0959:                        srid = encode(crs);
0960:                    }
0961:
0962:                    geometry((Geometry) value, srid, sql);
0963:
0964:                    return data;
0965:                }
0966:
0967:                //convert to string
0968:                String encoded = (String) Converters.convert(value,
0969:                        String.class);
0970:
0971:                if (encoded == null) {
0972:                    //fall back to toString()
0973:                    encoded = value.toString();
0974:                }
0975:
0976:                sql.append(encoded);
0977:
0978:                return data;
0979:            }
0980:
0981:            /**
0982:             * Helper method to encode a crs. Can we have this on CRS?
0983:             */
0984:            String encode(CoordinateReferenceSystem crs) {
0985:                if (crs == null) {
0986:                    return null;
0987:                }
0988:
0989:                for (Iterator i = crs.getIdentifiers().iterator(); i.hasNext();) {
0990:                    Identifier id = (Identifier) i.next();
0991:
0992:                    return id.toString();
0993:                }
0994:
0995:                return null;
0996:            }
0997:
0998:            /**
0999:             * Encodes a {@link PropertyName} in an sql statement.
1000:             * <p>
1001:             * If the AttributeType can be infered from {@link #featureType} then its name
1002:             * is used directly.
1003:             * </p>
1004:             *
1005:             * @return The class binding of the attribute type, or <code>null</code> if unknown.
1006:             */
1007:            public Object visit(PropertyName propertyName, Object data) {
1008:                try {
1009:                    //1. evaluate against the type to get the AttributeType
1010:                    FeatureType featureType = state.getMemberType();
1011:
1012:                    AttributeType attributeType = (AttributeType) propertyName
1013:                            .evaluate(featureType);
1014:
1015:                    if (attributeType != null) {
1016:                        //encode the name of the attribute, not the property name itself
1017:                        name(attributeType.getName());
1018:
1019:                        //return the type as the return 
1020:                        return attributeType.getType();
1021:                    }
1022:
1023:                    //2. not in type, could it be a primary key?
1024:                    PrimaryKey key = null; //state.primaryKey();
1025:
1026:                    //serach for the property in the primary key, encode it and return its type
1027:                    for (int i = 0; i < key.columns.length; i++) {
1028:                        String name = key.columns[i].name;
1029:
1030:                        if (propertyName.getPropertyName().equals(name)) {
1031:                            //encode it
1032:                            name(propertyName.getPropertyName());
1033:
1034:                            //return the type
1035:                            return key.columns[i].type;
1036:                        }
1037:                    }
1038:
1039:                    //3. give up, just encode directly
1040:                    name(propertyName.getPropertyName());
1041:
1042:                    //return nothing
1043:                    return null;
1044:                } catch (Exception e) {
1045:                    throw new RuntimeException(e);
1046:                }
1047:            }
1048:
1049:            /**
1050:             * Encodes a name to be used in an sql statement.
1051:             * <p>
1052:             * This implementation wraps the name in double quotes.
1053:             * <p>
1054:             *
1055:             * @param raw The raw name.
1056:             *
1057:             */
1058:            protected void name(String raw) {
1059:                sql.append("\"" + raw + "\"");
1060:            }
1061:
1062:            /**
1063:             * Encodes a string to be used in an sql statement.
1064:             *
1065:             * @param raw The raw string.
1066:             * @param sql The sql statement buffer
1067:             *
1068:             */
1069:            protected void string(String raw, StringBuffer sql) {
1070:                sql.append("'" + raw + "'");
1071:            }
1072:
1073:            /**
1074:             * Encodes a geometry with a known srid to be used in an sql statement.
1075:             *
1076:             * @param geometry The geometry to encode.
1077:             * @param srid The spatial reference id of the geometry
1078:             * @param sql HTe sql statement buffer
1079:             */
1080:            protected void geometry(Geometry geometry, String srid,
1081:                    StringBuffer sql) {
1082:                String wkt = new WKTWriter().write(geometry);
1083:                sql.append("GeometryFromText( '" + wkt + "', ");
1084:                srid(srid, sql);
1085:                sql.append(" )");
1086:            }
1087:
1088:            /**
1089:             * Encodes a srid to be used in an sql statement
1090:             *
1091:             * @param srid The raw spatial reference id of the geometry
1092:             * @param sql HTe sql statement buffer
1093:             */
1094:            protected void srid(String raw, StringBuffer sql) {
1095:                if (raw == null) {
1096:                    sql.append("0");
1097:                } else if (raw.matches("[0-9]+")) {
1098:                    sql.append(raw);
1099:                } else if (raw.matches(".*:[0-9]+")) {
1100:                    raw = raw.replaceAll(".*:([0-9]+)", "$1");
1101:                    sql.append(raw);
1102:                }
1103:            }
1104:
1105:            /**
1106:             * Encodes <code>nulL</code> to be used in an sql statement.
1107:             *
1108:             * @param sql The sql statement buffer
1109:             */
1110:            protected void nil(StringBuffer sql) {
1111:                sql.append("NULL");
1112:            }
1113:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.