/*---------------- FILE HEADER ------------------------------------------ This file is part of deegree. Copyright (C) 2001 by: EXSE, Department of Geography, University of Bonn http://www.giub.uni-bonn.de/exse/ lat/lon GmbH http://www.lat-lon.de It has been implemented within SEAGIS - An OpenSource implementation of OpenGIS specification (C) 2001, Institut de Recherche pour le D�veloppement (http://sourceforge.net/projects/seagis/) SEAGIS Contacts: Surveillance de l'Environnement Assist�e par Satellite Institut de Recherche pour le D�veloppement / US-Espace mailto:seasnet@teledetection.fr This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Contact: Andreas Poth lat/lon GmbH Aennchenstr. 19 53115 Bonn Germany E-Mail: poth@lat-lon.de Klaus Greve Department of Geography University of Bonn Meckenheimer Allee 166 53115 Bonn Germany E-Mail: klaus.greve@uni-bonn.de ---------------------------------------------------------------------------*/ package org.deegree.model.csct.cs; // OpenGIS dependencies import java.io.ObjectStreamException; import java.util.Locale; import java.util.NoSuchElementException; import javax.media.jai.EnumeratedParameter; import org.deegree.model.csct.resources.css.ResourceKeys; import org.deegree.model.csct.resources.css.Resources; /** * Orientation of axis. Some coordinate systems use non-standard orientations. * For example, the first axis in South African grids usually points West, * instead of East. This information is obviously relevant for algorithms * converting South African grid coordinates into Lat/Long. * <br><br> * The <em>natural ordering</em> for axis orientations is defined * as (EAST-WEST), (NORTH-SOUTH), (UP-DOWN), (FUTURE-PAST) and OTHER, which is * the ordering for a (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>) coordinate * system. This means that when an array of <code>AxisOrientation</code>s is sorted using * {@link java.util.Arrays#sort(Object[])}, EAST and WEST orientations will * appears first. NORTH and SOUTH will be next, followed by UP and DOWN, etc. * * Care should be exercised if <code>AxisOrientation</code>s are to be used as keys in * a sorted map or elements in a sorted set, as <code>AxisOrientation</code>'s natural * ordering is inconsistent with equals. See {@link java.lang.Comparable}, * {@link java.util.SortedMap} or {@link java.util.SortedSet} for more information. * * @version 1.00 * @author OpenGIS (www.opengis.org) * @author Martin Desruisseaux * * @see org.opengis.cs.CS_AxisOrientationEnum */ public final class AxisOrientation extends EnumeratedParameter implements Comparable { /** * Serial number for interoperability with different versions. */ private static final long serialVersionUID = 4649182002820021468L; /** * Unknown or unspecified axis orientation. * This can be used for local or fitted coordinate systems. */ public static final int CS_AO_Other=0; /** * Increasing ordinates values go North. * This is usually used for Grid Y coordinates and Latitude. */ public static final int CS_AO_North=1; /** * Increasing ordinates values go South. * This is rarely used. */ public static final int CS_AO_South=2; /** * Increasing ordinates values go East. * This is rarely used. */ public static final int CS_AO_East=3; /** * Increasing ordinates values go West. * This is usually used for Grid X coordinates and Longitude. */ public static final int CS_AO_West=4; /** * Increasing ordinates values go up. * This is used for vertical coordinate systems. */ public static final int CS_AO_Up=5; /** * Increasing ordinates values go down. * This is used for vertical coordinate systems. */ public static final int CS_AO_Down=6; /** * Unknown or unspecified axis orientation. * This can be used for local or fitted coordinate systems. * * @see org.opengis.cs.CS_AxisOrientationEnum#CS_AO_Other */ public static final AxisOrientation OTHER = new AxisOrientation( "OTHER", CS_AO_Other, ResourceKeys.OTHER ); /** * Increasing ordinates values go North. * This is usually used for Grid Y coordinates and Latitude. * * @see org.opengis.cs.CS_AxisOrientationEnum#CS_AO_North */ public static final AxisOrientation NORTH = new AxisOrientation( "NORTH", CS_AO_North, ResourceKeys.NORTH ); /** * Increasing ordinates values go South. * * @see org.opengis.cs.CS_AxisOrientationEnum#CS_AO_South */ public static final AxisOrientation SOUTH = new AxisOrientation( "SOUTH", CS_AO_South, ResourceKeys.SOUTH ); /** * Increasing ordinates values go East. * This is usually used for Grid X coordinates and Longitude. * * @see org.opengis.cs.CS_AxisOrientationEnum#CS_AO_East */ public static final AxisOrientation EAST = new AxisOrientation( "EAST", CS_AO_East, ResourceKeys.EAST ); /** * Increasing ordinates values go West. * * @see org.opengis.cs.CS_AxisOrientationEnum#CS_AO_West */ public static final AxisOrientation WEST = new AxisOrientation( "WEST", CS_AO_West, ResourceKeys.WEST ); /** * Increasing ordinates values go up. * This is used for vertical coordinate systems. * * @see org.opengis.cs.CS_AxisOrientationEnum#CS_AO_Up */ public static final AxisOrientation UP = new AxisOrientation( "UP", CS_AO_Up, ResourceKeys.UP ); /** * Increasing ordinates values go down. * This is used for vertical coordinate systems. * * @see org.opengis.cs.CS_AxisOrientationEnum#CS_AO_Down */ public static final AxisOrientation DOWN = new AxisOrientation( "DOWN", CS_AO_Down, ResourceKeys.DOWN ); /** * Increasing time go toward future. * This is used for temporal axis. */ public static final AxisOrientation FUTURE = new AxisOrientation( "FUTURE", 7, ResourceKeys.FUTURE ); /** * Increasing time go toward past. * This is used for temporal axis. */ public static final AxisOrientation PAST = new AxisOrientation( "PAST", 8, ResourceKeys.PAST ); /** * The last paired value. Paired value are NORTH-SOUTH, EAST-WEST, * UP-DOWN, FUTURE-PAST. */ private static final int LAST_PAIRED_VALUE = 8; /** * Axis orientations by value. Used to * canonicalize after deserialization. */ private static final AxisOrientation[] ENUMS = { OTHER, NORTH, SOUTH, EAST, WEST, UP, DOWN, FUTURE, PAST }; /** * The axis order. Used for {@link #compareTo} implementation. */ private static final AxisOrientation[] ORDER = { EAST, NORTH, UP, FUTURE }; /** * Resource key, used for building localized name. This key doesn't need to * be serialized, since {@link #readResolve} canonicalize enums according their * {@link #value}. Furthermore, its value is implementation-dependent (which is * an other raison why it should not be serialized). */ private transient final int key; /** * Construct a new enum with the specified value. */ private AxisOrientation( final String name, final int value, final int key ) { super( name, value ); this.key = key; } /** * Return the enum for the specified value. * This method is provided for compatibility with * {@link org.opengis.cs.CS_AxisOrientationEnum}. * * @param value The enum value. * @return The enum for the specified value. * @throws NoSuchElementException if there is no enum for the specified value. */ public static AxisOrientation getEnum( final int value ) throws NoSuchElementException { if ( value >= 0 && value < ENUMS.length ) return ENUMS[value]; throw new NoSuchElementException( String.valueOf( value ) ); } /** * Returns this enum's name in the specified locale. * If no name is available for the specified locale, a default one will be used. * * @param locale The locale, or <code>null</code> for the default locale. * @return Enum's name in the specified locale. */ public String getName( final Locale locale ) { return Resources.getResources( locale ).getString( key ); } /** * Returns the opposite orientation of this axis. * The opposite of North is South, and the opposite of South is North. * The same apply to East-West, Up-Down and Future-Past. * Other axis orientation are returned inchanged. */ public AxisOrientation inverse() { final int value = getValue() - 1; if ( value >= 0 && value < LAST_PAIRED_VALUE ) { return ENUMS[( value ^ 1 ) + 1]; } return this; } /** * Returns the "absolute" orientation of this axis. * This "absolute" operation is similar to the <code>Math.abs(int)</code> method * in that "negative" orientation (<code>SOUTH</code>, <code>WEST</code>, <code>DOWN</code>, * <code>PAST</code>) are changed for their positive counterpart (<code>NORTH</code>, * <code>EAST</code>, <code>UP</code>, <code>FUTURE</code>). More specifically, the * following conversion table is applied. * <br>  * <table align="center" cellpadding="3" border="1" bgcolor="F4F8FF"> * <tr bgcolor="#B9DCFF"> * <th>  Orientation  </th> * <th>  Absolute value  </th> * </tr> * <tr align="center"><td>NORTH</td> <td>NORTH</td> </tr> * <tr align="center"><td>SOUTH</td> <td>NORTH</td> </tr> * <tr align="center"><td>EAST</td> <td>EAST</td> </tr> * <tr align="center"><td>WEST</td> <td>EAST</td> </tr> * <tr align="center"><td>UP</td> <td>UP</td> </tr> * <tr align="center"><td>DOWN</td> <td>UP</td> </tr> * <tr align="center"><td>FUTURE</td><td>FUTURE</td></tr> * <tr align="center"><td>PAST</td> <td>FUTURE</td></tr> * <tr align="center"><td>OTHER</td> <td>OTHER</td> </tr> * </table> */ public AxisOrientation absolute() { final int value = getValue() - 1; if ( value >= 0 && value < LAST_PAIRED_VALUE ) { return ENUMS[( value & ~1 ) + 1]; } return this; } /** * Compares this <code>AxisOrientation</code> with the specified orientation. * The <em>natural ordering</em> is defined as (EAST-WEST), (NORTH-SOUTH), * (UP-DOWN), (FUTURE-PAST) and OTHER, which is the ordering for a * (<var>x</var>,<var>y</var>,<var>z</var>,<var>t</var>) coordinate system. * Two <code>AxisOrientation</code> that are among the same axis but with an * opposite direction (e.g. EAST vs WEST) are considered equal by this method. * * @param ao An <code>AxisOrientation</code> object to be compared with. * @throws ClassCastException if <code>ao</code> is not an <code>AxisOrientation</code> object. */ public int compareTo( final Object ao ) { final AxisOrientation that = (AxisOrientation) ao; final int thisOrder = this.absolute().getOrder(); final int thatOrder = that.absolute().getOrder(); if ( thisOrder > thatOrder ) return +1; if ( thisOrder < thatOrder ) return -1; return 0; } /** * Returns the order for this axis orientation * (i.e. the index in the {@link #ORDER} table). */ private int getOrder() { int i; for ( i = 0; i < ORDER.length; i++ ) if ( equals( ORDER[i] ) ) break; return i; } /** * Use a single instance of {@link AxisOrientation} after deserialization. * It allow client code to test <code>enum1==enum2</code> instead of * <code>enum1.equals(enum2)</code>. * * @return A single instance of this enum. * @throws ObjectStreamException is deserialization failed. */ private Object readResolve() { final int value = getValue(); if ( value >= 0 && value < ENUMS.length ) { return ENUMS[value]; // Canonicalize } return ENUMS[0]; // Collapse unknow value to a single canonical one } }