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


001:        /*
002:         *    GeoTools - OpenSource mapping toolkit
003:         *    http://geotools.org
004:         *    (C) 2005-2006, GeoTools Project Managment Committee (PMC)
005:         *    (C) 2005, Institut de Recherche pour le Développement
006:         *   
007:         *    This library is free software; you can redistribute it and/or
008:         *    modify it under the terms of the GNU Lesser General Public
009:         *    License as published by the Free Software Foundation;
010:         *    version 2.1 of the License.
011:         *
012:         *    This library is distributed in the hope that it will be useful,
013:         *    but WITHOUT ANY WARRANTY; without even the implied warranty of
014:         *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
015:         *    Lesser General Public License for more details.
016:         */
017:        package org.geotools.referencing.factory.epsg;
018:
019:        // J2SE dependencies
020:        import java.util.Set;
021:        import java.util.AbstractSet;
022:        import java.util.AbstractMap;
023:        import java.util.Collections;
024:        import java.util.LinkedHashSet;
025:        import java.util.NoSuchElementException;
026:        import java.util.logging.Level;
027:        import java.util.logging.Logger;
028:        import java.util.logging.LogRecord;
029:        import java.io.Serializable;
030:        import java.io.ObjectStreamException;
031:        import java.sql.Connection;
032:        import java.sql.PreparedStatement;
033:        import java.sql.ResultSet;
034:        import java.sql.SQLException;
035:
036:        // OpenGIS dependencies
037:        import org.opengis.referencing.operation.Projection;
038:
039:        // Geotools dependencies
040:        import org.geotools.resources.i18n.Logging;
041:        import org.geotools.resources.i18n.LoggingKeys;
042:
043:        /**
044:         * A set of EPSG authority codes. This set requires a living connection to the EPSG database.
045:         * All {@link #iterator} method call creates a new {@link ResultSet} holding the codes. However,
046:         * call to {@link #contains} map directly to a SQL call.
047:         * <p>
048:         * Serialization of this class store a copy of all authority codes. The serialization
049:         * do not preserve any connection to the database.
050:         *
051:         * @since 2.2
052:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/factory/epsg/AuthorityCodes.java $
053:         * @version $Id: AuthorityCodes.java 27862 2007-11-12 19:51:19Z desruisseaux $
054:         * @author Martin Desruisseaux
055:         */
056:        final class AuthorityCodes extends AbstractSet implements  Serializable {
057:            /**
058:             * For compatibility with different versions.
059:             */
060:            private static final long serialVersionUID = 7105664579449680562L;
061:
062:            /**
063:             * The logger name.
064:             */
065:            private static final String LOGGER = "org.geotools.referencing.factory.epsg";
066:
067:            /**
068:             * The factory which is the owner of this set. One purpose of this field (even if it were not
069:             * used directly by this class) is to avoid garbage collection of the factory as long as this
070:             * set is in use. This is required because {@link DirectEpsgFactory#finalize} closes the JDBC
071:             * connections.
072:             */
073:            private final DirectEpsgFactory factory;
074:
075:            /**
076:             * The type for this code set. This is translated to the most appropriate
077:             * interface type even if the user supplied an implementation type.
078:             */
079:            public final Class type;
080:
081:            /**
082:             * {@code true} if {@link #type} is assignable to {@link Projection}.
083:             */
084:            private final boolean isProjection;
085:
086:            /**
087:             * A view of this set as a map with object's name as values, or {@code null} if none.
088:             * Will be created only when first needed.
089:             */
090:            private transient java.util.Map asMap;
091:
092:            /**
093:             * The SQL command to use for creating the {@code queryAll} statement.
094:             * Used for iteration over all codes.
095:             */
096:            final String sqlAll;
097:
098:            /**
099:             * The SQL command to use for creating the {@code querySingle} statement.
100:             * Used for fetching the description from a code.
101:             */
102:            private final String sqlSingle;
103:
104:            /**
105:             * The statement to use for querying all codes.
106:             * Will be created only when first needed.
107:             */
108:            private transient PreparedStatement queryAll;
109:
110:            /**
111:             * The statement to use for querying a single code.
112:             * Will be created only when first needed.
113:             */
114:            private transient PreparedStatement querySingle;
115:
116:            /**
117:             * The connection to the underlying database. This set should never close
118:             * this connection. Closing it is {@link DirectEpsgFactory}'s job.
119:             */
120:            private final Connection connection;
121:
122:            /**
123:             * The collection's size, or a negative value if not yet computed. The records will be counted
124:             * only when first needed. The special value -2 if set by {@link #isEmpty} if the size has not
125:             * yet been computed, but we know that the set is not empty.
126:             */
127:            private int size = -1;
128:
129:            /**
130:             * Creates a new set of authority codes for the specified type.
131:             *
132:             * @param  connection The connection to the EPSG database.
133:             * @param  table      The table to query.
134:             * @param  type       The type to query.
135:             * @param  factory    The factory originator.
136:             */
137:            public AuthorityCodes(final Connection connection,
138:                    final TableInfo table, final Class type,
139:                    final DirectEpsgFactory factory) {
140:                this .factory = factory;
141:                this .connection = connection;
142:                final StringBuffer buffer = new StringBuffer("SELECT ");
143:                buffer.append(table.codeColumn);
144:                if (table.nameColumn != null) {
145:                    buffer.append(", ").append(table.nameColumn);
146:                }
147:                buffer.append(" FROM ").append(table.table);
148:                boolean hasWhere = false;
149:                Class tableType = table.type;
150:                if (table.typeColumn != null) {
151:                    for (int i = 0; i < table.subTypes.length; i++) {
152:                        final Class candidate = table.subTypes[i];
153:                        if (candidate.isAssignableFrom(type)) {
154:                            buffer.append(" WHERE (").append(table.typeColumn)
155:                                    .append(" LIKE '").append(
156:                                            table.typeNames[i]).append("%'");
157:                            hasWhere = true;
158:                            tableType = candidate;
159:                            break;
160:                        }
161:                    }
162:                    if (hasWhere) {
163:                        buffer.append(')');
164:                    }
165:                }
166:                this .type = tableType;
167:                isProjection = Projection.class.isAssignableFrom(tableType);
168:                final int length = buffer.length();
169:                buffer.append(" ORDER BY ").append(table.codeColumn);
170:                sqlAll = factory.adaptSQL(buffer.toString());
171:                buffer.setLength(length);
172:                buffer.append(hasWhere ? " AND " : " WHERE ").append(
173:                        table.codeColumn).append(" = ?");
174:                sqlSingle = factory.adaptSQL(buffer.toString());
175:            }
176:
177:            /**
178:             * Returns all codes.
179:             */
180:            private ResultSet getAll() throws SQLException {
181:                assert Thread.holdsLock(this );
182:                if (queryAll != null) {
183:                    try {
184:                        return queryAll.executeQuery();
185:                    } catch (SQLException ignore) {
186:                        /*
187:                         * Failed to reuse an existing statement. This problem occurs in some occasions
188:                         * with the JDBC-ODBC bridge in Java 6 (the error message is "Invalid handle").
189:                         * I'm not sure where the bug come from (didn't noticed it when using HSQL). We
190:                         * will try again with a new statement created in the code after this 'catch'
191:                         * clause. Note that we set 'queryAll' to null first in case of failure during
192:                         * the 'prepareStatement(...)' execution.
193:                         */
194:                        queryAll.close();
195:                        queryAll = null;
196:                        recoverableException("getAll", ignore);
197:                    }
198:                }
199:                queryAll = connection.prepareStatement(sqlAll);
200:                return queryAll.executeQuery();
201:            }
202:
203:            /**
204:             * Returns a single code.
205:             */
206:            private ResultSet getSingle(final Object code) throws SQLException {
207:                assert Thread.holdsLock(this );
208:                if (querySingle == null) {
209:                    querySingle = connection.prepareStatement(sqlSingle);
210:                }
211:                querySingle.setString(1, code.toString());
212:                return querySingle.executeQuery();
213:            }
214:
215:            /**
216:             * Returns {@code true} if the code in the specified result set is acceptable.
217:             * This method handle projections in a special way.
218:             */
219:            private boolean isAcceptable(final ResultSet results)
220:                    throws SQLException {
221:                if (!isProjection) {
222:                    return true;
223:                }
224:                final String code = results.getString(1);
225:                synchronized (factory) {
226:                    return factory.isProjection(code);
227:                }
228:            }
229:
230:            /**
231:             * Returns {@code true} if the code in the specified code is acceptable.
232:             * This method handle projections in a special way.
233:             */
234:            private boolean isAcceptable(final String code) throws SQLException {
235:                if (!isProjection) {
236:                    return true;
237:                }
238:                synchronized (factory) {
239:                    return factory.isProjection(code);
240:                }
241:            }
242:
243:            /**
244:             * Returns {@code true} if this collection contains no elements.
245:             * This method fetch at most one row instead of counting all rows.
246:             */
247:            public synchronized boolean isEmpty() {
248:                if (size != -1) {
249:                    return size == 0;
250:                }
251:                boolean empty = true;
252:                try {
253:                    final ResultSet results = getAll();
254:                    while (results.next()) {
255:                        if (isAcceptable(results)) {
256:                            empty = false;
257:                            break;
258:                        }
259:                    }
260:                    results.close();
261:                } catch (SQLException exception) {
262:                    unexpectedException("isEmpty", exception);
263:                }
264:                size = empty ? 0 : -2;
265:                return empty;
266:            }
267:
268:            /**
269:             * Count the number of elements in the underlying result set.
270:             */
271:            public synchronized int size() {
272:                if (size >= 0) {
273:                    return size;
274:                }
275:                int count = 0;
276:                try {
277:                    final ResultSet results = getAll();
278:                    while (results.next()) {
279:                        if (isAcceptable(results)) {
280:                            count++;
281:                        }
282:                    }
283:                    results.close();
284:                } catch (SQLException exception) {
285:                    unexpectedException("size", exception);
286:                }
287:                size = count; // Stores only on success.
288:                return count;
289:            }
290:
291:            /**
292:             * Returns {@code true} if this collection contains the specified element.
293:             */
294:            public synchronized boolean contains(final Object code) {
295:                boolean exists = false;
296:                if (code != null)
297:                    try {
298:                        final ResultSet results = getSingle(code);
299:                        while (results.next()) {
300:                            if (isAcceptable(results)) {
301:                                exists = true;
302:                                break;
303:                            }
304:                        }
305:                        results.close();
306:                    } catch (SQLException exception) {
307:                        unexpectedException("contains", exception);
308:                    }
309:                return exists;
310:            }
311:
312:            /**
313:             * Returns an iterator over the codes. The iterator is backed by a living {@link ResultSet},
314:             * which will be closed as soon as the iterator reach the last element.
315:             */
316:            public synchronized java.util.Iterator iterator() {
317:                try {
318:                    final Iterator iterator = new Iterator(getAll());
319:                    /*
320:                     * Set the statement to null without closing it, in order to force a new statement
321:                     * creation if getAll() is invoked before the iterator finish its iteration.  This
322:                     * is needed because only one ResultSet is allowed for each Statement.
323:                     */
324:                    queryAll = null;
325:                    return iterator;
326:                } catch (SQLException exception) {
327:                    unexpectedException("iterator", exception);
328:                    return Collections.EMPTY_SET.iterator();
329:                }
330:            }
331:
332:            /**
333:             * Returns a serializable copy of this set. This method is invoked automatically during
334:             * serialization. The serialised set of authority code is disconnected from the underlying
335:             * database.
336:             */
337:            protected Object writeReplace() throws ObjectStreamException {
338:                return new LinkedHashSet(this );
339:            }
340:
341:            /**
342:             * Closes the underlying statements. Note: this method is also invoked directly
343:             * by {@link DirectEpsgFactory#dispose}, which is okay in this particular case since
344:             * the implementation of this method can be executed an arbitrary amount of times.
345:             */
346:            protected synchronized void finalize() throws SQLException {
347:                if (querySingle != null) {
348:                    querySingle.close();
349:                    querySingle = null;
350:                }
351:                if (queryAll != null) {
352:                    queryAll.close();
353:                    queryAll = null;
354:                }
355:            }
356:
357:            /**
358:             * Invoked when an exception occured. This method just log a warning.
359:             */
360:            private static void unexpectedException(final String method,
361:                    final SQLException exception) {
362:                unexpectedException(AuthorityCodes.class, method, exception);
363:            }
364:
365:            /**
366:             * Invoked when an exception occured. This method just log a warning.
367:             */
368:            static void unexpectedException(final Class classe,
369:                    final String method, final SQLException exception) {
370:                org.geotools.util.logging.Logging.unexpectedException(LOGGER,
371:                        classe, method, exception);
372:            }
373:
374:            /**
375:             * Invoked when a recoverable exception occured.
376:             */
377:            private static void recoverableException(final String method,
378:                    final SQLException exception) {
379:                // Uses the FINE level instead of WARNING because it may be a recoverable error.
380:                LogRecord record = Logging.format(Level.FINE,
381:                        LoggingKeys.UNEXPECTED_EXCEPTION);
382:                record.setSourceClassName(AuthorityCodes.class.getName());
383:                record.setSourceMethodName(method);
384:                record.setThrown(exception);
385:                org.geotools.util.logging.Logging.getLogger(LOGGER).log(record);
386:            }
387:
388:            /**
389:             * The iterator over the codes. This inner class must kept a reference toward the enclosing
390:             * {@link AuthorityCodes} in order to prevent a call to {@link AuthorityCodes#finalize}
391:             * before the iteration is finished.
392:             */
393:            private final class Iterator implements  java.util.Iterator {
394:                /** The result set, or {@code null} if there is no more elements. */
395:                private ResultSet results;
396:
397:                /** The next code. */
398:                private transient String next;
399:
400:                /** Creates a new iterator for the specified result set. */
401:                Iterator(final ResultSet results) throws SQLException {
402:                    assert Thread.holdsLock(AuthorityCodes.this );
403:                    this .results = results;
404:                    toNext();
405:                }
406:
407:                /** Moves to the next element. */
408:                private void toNext() throws SQLException {
409:                    while (results.next()) {
410:                        next = results.getString(1);
411:                        if (isAcceptable(next)) {
412:                            return;
413:                        }
414:                    }
415:                    finalize();
416:                }
417:
418:                /** Returns {@code true} if there is more elements. */
419:                public boolean hasNext() {
420:                    return results != null;
421:                }
422:
423:                /** Returns the next element. */
424:                public Object next() {
425:                    if (results == null) {
426:                        throw new NoSuchElementException();
427:                    }
428:                    final String current = next;
429:                    try {
430:                        toNext();
431:                    } catch (SQLException exception) {
432:                        results = null;
433:                        unexpectedException(Iterator.class, "next", exception);
434:                    }
435:                    return current;
436:                }
437:
438:                /** Always throws an exception, since this iterator is read-only. */
439:                public void remove() {
440:                    throw new UnsupportedOperationException();
441:                }
442:
443:                /** Closes the underlying result set. */
444:                protected void finalize() throws SQLException {
445:                    next = null;
446:                    if (results != null) {
447:                        final PreparedStatement owner = (PreparedStatement) results
448:                                .getStatement();
449:                        results.close();
450:                        results = null;
451:                        synchronized (AuthorityCodes.this ) {
452:                            /*
453:                             * We don't need the statement anymore. Gives it back to the enclosing class
454:                             * in order to avoid creating a new one when AuthorityCodes.getAll() will be
455:                             * invoked again,  or closes the statement if getAll() already created a new
456:                             * statement anyway.
457:                             */
458:                            assert owner != queryAll;
459:                            if (queryAll == null) {
460:                                queryAll = owner;
461:                            } else {
462:                                owner.close();
463:                            }
464:                        }
465:                    }
466:                }
467:            }
468:
469:            /**
470:             * Returns a view of this set as a map with object's name as value, or {@code null} if none.
471:             */
472:            final java.util.Map asMap() {
473:                if (asMap == null) {
474:                    asMap = new Map();
475:                }
476:                return asMap;
477:            }
478:
479:            /**
480:             * A view of {@link AuthorityCodes} as a map, with authority codes as key and
481:             * object names as values.
482:             */
483:            private final class Map extends AbstractMap {
484:                /**
485:                 * Returns the number of key-value mappings in this map.
486:                 */
487:                public int size() {
488:                    return AuthorityCodes.this .size();
489:                }
490:
491:                /**
492:                 * Returns {@code true} if this map contains no key-value mappings.
493:                 */
494:                public boolean isEmpty() {
495:                    return AuthorityCodes.this .isEmpty();
496:                }
497:
498:                /**
499:                 * Returns the description to which this map maps the specified EPSG code.
500:                 */
501:                public Object get(final Object code) {
502:                    String value = null;
503:                    if (code != null)
504:                        try {
505:                            synchronized (AuthorityCodes.this ) {
506:                                final ResultSet results = getSingle(code);
507:                                while (results.next()) {
508:                                    if (isAcceptable(results)) {
509:                                        value = results.getString(2);
510:                                        break;
511:                                    }
512:                                }
513:                                results.close();
514:                            }
515:                        } catch (SQLException exception) {
516:                            unexpectedException("get", exception);
517:                        }
518:                    return value;
519:                }
520:
521:                /**
522:                 * Returns {@code true} if this map contains a mapping for the specified EPSG code.
523:                 */
524:                public boolean containsKey(final Object key) {
525:                    return contains(key);
526:                }
527:
528:                /**
529:                 * Returns a set view of the keys contained in this map.
530:                 */
531:                public Set keySet() {
532:                    return AuthorityCodes.this ;
533:                }
534:
535:                /**
536:                 * Returns a set view of the mappings contained in this map.
537:                 *
538:                 * @todo Not yet implemented.
539:                 */
540:                public Set entrySet() {
541:                    throw new UnsupportedOperationException();
542:                }
543:            }
544:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.