001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_testing/src/org/deegree/crs/components/Axis.java $
002    /*----------------------------------------------------------------------------
003     This file is part of deegree, http://deegree.org/
004     Copyright (C) 2001-2009 by:
005       Department of Geography, University of Bonn
006     and
007       lat/lon GmbH
008    
009     This library is free software; you can redistribute it and/or modify it under
010     the terms of the GNU Lesser General Public License as published by the Free
011     Software Foundation; either version 2.1 of the License, or (at your option)
012     any later version.
013     This library is distributed in the hope that it will be useful, but WITHOUT
014     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
015     FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
016     details.
017     You should have received a copy of the GNU Lesser General Public License
018     along with this library; if not, write to the Free Software Foundation, Inc.,
019     59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
020    
021     Contact information:
022    
023     lat/lon GmbH
024     Aennchenstr. 19, 53177 Bonn
025     Germany
026     http://lat-lon.de/
027    
028     Department of Geography, University of Bonn
029     Prof. Dr. Klaus Greve
030     Postfach 1147, 53001 Bonn
031     Germany
032     http://www.geographie.uni-bonn.de/deegree/
033    
034     e-mail: info@deegree.org
035    ----------------------------------------------------------------------------*/
036    
037    package org.deegree.crs.components;
038    
039    import java.io.Serializable;
040    
041    /**
042     * The <code>Axis</code> class describe the orientation, unit and the name of a crs-axis.
043     *
044     * @author <a href="mailto:bezema@lat-lon.de">Rutger Bezema</a>
045     *
046     * @author last edited by: $Author: mschneider $
047     *
048     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
049     *
050     */
051    
052    public class Axis implements Serializable {
053    
054        private static final long serialVersionUID = -4527409382797041807L;
055    
056        /**
057         * Axis is pointing NORTH ( == -SOUTH) e.g Polar axis positive northwards.
058         */
059        public static final int AO_NORTH = 1;
060    
061        /**
062         * Axis is pointing SOUTH ( == -NORTH )
063         */
064        public static final int AO_SOUTH = -AO_NORTH;
065    
066        /**
067         * Axis is pointing WEST( == -EAST)
068         */
069        public static final int AO_WEST = 2;
070    
071        /**
072         * Axis is pointing EAST( == -WEST) the intersection of the equator with longitude 90°E.
073         */
074        public static final int AO_EAST = -AO_WEST;
075    
076        /**
077         * Axis is pointing UP ( == -DOWN ),
078         */
079        public static final int AO_UP = 3;
080    
081        /**
082         * Axis is pointing DOWN ( == -UP)
083         */
084        public static final int AO_DOWN = -AO_UP;
085    
086        /**
087         * Axis is pointing FRONT( == -BACK), e.g. the Axis through the intersection of the Greenwich meridian and equator.
088         */
089        public static final int AO_FRONT = 4;
090    
091        /**
092         * Axis is pointing BACK ( == -FRONT) e.g. the Axis through the intersection of the opposite of the Greenwich
093         * meridian and equator.
094         */
095        public static final int AO_BACK = -AO_FRONT;
096    
097        /**
098         * Axis is pointing PERPENDICULAR to the earth's surface, which is used for a vertical axis.
099         */
100        public static final int AO_PERPENDICULAR = 5;
101    
102        /**
103         * Axis is pointing in an OTHER direction, which is not specified.
104         */
105        public static final int AO_OTHER = Integer.MAX_VALUE;
106    
107        private Unit units;
108    
109        private String name;
110    
111        private int orientation;
112    
113        /**
114         * @param units
115         *            of this axis
116         * @param name
117         *            of this axis (e.g. longitude...)
118         * @param orientation
119         *            of the positive scale direction, one of Axis.AO*. If an unknown value is supplied AO_OTHER is assumed.
120         */
121        public Axis( Unit units, String name, final int orientation ) {
122            this.units = units;
123            this.name = name;
124            this.orientation = orientation;
125            if ( orientation != AO_NORTH && orientation != AO_SOUTH && orientation != AO_WEST && orientation != AO_EAST
126                 && orientation != AO_UP && orientation != AO_DOWN && orientation != AO_FRONT && orientation != AO_BACK
127                 && orientation != AO_PERPENDICULAR ) {
128                this.orientation = AO_OTHER;
129            }
130    
131        }
132    
133        /**
134         * Parses the given orientation and creates a valid orientation of it's non-case-sensitive version. If no conversion
135         * was found, {@link #AO_OTHER} will be used.
136         *
137         * @param units
138         *            of the axis.
139         * @param name
140         *            of the axis.
141         * @param orientation
142         *            of the axis as a string for example north
143         */
144        public Axis( Unit units, String name, String orientation ) {
145            this.units = units;
146            this.name = name;
147            this.orientation = AO_OTHER;
148            if ( orientation != null ) {
149                String tmp = orientation.trim().toLowerCase();
150                if ( tmp.contains( "north" ) ) {
151                    this.orientation = AO_NORTH;
152                } else if ( tmp.contains( "south" ) ) {
153                    this.orientation = AO_SOUTH;
154                } else if ( tmp.contains( "east" ) ) {
155                    this.orientation = AO_EAST;
156                } else if ( tmp.contains( "west" ) ) {
157                    this.orientation = AO_WEST;
158                } else if ( tmp.contains( "front" ) ) {
159                    this.orientation = AO_FRONT;
160                } else if ( tmp.contains( "back" ) ) {
161                    this.orientation = AO_BACK;
162                } else if ( tmp.contains( "up" ) ) {
163                    this.orientation = AO_UP;
164                } else if ( tmp.contains( "down" ) ) {
165                    this.orientation = AO_DOWN;
166                } else if ( tmp.contains( "perpendicular" ) ) {
167                    this.orientation = AO_PERPENDICULAR;
168                }
169            }
170        }
171    
172        /**
173         * An Axis with unit set to metre.
174         *
175         * @param name
176         *            of this axis (e.g. longitude...)
177         * @param orientation
178         *            of the positive scale direction, one of Axis.AO*. If an unknown value is supplied AO_OTHER is assumed.
179         */
180        public Axis( String name, final int orientation ) {
181            this( Unit.METRE, name, orientation );
182        }
183    
184        /**
185         * Parses the given orientation and creates a valid orientation of it's non-case-sensitive version. If no conversion
186         * was found, {@link #AO_OTHER} will be used. This axis will have metres as it's unit.
187         *
188         * @param name
189         *            of the axis
190         * @param orientation
191         *            of the axis as a string for example north
192         */
193        public Axis( String name, final String orientation ) {
194            this( Unit.METRE, name, orientation );
195        }
196    
197        /**
198         * @return the name.
199         */
200        public final String getName() {
201            return name;
202        }
203    
204        /**
205         * @return the orientation.
206         */
207        public final int getOrientation() {
208            return orientation;
209        }
210    
211        /**
212         * @return the units.
213         */
214        public final Unit getUnits() {
215            return units;
216        }
217    
218        @Override
219        public String toString() {
220            return new StringBuilder( "name: " ).append( name ).append( " orientation: " ).append( getOrientationAsString() ).append(
221                                                                                                                                      " units: " ).append(
222                                                                                                                                                           units ).toString();
223        }
224    
225        @Override
226        public boolean equals( Object otherAxis ) {
227            if ( otherAxis == null || !( otherAxis instanceof Axis ) ) {
228                return false;
229            }
230            Axis other = (Axis) otherAxis;
231            return this.units.equals( other.units ) && this.orientation == other.orientation;
232        }
233    
234        /**
235         * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
236         * distribution and is relatively fast. It is created from field <b>f</b> as follows:
237         * <ul>
238         * <li>boolean -- code = (f ? 0 : 1)</li>
239         * <li>byte, char, short, int -- code = (int)f</li>
240         * <li>long -- code = (int)(f ^ (f &gt;&gt;&gt;32))</li>
241         * <li>float -- code = Float.floatToIntBits(f);</li>
242         * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l &gt;&gt;&gt; 32))</li>
243         * <li>all Objects, (where equals(&nbsp;) calls equals(&nbsp;) for this field) -- code = f.hashCode(&nbsp;)</li>
244         * <li>Array -- Apply above rules to each element</li>
245         * </ul>
246         * <p>
247         * Combining the hash code(s) computed above: result = 37 * result + code;
248         * </p>
249         *
250         * @return (int) ( result >>> 32 ) ^ (int) result;
251         *
252         * @see java.lang.Object#hashCode()
253         */
254        @Override
255        public int hashCode() {
256            // the 2nd millionth prime, :-)
257            long code = 32452843;
258            if ( units != null ) {
259                code = code * 37 + units.hashCode();
260            }
261            long tmp = Double.doubleToLongBits( orientation );
262            code = code * 37 + (int) ( tmp ^ ( tmp >>> 32 ) );
263            return (int) ( code >>> 32 ) ^ (int) code;
264        }
265    
266        /**
267         * @return an 'English' representation for the Axis Orientation, or Unknown if the given direction is not known.
268         */
269        public String getOrientationAsString() {
270            switch ( orientation ) {
271            case AO_NORTH:
272                return "north";
273            case AO_SOUTH:
274                return "south";
275            case AO_EAST:
276                return "east";
277            case AO_WEST:
278                return "west";
279            case AO_FRONT:
280                return "front";
281            case AO_BACK:
282                return "back";
283            case AO_UP:
284                return "up";
285            case AO_DOWN:
286                return "down";
287            case AO_OTHER:
288                return "Other";
289            case AO_PERPENDICULAR:
290                return "perpendicular";
291            }
292            return "Unknown";
293        }
294    
295    }