001    //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/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: lbuesching $
047     * 
048     * @version $Revision: 31344 $, $Date: 2011-07-25 15:08:59 +0200 (Mo, 25 Jul 2011) $
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" ) || tmp.contains( "nord" ) ) {
151                    this.orientation = AO_NORTH;
152                } else if ( tmp.contains( "south" ) || tmp.contains( "sued" ) ) {
153                    this.orientation = AO_SOUTH;
154                } else if ( tmp.contains( "east" ) || tmp.contains( "ost" ) ) {
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( " units: " ).append( units ).toString();
221        }
222    
223        @Override
224        public boolean equals( Object otherAxis ) {
225            if ( otherAxis == null || !( otherAxis instanceof Axis ) ) {
226                return false;
227            }
228            Axis other = (Axis) otherAxis;
229            return this.units.equals( other.units ) && this.orientation == other.orientation;
230        }
231    
232        /**
233         * Implementation as proposed by Joshua Block in Effective Java (Addison-Wesley 2001), which supplies an even
234         * distribution and is relatively fast. It is created from field <b>f</b> as follows:
235         * <ul>
236         * <li>boolean -- code = (f ? 0 : 1)</li>
237         * <li>byte, char, short, int -- code = (int)f</li>
238         * <li>long -- code = (int)(f ^ (f &gt;&gt;&gt;32))</li>
239         * <li>float -- code = Float.floatToIntBits(f);</li>
240         * <li>double -- long l = Double.doubleToLongBits(f); code = (int)(l ^ (l &gt;&gt;&gt; 32))</li>
241         * <li>all Objects, (where equals(&nbsp;) calls equals(&nbsp;) for this field) -- code = f.hashCode(&nbsp;)</li>
242         * <li>Array -- Apply above rules to each element</li>
243         * </ul>
244         * <p>
245         * Combining the hash code(s) computed above: result = 37 * result + code;
246         * </p>
247         * 
248         * @return (int) ( result >>> 32 ) ^ (int) result;
249         * 
250         * @see java.lang.Object#hashCode()
251         */
252        @Override
253        public int hashCode() {
254            // the 2nd millionth prime, :-)
255            long code = 32452843;
256            if ( units != null ) {
257                code = code * 37 + units.hashCode();
258            }
259            long tmp = Double.doubleToLongBits( orientation );
260            code = code * 37 + (int) ( tmp ^ ( tmp >>> 32 ) );
261            return (int) ( code >>> 32 ) ^ (int) code;
262        }
263    
264        /**
265         * @return an 'English' representation for the Axis Orientation, or Unknown if the given direction is not known.
266         */
267        public String getOrientationAsString() {
268            switch ( orientation ) {
269            case AO_NORTH:
270                return "north";
271            case AO_SOUTH:
272                return "south";
273            case AO_EAST:
274                return "east";
275            case AO_WEST:
276                return "west";
277            case AO_FRONT:
278                return "front";
279            case AO_BACK:
280                return "back";
281            case AO_UP:
282                return "up";
283            case AO_DOWN:
284                return "down";
285            case AO_OTHER:
286                return "Other";
287            case AO_PERPENDICULAR:
288                return "perpendicular";
289            }
290            return "Unknown";
291        }
292    
293    }