001    //$HeadURL: $
002    /*----------------    FILE HEADER  ------------------------------------------
003     This file is part of deegree.
004     Copyright (C) 2001-2008 by:
005     Department of Geography, University of Bonn
006     http://www.giub.uni-bonn.de/deegree/
007     lat/lon GmbH
008     http://www.lat-lon.de
009    
010     This library is free software; you can redistribute it and/or
011     modify it under the terms of the GNU Lesser General Public
012     License as published by the Free Software Foundation; either
013     version 2.1 of the License, or (at your option) any later version.
014     This library is distributed in the hope that it will be useful,
015     but WITHOUT ANY WARRANTY; without even the implied warranty of
016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     Lesser General Public License for more details.
018     You should have received a copy of the GNU Lesser General Public
019     License along with this library; if not, write to the Free Software
020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021     Contact:
022    
023     Andreas Poth
024     lat/lon GmbH
025     Aennchenstr. 19
026     53177 Bonn
027     Germany
028     E-Mail: poth@lat-lon.de
029    
030     Prof. Dr. Klaus Greve
031     Department of Geography
032     University of Bonn
033     Meckenheimer Allee 166
034     53115 Bonn
035     Germany
036     E-Mail: greve@giub.uni-bonn.de
037     ---------------------------------------------------------------------------*/
038    
039    package org.deegree.crs.components;
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:$
047     * 
048     * @version $Revision:$, $Date:$
049     * 
050     */
051    
052    public class Axis {
053    
054        /**
055         * Axis is pointing NORTH ( == -SOUTH) e.g Polar axis positive northwards.
056         */
057        public static final int AO_NORTH = 1;
058    
059        /**
060         * Axis is pointing SOUTH ( == -NORTH )
061         */
062        public static final int AO_SOUTH = -AO_NORTH;
063    
064        /**
065         * Axis is pointing WEST( == -EAST)
066         */
067        public static final int AO_WEST = 2;
068    
069        /**
070         * Axis is pointing EAST( == -WEST) the intersection of the equator with longitude 90°E.
071         */
072        public static final int AO_EAST = -AO_WEST;
073    
074        /**
075         * Axis is pointing UP ( == -DOWN ),
076         */
077        public static final int AO_UP = 3;
078    
079        /**
080         * Axis is pointing DOWN ( == -UP)
081         */
082        public static final int AO_DOWN = -AO_UP;
083    
084        /**
085         * Axis is pointing FRONT( == -BACK), e.g. the Axis through the intersection of the Greenwich meridian and equator.
086         */
087        public static final int AO_FRONT = 4;
088    
089        /**
090         * Axis is pointing BACK ( == -FRONT) e.g. the Axis through the intersection of the opposite of the Greenwich
091         * meridian and equator.
092         */
093        public static final int AO_BACK = -AO_FRONT;
094    
095        /**
096         * Axis is pointing in an OTHER direction, which is not specified.
097         */
098        public static final int AO_OTHER = Integer.MAX_VALUE;
099    
100        private Unit units;
101    
102        private String name;
103    
104        private int orientation;
105    
106        /**
107         * @param units
108         *            of this axis
109         * @param name
110         *            of this axis (e.g. longitude...)
111         * @param orientation
112         *            of the positive scale direction, one of Axis.AO*. If an unknown value is supplied AO_OTHER is assumed.
113         */
114        public Axis( Unit units, String name, final int orientation ) {
115            this.units = units;
116            this.name = name;
117            this.orientation = orientation;
118            if ( orientation != AO_NORTH && orientation != AO_SOUTH
119                 && orientation != AO_WEST
120                 && orientation != AO_EAST
121                 && orientation != AO_UP
122                 && orientation != AO_DOWN
123                 && orientation != AO_FRONT
124                 && orientation != AO_BACK ) {
125                this.orientation = AO_OTHER;
126            }
127    
128        }
129    
130        /**
131         * Parses the given orientation and creates a valid orientation of it's non-case-sensitive version. If no conversion
132         * was found, {@link #AO_OTHER} will be used.
133         * 
134         * @param units
135         *            of the axis.
136         * @param name
137         *            of the axis.
138         * @param orientation
139         *            of the axis as a string for example north
140         */
141        public Axis( Unit units, String name, String orientation ) {
142            this.units = units;
143            this.name = name;
144            this.orientation = AO_OTHER;
145            if ( orientation != null ) {
146                orientation = orientation.trim().toLowerCase();
147                if ( "north".equals( orientation ) ) {
148                    this.orientation = AO_NORTH;
149                } else if ( "south".equals( orientation ) ) {
150                    this.orientation = AO_SOUTH;
151                } else if ( "east".equals( orientation ) ) {
152                    this.orientation = AO_EAST;
153                } else if ( "west".equals( orientation ) ) {
154                    this.orientation = AO_WEST;
155                } else if ( "front".equals( orientation ) ) {
156                    this.orientation = AO_FRONT;
157                } else if ( "back".equals( orientation ) ) {
158                    this.orientation = AO_BACK;
159                } else if ( "up".equals( orientation ) ) {
160                    this.orientation = AO_UP;
161                } else if ( "down".equals( orientation ) ) {
162                    this.orientation = AO_DOWN;
163                }
164            }
165        }
166    
167        /**
168         * An Axis with unit set to metre.
169         * 
170         * @param name
171         *            of this axis (e.g. longitude...)
172         * @param orientation
173         *            of the positive scale direction, one of Axis.AO*. If an unknown value is supplied AO_OTHER is assumed.
174         */
175        public Axis( String name, final int orientation ) {
176            this( Unit.METRE, name, orientation );
177        }
178    
179        /**
180         * Parses the given orientation and creates a valid orientation of it's non-case-sensitive version. If no conversion
181         * was found, {@link #AO_OTHER} will be used. This axis will have metres as it's unit.
182         * 
183         * @param name
184         *            of the axis
185         * @param orientation
186         *            of the axis as a string for example north
187         */
188        public Axis( String name, final String orientation ) {
189            this( Unit.METRE, name, orientation );
190        }
191    
192        /**
193         * @return the name.
194         */
195        public final String getName() {
196            return name;
197        }
198    
199        /**
200         * @return the orientation.
201         */
202        public final int getOrientation() {
203            return orientation;
204        }
205    
206        /**
207         * @return the units.
208         */
209        public final Unit getUnits() {
210            return units;
211        }
212    
213        @Override
214        public String toString() {
215            return new StringBuilder( "name: " ).append( name )
216                                                .append( " orientation: " )
217                                                .append( getOrientationAsString() )
218                                                .append( " units: " )
219                                                .append( units )
220                                                .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            }
288            return "Unknown";
289        }
290    
291    }