Source Code Cross Referenced for OrderedAxisAuthorityFactory.java in  » GIS » GeoTools-2.4.1 » org » geotools » referencing » factory » 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 
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;
018:
019:        // J2SE dependencies and extensions
020:        import java.util.Map;
021:        import java.util.Arrays;
022:        import java.util.HashMap;
023:        import java.util.Comparator;
024:        import javax.units.Unit;
025:        import javax.units.SI;
026:        import javax.units.NonSI;
027:
028:        // OpenGIS dependencies
029:        import org.opengis.referencing.cs.*;
030:        import org.opengis.referencing.crs.CRSAuthorityFactory;
031:        import org.opengis.referencing.FactoryException;
032:
033:        // Geotools dependencies
034:        import org.geotools.factory.Hints;
035:        import org.geotools.factory.FactoryRegistryException;
036:        import org.geotools.referencing.ReferencingFactoryFinder;
037:        import org.geotools.referencing.cs.DefaultCoordinateSystemAxis;
038:        import org.geotools.resources.i18n.Errors;
039:        import org.geotools.resources.i18n.ErrorKeys;
040:
041:        /**
042:         * An authority factory which delegates all the work to an other factory, and reorder the axis in
043:         * some pre-determined order. This factory is mostly used by application expecting geographic
044:         * coordinates in (<var>longitude</var>, <var>latitude</var>) order, while most geographic CRS
045:         * specified in the <A HREF="http://www.epsg.org">EPSG database</A> use the opposite axis order.
046:         * <p>
047:         * It is better to avoid this class if you can. This class exists primarily for compatibility with
048:         * external data or applications that assume (<var>longitude</var>, <var>latitude</var>) axis order
049:         * no matter what the EPSG database said, for example Shapefiles.
050:         * <p>
051:         * The axis order can be specified at construction time as an array of {@linkplain AxisDirection
052:         * axis directions}. If no such array is explicitly specified, then the default order is
053:         * {@linkplain AxisDirection#EAST               East},
054:         * {@linkplain AxisDirection#EAST_NORTH_EAST    East-North-East},
055:         * {@linkplain AxisDirection#NORTH_EAST         North-East},
056:         * {@linkplain AxisDirection#NORTH_NORTH_EAST   North-North-East},
057:         * {@linkplain AxisDirection#NORTH              North},
058:         * {@linkplain AxisDirection#UP                 Up},
059:         * {@linkplain AxisDirection#GEOCENTRIC_X       Geocentric X},
060:         * {@linkplain AxisDirection#GEOCENTRIC_Y       Geocentric Y},
061:         * {@linkplain AxisDirection#GEOCENTRIC_Z       Geocentric Z},
062:         * {@linkplain AxisDirection#COLUMN_POSITIVE    Column},
063:         * {@linkplain AxisDirection#ROW_POSITIVE       Row},
064:         * {@linkplain AxisDirection#DISPLAY_RIGHT      Display right},
065:         * {@linkplain AxisDirection#DISPLAY_UP         Display up} and
066:         * {@linkplain AxisDirection#FUTURE             Future}.
067:         * This means that, for example, axis with East or West direction will be placed before any
068:         * axis with North or South direction. Axis directions not specified in the table (for example
069:         * {@link AxisDirection#OTHER OTHER}) will be ordered last. This is somewhat equivalent to the
070:         * ordering of {@link Double#NaN NaN} values in an array of {@code double}.
071:         * <p>
072:         * <strong>Notes:</strong>
073:         * <ul>
074:         *   <li>This class compares only the "{@linkplain AxisDirection#absolute absolute}" axis
075:         *       directions, so North and South are considered equivalent.</li>
076:         *   <li>The default direction order may changes in future Geotools version in order
077:         *       to fit what appears to be the most common usage on the market.</li>
078:         *   <li>The actual axis ordering is determined by the {@link #compare compare} method
079:         *       implementation. Subclasses may override this method if the want to provide a more
080:         *       sophesticated axis ordering.</li>
081:         * </ul>
082:         * <p>
083:         * For some authority factories, an instance of this class can be obtained by passing a
084:         * {@link Hints#FORCE_LONGITUDE_FIRST_AXIS_ORDER FORCE_LONGITUDE_FIRST_AXIS_ORDER} hint
085:         * to the <code>{@linkplain ReferencingFactoryFinder#getCRSAuthorityFactory
086:         * FactoryFinder.getCRSAuthorityFactory}(...)</code> method. Whatever this hint is supported
087:         * or not is authority dependent. Example:
088:         *
089:         * <blockquote><pre>
090:         * Hints                   hints = new Hints(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER, Boolean.TRUE);
091:         * CRSAuthorityFactory   factory = FactoryFinder.getCRSAuthorityFactory("EPSG", hints);
092:         * CoordinateReferenceSystem crs = factory.createCoordinateReferenceSystem("EPSG:4326");
093:         * </pre></blockquote>
094:         *
095:         * This class is named <cite>ordered axis authority factory</cite> instead of something like
096:         * <cite>longitude first axis order</cite> because the axis order can be user-supplied. The
097:         * (<var>longitude</var>, <var>latitude</var>) order just appears to be the default one.
098:         *
099:         * @since 2.2
100:         * @source $URL: http://svn.geotools.org/geotools/tags/2.4.1/modules/library/referencing/src/main/java/org/geotools/referencing/factory/OrderedAxisAuthorityFactory.java $
101:         * @version $Id: OrderedAxisAuthorityFactory.java 25406 2007-05-03 18:08:10Z desruisseaux $
102:         * @author Martin Desruisseaux
103:         *
104:         * @see Hints#FORCE_LONGITUDE_FIRST_AXIS_ORDER
105:         * @see Hints#FORCE_STANDARD_AXIS_UNITS
106:         * @tutorial http://docs.codehaus.org/display/GEOTOOLS/The+axis+order+issue
107:         */
108:        public class OrderedAxisAuthorityFactory extends
109:                TransformedAuthorityFactory implements  CSAuthorityFactory,
110:                CRSAuthorityFactory, Comparator/*<CoordinateSystemAxis>*/
111:        {
112:            /**
113:             * The default order for axis directions. Note that this array needs to contain only the
114:             * "{@linkplain AxisDirection#absolute absolute}" directions.
115:             *
116:             * REMINDER: If this array is modified, don't forget to update the class javadoc above.
117:             */
118:            private static final AxisDirection[] DEFAULT_ORDER = {
119:                    AxisDirection.EAST, AxisDirection.EAST_NORTH_EAST,
120:                    AxisDirection.NORTH_EAST, AxisDirection.NORTH_NORTH_EAST,
121:                    AxisDirection.NORTH, AxisDirection.UP,
122:                    AxisDirection.GEOCENTRIC_X, AxisDirection.GEOCENTRIC_Y,
123:                    AxisDirection.GEOCENTRIC_Z, AxisDirection.COLUMN_POSITIVE,
124:                    AxisDirection.ROW_POSITIVE, AxisDirection.DISPLAY_RIGHT,
125:                    AxisDirection.DISPLAY_UP, AxisDirection.FUTURE };
126:
127:            /**
128:             * The rank to be given to each axis direction. The rank is stored at the indice
129:             * corresponding to the direction {@linkplain AxisDirection#ordinal ordinal} value.
130:             */
131:            private final int[] directionRanks;
132:
133:            /**
134:             * {@code true} if this authority factory should also force the axis to their standard
135:             * direction. For example if {@code true}, then axis with increasing values toward South
136:             * will be converted to axis with increasing values toward North. The default value is
137:             * {@code false}.
138:             *
139:             * @see Hints#FORCE_STANDARD_AXIS_DIRECTIONS
140:             * @since 2.3
141:             */
142:            protected final boolean forceStandardDirections;
143:
144:            /**
145:             * {@code true} if this authority factory should also force all angular units to
146:             * decimal degrees and linear units to meters. The default value is {@code false}.
147:             *
148:             * @see Hints#FORCE_STANDARD_AXIS_UNITS
149:             * @since 2.3
150:             */
151:            protected final boolean forceStandardUnits;
152:
153:            /**
154:             * Creates a factory which will reorder the axis of all objects created by the default
155:             * authority factories. The factories are fetched using {@link ReferencingFactoryFinder}. This
156:             * constructor accepts the following hints:
157:             * <p>
158:             * <ul>
159:             *   <li>{@link Hints#FORCE_STANDARD_AXIS_UNITS}</li>
160:             *   <li>{@link Hints#FORCE_STANDARD_AXIS_DIRECTIONS}</li>
161:             *   <li>All hints understood by {@link ReferencingFactoryFinder}</li>
162:             * </ul>
163:             *
164:             * @param  authority The authority to wraps (example: {@code "EPSG"}). If {@code null},
165:             *         then all authority factories must be explicitly specified in the set of hints.
166:             * @param  userHints An optional set of hints, or {@code null} if none.
167:             * @param  axisOrder An array of axis directions that determine the axis order wanted,
168:             *         or {@code null} for the default axis order.
169:             * @throws FactoryRegistryException if at least one factory can not be obtained.
170:             * @throws IllegalArgumentException If at least two axis directions are colinear.
171:             *
172:             * @since 2.3
173:             */
174:            public OrderedAxisAuthorityFactory(final String authority,
175:                    final Hints userHints, final AxisDirection[] axisOrder)
176:                    throws FactoryRegistryException, IllegalArgumentException {
177:                super (authority, userHints);
178:                forceStandardUnits = booleanValue(userHints,
179:                        Hints.FORCE_STANDARD_AXIS_UNITS);
180:                forceStandardDirections = booleanValue(userHints,
181:                        Hints.FORCE_STANDARD_AXIS_DIRECTIONS);
182:                directionRanks = computeDirectionRanks(axisOrder);
183:                completeHints();
184:            }
185:
186:            /**
187:             * Creates a factory which will reorder the axis of all objects created by the supplied
188:             * factory. This constructor accepts the following optional hints:
189:             * <p>
190:             * <ul>
191:             *   <li>{@link Hints#FORCE_STANDARD_AXIS_UNITS}</li>
192:             *   <li>{@link Hints#FORCE_STANDARD_AXIS_DIRECTIONS}</li>
193:             * </ul>
194:             *
195:             * @param  factory   The factory that produces objects using arbitrary axis order.
196:             * @param  userHints An optional set of hints, or {@code null} if none.
197:             * @param  axisOrder An array of axis directions that determine the axis order wanted,
198:             *                   or {@code null} for the default axis order.
199:             * @throws IllegalArgumentException If at least two axis directions are colinear.
200:             *
201:             * @since 2.3
202:             */
203:            public OrderedAxisAuthorityFactory(
204:                    final AbstractAuthorityFactory factory,
205:                    final Hints userHints, final AxisDirection[] axisOrder)
206:                    throws IllegalArgumentException {
207:                super (factory);
208:                forceStandardUnits = booleanValue(userHints,
209:                        Hints.FORCE_STANDARD_AXIS_UNITS);
210:                forceStandardDirections = booleanValue(userHints,
211:                        Hints.FORCE_STANDARD_AXIS_DIRECTIONS);
212:                directionRanks = computeDirectionRanks(axisOrder);
213:                completeHints();
214:            }
215:
216:            /**
217:             * Returns the boolean value for the specified hint.
218:             */
219:            private static boolean booleanValue(final Hints userHints,
220:                    final Hints.Key key) {
221:                if (userHints != null) {
222:                    final Boolean value = (Boolean) userHints.get(key);
223:                    if (value != null) {
224:                        return value.booleanValue();
225:                    }
226:                }
227:                return false;
228:            }
229:
230:            /**
231:             * Completes the set of hints according the value currently set in this object.
232:             * This method is invoked by constructors only.
233:             */
234:            private void completeHints() {
235:                hints.put(Hints.FORCE_STANDARD_AXIS_UNITS, Boolean
236:                        .valueOf(forceStandardUnits));
237:                hints.put(Hints.FORCE_STANDARD_AXIS_DIRECTIONS, Boolean
238:                        .valueOf(forceStandardDirections));
239:                // The following hint has no effect on this class behaviour,
240:                // but tells to the user what this factory do about axis order.
241:                if (compare(DefaultCoordinateSystemAxis.EASTING,
242:                        DefaultCoordinateSystemAxis.NORTHING) < 0) {
243:                    hints.put(Hints.FORCE_LONGITUDE_FIRST_AXIS_ORDER,
244:                            Boolean.TRUE);
245:                }
246:            }
247:
248:            /**
249:             * Computes the rank for every direction in the specified. The rank is stored in an array
250:             * at the indice corresponding to the direction {@linkplain AxisDirection#ordinal ordinal}
251:             * value. This method is used by constructors for computing the {@link #directionRanks} field.
252:             *
253:             * @throws IllegalArgumentException If at least two axis directions are colinear.
254:             */
255:            private static int[] computeDirectionRanks(AxisDirection[] axisOrder)
256:                    throws IllegalArgumentException {
257:                if (axisOrder == null) {
258:                    axisOrder = DEFAULT_ORDER;
259:                }
260:                int length = 0;
261:                for (int i = 0; i < axisOrder.length; i++) {
262:                    final int ordinal = axisOrder[i].absolute().ordinal() + 1;
263:                    if (ordinal > length) {
264:                        length = ordinal;
265:                    }
266:                }
267:                final int[] directionRanks = new int[length];
268:                Arrays.fill(directionRanks, length);
269:                for (int i = 0; i < axisOrder.length; i++) {
270:                    final int ordinal = axisOrder[i].absolute().ordinal();
271:                    final int previous = directionRanks[ordinal];
272:                    if (previous != length) {
273:                        // TODO: Use the localized version of 'getName' in GeoAPI 2.1
274:                        throw new IllegalArgumentException(Errors.format(
275:                                ErrorKeys.COLINEAR_AXIS_$2, axisOrder[previous]
276:                                        .name(), axisOrder[i].name()));
277:                    }
278:                    directionRanks[ordinal] = i;
279:                }
280:                return directionRanks;
281:            }
282:
283:            /**
284:             * Returns the rank for the specified axis. Any axis that were not specified
285:             * at construction time will ordered after all known axis.
286:             */
287:            private final int rank(final CoordinateSystemAxis axis) {
288:                int c = axis.getDirection().absolute().ordinal();
289:                c = (c >= 0 && c < directionRanks.length) ? directionRanks[c]
290:                        : directionRanks.length;
291:                return c;
292:            }
293:
294:            /**
295:             * Compares two axis for order. This method is invoked automatically by the
296:             * {@link #replace(CoordinateSystem) replace} method for ordering the axis in a
297:             * coordinate system. The default implementation orders the axis according their
298:             * {@linkplain CoordinateSystemAxis#getDirection direction}, using the direction
299:             * table given at {@linkplain #OrderedAxisAuthorityFactory(AbstractAuthorityFactory,
300:             * Hints, AxisDirection[]) construction time} (see also the class description).
301:             * Subclasses may override this method if they want to define a more sophesticated
302:             * axis ordering.
303:             *
304:             * @param  axis1 The first axis to compare.
305:             * @param  axis2 The second axis to compare.
306:             * @return A negative integer if {@code axis1} should appears before {@code axis2}, or a
307:             *         positive number if {@code axis2} should appears before {@code axis1}, or 0 if
308:             *         the two axis are unordered one relative to the other.
309:             *
310:             * @todo The argument type will be changed to {@link CoordinateSystemAxis} when we will
311:             *       be allowed to compile for J2SE 1.5.
312:             *
313:             * @since 2.3
314:             */
315:            public int compare(final Object axis1, final Object axis2) {
316:                return rank((CoordinateSystemAxis) axis1)
317:                        - rank((CoordinateSystemAxis) axis2);
318:            }
319:
320:            /**
321:             * Replaces the specified unit, if applicable. This method is invoked automatically by the
322:             * {@link #replace(CoordinateSystem)} method. The default implementation replaces the unit
323:             * only if the {@link Hints#FORCE_STANDARD_AXIS_UNITS FORCE_STANDARD_AXIS_UNITS} hint was
324:             * specified as {@link Boolean#TRUE TRUE} at construction time. In such case, the default
325:             * substitution table is:
326:             * <p>
327:             * <ul>
328:             *   <li>Any linear units converted to {@linkplain SI#METER meters}</li>
329:             *   <li>{@linkplain SI#RADIAN Radians} and {@linkplain NonSI#GRADE grades} converted to
330:             *       {@linkplain NonSI#DEGREE_ANGLE decimal degrees}</li>
331:             * </ul>
332:             * <p>
333:             * This default substitution table may be expanded in future Geotools versions.
334:             *
335:             * @since 2.3
336:             */
337:            protected Unit replace(final Unit units) {
338:                if (forceStandardUnits) {
339:                    if (units.isCompatible(SI.METER)) {
340:                        return SI.METER;
341:                    }
342:                    if (units.equals(SI.RADIAN) || units.equals(NonSI.GRADE)) {
343:                        return NonSI.DEGREE_ANGLE;
344:                    }
345:                }
346:                return units;
347:            }
348:
349:            /**
350:             * Replaces the specified direction, if applicable. This method is invoked automatically by the
351:             * {@link #replace(CoordinateSystem)} method. The default implementation replaces the direction
352:             * only if the {@link Hints#FORCE_STANDARD_AXIS_DIRECTIONS FORCE_STANDARD_AXIS_DIRECTIONS} hint
353:             * was specified as {@link Boolean#TRUE TRUE} at construction time. In such case, the default
354:             * substitution table is as specified in the {@link AxisDirection#absolute} method.
355:             * Subclasses may override this method if they want to use a different substitution table.
356:             *
357:             * @since 2.3
358:             */
359:            protected AxisDirection replace(final AxisDirection direction) {
360:                return (forceStandardDirections) ? direction.absolute()
361:                        : direction;
362:            }
363:
364:            /**
365:             * Returns the error message for the specified coordinate system.
366:             * Used when throwing {@link FactoryException}.
367:             */
368:            private static final String getErrorMessage(
369:                    final CoordinateSystem cs) {
370:                return Errors.format(
371:                        ErrorKeys.UNSUPPORTED_COORDINATE_SYSTEM_$1, cs
372:                                .getName().getCode());
373:            }
374:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.