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


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2004-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:         * TODO: 26-may-2005 D. Adler Added constructor with returnFIDColumnsAsAttributes. Added accessors for ColumnInfo
017:         */
018:        /*
019:         * 26-may-2005 D. Adler Added constructor with returnFIDColumnsAsAttributes.
020:         *                      Added accessors for ColumnInfo
021:         * 12-jul-2006 D. Adler GEOT-728 Refactor FIDMapper classes
022:         */
023:        package org.geotools.data.jdbc.fidmapper;
024:
025:        import org.geotools.data.DataSourceException;
026:        import org.geotools.data.SchemaNotFoundException;
027:        import org.geotools.data.Transaction;
028:        import org.geotools.data.jdbc.JDBCUtils;
029:        import org.geotools.feature.FeatureType;
030:        import java.io.IOException;
031:        import java.sql.Connection;
032:        import java.sql.DatabaseMetaData;
033:        import java.sql.ResultSet;
034:        import java.sql.SQLException;
035:        import java.sql.Statement;
036:        import java.sql.Types;
037:        import java.util.ArrayList;
038:        import java.util.Collection;
039:        import java.util.HashMap;
040:        import java.util.LinkedHashMap;
041:        import java.util.List;
042:        import java.util.Map;
043:        import java.util.logging.Level;
044:        import java.util.logging.Logger;
045:
046:        /**
047:         * Default FID mapper that works with default FID mappers.
048:         * 
049:         * <p>
050:         * May also be used a base class for more specific and feature rich factories
051:         * </p>
052:         *
053:         * @author Andrea Aime
054:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/jdbc/src/main/java/org/geotools/data/jdbc/fidmapper/DefaultFIDMapperFactory.java $
055:         */
056:        public class DefaultFIDMapperFactory implements  FIDMapperFactory {
057:            /** The logger for the filter module. */
058:            protected static final Logger LOGGER = org.geotools.util.logging.Logging
059:                    .getLogger("org.geotools.data.jdbc");
060:            protected boolean returningTypedFIDMapper = true;
061:
062:            /** Set if table FID columns are to be returned as business attributes. */
063:            protected boolean returnFIDColumnsAsAttributes = false;
064:
065:            /**
066:             * Constructs a DefaultFIDMapperFactory which will not return FID columns
067:             * as business attributes.
068:             */
069:            public DefaultFIDMapperFactory() {
070:            }
071:
072:            /**
073:             * Constructs a DefaultFIDMapperFactory with user specification of whether
074:             * to return FID columns as business attributes.
075:             *
076:             * @param returnFIDColumnsAsAttributes true if FID columns should be
077:             *        returned as business  attributes.
078:             */
079:            public DefaultFIDMapperFactory(boolean returnFIDColumnsAsAttributes) {
080:                this .returnFIDColumnsAsAttributes = returnFIDColumnsAsAttributes;
081:            }
082:
083:            /**
084:             * Setter for the flag controlling wther a "typed" fid mapper is returned.
085:             * @param returningTypedFIDMapper
086:             */
087:            public void setReturningTypedFIDMapper(
088:                    boolean returningTypedFIDMapper) {
089:                this .returningTypedFIDMapper = returningTypedFIDMapper;
090:            }
091:
092:            /**
093:             * Getter for the flog controll wether a "typed" fid mapper should be returned.
094:             */
095:            public boolean isReturningTypedFIDMapper() {
096:                return returningTypedFIDMapper;
097:            }
098:
099:            /**
100:             * Gets the appropriate FIDMapper for the specified table.
101:             *
102:             * @param catalog
103:             * @param schema
104:             * @param tableName
105:             * @param connection the active database connection to get table key
106:             *        information
107:             *
108:             * @return the appropriate FIDMapper for the specified table.
109:             *
110:             * @throws IOException if any error occurs.
111:             */
112:            public FIDMapper getMapper(String catalog, String schema,
113:                    String tableName, Connection connection) throws IOException {
114:                ColumnInfo[] colInfos = getPkColumnInfo(catalog, schema,
115:                        tableName, connection);
116:                FIDMapper mapper = null;
117:
118:                if (colInfos.length == 0) {
119:                    mapper = buildNoPKMapper(schema, tableName, connection);
120:                } else if (colInfos.length > 1) {
121:                    mapper = buildMultiColumnFIDMapper(schema, tableName,
122:                            connection, colInfos);
123:                } else {
124:                    ColumnInfo ci = colInfos[0];
125:
126:                    mapper = buildSingleColumnFidMapper(schema, tableName,
127:                            connection, ci);
128:                }
129:
130:                if (mapper == null) {
131:                    mapper = buildLastResortFidMapper(schema, tableName,
132:                            connection, colInfos);
133:
134:                    if (mapper == null) {
135:                        String msg = "Cannot map primary key to a FID mapper, primary key columns are:\n"
136:                                + getColumnInfoList(colInfos);
137:                        LOGGER.log(Level.SEVERE, msg);
138:                        throw new IOException(msg);
139:                    }
140:                }
141:
142:                if (returningTypedFIDMapper && (mapper != null)) {
143:                    return new TypedFIDMapper(mapper, tableName);
144:                } else {
145:                    return mapper;
146:                }
147:            }
148:
149:            /**
150:             * Retuns a List of column infos, nice for logging the column infos
151:             * leveraging the complete toString() method provided by lists
152:             *
153:             * @param colInfos
154:             *
155:             */
156:            protected List getColumnInfoList(ColumnInfo[] colInfos) {
157:                ArrayList list = new ArrayList();
158:
159:                for (int i = 0; i < colInfos.length; i++) {
160:                    list.add(colInfos[i]);
161:                }
162:
163:                return list;
164:            }
165:
166:            /**
167:             * Builds a FidMapper when every other tentative of building one fails.
168:             * This method is used as a last resort fall back, use it if you can
169:             * provide a FIDMapper that works on every kind of table, but it's usually
170:             * suboptimal. The default behaviour is to return no FID mapper at all.
171:             *
172:             * @param schema
173:             * @param tableName
174:             * @param connection
175:             * @param colInfos
176:             *
177:             */
178:            protected FIDMapper buildLastResortFidMapper(String schema,
179:                    String tableName, Connection connection,
180:                    ColumnInfo[] colInfos) {
181:                return null;
182:            }
183:
184:            /**
185:             * Builds a FID mapper based on a single column primary key. Default
186:             * version tries the auto-increment way, then a mapping on an {@link
187:             * MaxIncFIDMapper} type for numeric columns, and a plain {@link
188:             * BasicFIDMapper} of text based columns.
189:             *
190:             * @param schema
191:             * @param tableName
192:             * @param connection an open database connection.
193:             * @param ci the column information for the FID column.
194:             *
195:             * @return the appropriate FIDMapper.
196:             */
197:            protected FIDMapper buildSingleColumnFidMapper(String schema,
198:                    String tableName, Connection connection, ColumnInfo ci) {
199:                if (ci.autoIncrement) {
200:                    return new AutoIncrementFIDMapper(schema, tableName,
201:                            ci.colName, ci.dataType);
202:                } else if (isIntegralType(ci.dataType)) {
203:                    return new MaxIncFIDMapper(schema, tableName, ci.colName,
204:                            ci.dataType, this .returnFIDColumnsAsAttributes);
205:                } else {
206:                    return new BasicFIDMapper(ci.colName, ci.size,
207:                            this .returnFIDColumnsAsAttributes);
208:                }
209:            }
210:
211:            /**
212:             * DOCUMENT ME!
213:             *
214:             * @param schema
215:             * @param tableName
216:             * @param connection
217:             *
218:             */
219:            protected FIDMapper buildNoPKMapper(String schema,
220:                    String tableName, Connection connection) {
221:                FIDMapper mapper;
222:                mapper = new NullFIDMapper();
223:
224:                return mapper;
225:            }
226:
227:            /**
228:             * Builds a FID mapper for multi column public columns
229:             *
230:             * @param schema
231:             * @param tableName
232:             * @param connection
233:             * @param colInfos
234:             *
235:             */
236:            protected FIDMapper buildMultiColumnFIDMapper(String schema,
237:                    String tableName, Connection connection,
238:                    ColumnInfo[] colInfos) {
239:                String[] colNames = new String[colInfos.length];
240:                int[] colTypes = new int[colInfos.length];
241:                int[] colSizes = new int[colInfos.length];
242:                int[] colDecimalDigits = new int[colInfos.length];
243:                boolean[] autoIncrement = new boolean[colInfos.length];
244:
245:                for (int i = 0; i < colInfos.length; i++) {
246:                    ColumnInfo ci = colInfos[i];
247:                    colNames[i] = ci.colName;
248:                    colTypes[i] = ci.dataType;
249:                    colSizes[i] = ci.size;
250:                    colDecimalDigits[i] = ci.decimalDigits;
251:                    autoIncrement[i] = ci.autoIncrement;
252:                }
253:
254:                return new MultiColumnFIDMapper(schema, tableName, colNames,
255:                        colTypes, colSizes, colDecimalDigits, autoIncrement);
256:            }
257:
258:            protected ColumnInfo[] getPkColumnInfo(String catalog,
259:                    String schema, String typeName, Connection conn)
260:                    throws SchemaNotFoundException, DataSourceException {
261:                ResultSet tableInfo = null;
262:                ResultSet pkInfo = null;
263:                boolean pkMetadataFound = false;
264:
265:                try {
266:                    DatabaseMetaData dbMetaData = conn.getMetaData();
267:
268:                    Map pkMap = new LinkedHashMap();
269:                    pkInfo = dbMetaData.getPrimaryKeys(catalog, schema,
270:                            typeName);
271:                    pkMetadataFound = true;
272:
273:                    while (pkInfo.next()) {
274:                        ColumnInfo ci = new ColumnInfo();
275:                        ci.colName = pkInfo.getString("COLUMN_NAME");
276:                        ci.keySeq = pkInfo.getInt("KEY_SEQ");
277:                        pkMap.put(ci.colName, ci);
278:                    }
279:
280:                    tableInfo = dbMetaData.getColumns(catalog, schema,
281:                            typeName, "%");
282:
283:                    boolean tableInfoFound = false;
284:
285:                    while (tableInfo.next()) {
286:                        tableInfoFound = true;
287:
288:                        String columnName = tableInfo.getString("COLUMN_NAME");
289:                        ColumnInfo ci = (ColumnInfo) pkMap.get(columnName);
290:
291:                        if (ci != null) {
292:                            ci.dataType = tableInfo.getInt("DATA_TYPE");
293:                            ci.size = tableInfo.getInt("COLUMN_SIZE");
294:                            ci.decimalDigits = tableInfo
295:                                    .getInt("DECIMAL_DIGITS");
296:                            ci.autoIncrement = isAutoIncrement(catalog, schema,
297:                                    typeName, conn, tableInfo, columnName,
298:                                    ci.dataType);
299:                        }
300:                    }
301:
302:                    if (!tableInfoFound) {
303:                        throw new SchemaNotFoundException(typeName);
304:                    }
305:
306:                    Collection columnInfos = pkMap.values();
307:
308:                    return (ColumnInfo[]) columnInfos
309:                            .toArray(new ColumnInfo[columnInfos.size()]);
310:                } catch (SQLException sqlException) {
311:                    JDBCUtils
312:                            .close(conn, Transaction.AUTO_COMMIT, sqlException);
313:                    conn = null; // prevent finally block from reclosing
314:
315:                    if (pkMetadataFound) {
316:                        throw new DataSourceException(
317:                                "SQL Error building FeatureType for "
318:                                        + typeName + " "
319:                                        + sqlException.getMessage(),
320:                                sqlException);
321:                    } else {
322:                        throw new SchemaNotFoundException(typeName,
323:                                sqlException);
324:                    }
325:                } finally {
326:                    JDBCUtils.close(tableInfo);
327:                }
328:            }
329:
330:            /**
331:             * Returns true if the specified column is auto-increment. This method is
332:             * left protected so that specific datastore implementations can put their
333:             * own logic, should the default one be ineffective or have bad
334:             * performance.  NOTE: the postgis subclass will call this with the
335:             * columnname and table name pre-double-quoted! Other DB may have to do
336:             * the same - please check your DB's documentation.
337:             *
338:             * @param catalog
339:             * @param schema
340:             * @param tableName
341:             * @param conn
342:             * @param tableInfo
343:             * @param columnName
344:             * @param dataType
345:             *
346:             *
347:             * @throws SQLException
348:             */
349:            protected boolean isAutoIncrement(String catalog, String schema,
350:                    String tableName, Connection conn, ResultSet tableInfo,
351:                    String columnName, int dataType) throws SQLException {
352:                // if it's not an integer type it can't be an auto increment type
353:                if (!isIntegralType(dataType)) {
354:                    return false;
355:                }
356:
357:                // ok, it's an integer. To know if it's an auto-increment let's have a look at resultset metadata
358:                // and try to force it to get just a single row for exploring the metadata
359:                boolean autoIncrement = false;
360:                Statement statement = null;
361:                ResultSet rs = null;
362:
363:                try {
364:                    statement = conn.createStatement();
365:                    statement.setFetchSize(1);
366:                    String query = "SELECT " + columnName + " FROM ";
367:                    if (schema != null) {
368:                        query = query + schema + "."; //the schema will default to public if not specified
369:                    }
370:                    query = query + tableName + " WHERE 0=1"; //DJB: the "where 0=1" will optimize if you have a lot of dead tuples 
371:                    rs = statement.executeQuery(query);
372:
373:                    // if the WHERE 0=1 give any data store problems, just remove it 
374:                    // and put a comment here as to why it caused problems.
375:                    java.sql.ResultSetMetaData rsInfo = rs.getMetaData();
376:                    autoIncrement = rsInfo.isAutoIncrement(1);
377:                } finally {
378:                    JDBCUtils.close(statement);
379:                    JDBCUtils.close(rs);
380:                }
381:
382:                return autoIncrement;
383:            }
384:
385:            /**
386:             * Returns true if the dataType for the column can serve as a primary key.
387:             * Note that this now returns true for a DECIMAL type, because oracle
388:             * Numbers are returned in jdbc as DECIMAL.  This may cause errors in very
389:             * rare cases somewhere down the line, but only if users do something
390:             * incredibly silly like defining a primary key with a double.
391:             *
392:             * @param dataType DOCUMENT ME!
393:             *
394:             * @return DOCUMENT ME!
395:             */
396:            protected boolean isIntegralType(int dataType) {
397:                return (dataType == Types.BIGINT)
398:                        || (dataType == Types.INTEGER)
399:                        || (dataType == Types.NUMERIC)
400:                        || (dataType == Types.SMALLINT)
401:                        || (dataType == Types.TINYINT)
402:                        || (dataType == Types.DECIMAL);
403:            }
404:
405:            protected boolean isTextType(int dataType) {
406:                return (dataType == Types.VARCHAR) || (dataType == Types.CHAR)
407:                        || (dataType == Types.CLOB);
408:            }
409:
410:            /**
411:             * @see org.geotools.data.jdbc.fidmapper.FIDMapperFactory#getMapper(org.geotools.feature.FeatureType)
412:             */
413:            public FIDMapper getMapper(FeatureType featureType) {
414:                return new BasicFIDMapper("ID", 255, false);
415:            }
416:
417:            /**
418:             * Simple class used as a struct to hold column informations used in this
419:             * factory
420:             *
421:             * @author Andrea Aime
422:             */
423:            protected class ColumnInfo implements  Comparable {
424:                public String colName;
425:                public int dataType;
426:                public int size;
427:                public int decimalDigits;
428:                public boolean autoIncrement;
429:                public int keySeq;
430:
431:                /**
432:                 * @see java.lang.Comparable#compareTo(java.lang.Object)
433:                 */
434:                public int compareTo(Object o) {
435:                    return keySeq - ((ColumnInfo) o).keySeq;
436:                }
437:
438:                public String toString() {
439:                    return "ColumnInfo, name(" + colName + "), type("
440:                            + dataType + ") size(" + size + ") decimalDigits("
441:                            + decimalDigits + ") autoIncrement("
442:                            + autoIncrement + ")";
443:                }
444:
445:                /**
446:                 * DOCUMENT ME!
447:                 *
448:                 * @return Returns the autoIncrement.
449:                 */
450:                public boolean isAutoIncrement() {
451:                    return autoIncrement;
452:                }
453:
454:                /**
455:                 * DOCUMENT ME!
456:                 *
457:                 * @return Returns the colName.
458:                 */
459:                public String getColName() {
460:                    return colName;
461:                }
462:
463:                /**
464:                 * DOCUMENT ME!
465:                 *
466:                 * @return Returns the dataType.
467:                 */
468:                public int getDataType() {
469:                    return dataType;
470:                }
471:
472:                /**
473:                 * DOCUMENT ME!
474:                 *
475:                 * @return Returns the decimalDigits.
476:                 */
477:                public int getDecimalDigits() {
478:                    return decimalDigits;
479:                }
480:
481:                /**
482:                 * DOCUMENT ME!
483:                 *
484:                 * @return Returns the size.
485:                 */
486:                public int getSize() {
487:                    return size;
488:                }
489:            }
490:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.