001    /*
002     * Copyright 1997-2004 The Apache Software Foundation
003     * Copyright 2005 Stephen J. McConnell, OSM
004     * 
005     * Licensed  under the  Apache License,  Version 2.0  (the "License");
006     * you may not use  this file  except in  compliance with the License.
007     * You may obtain a copy of the License at 
008     * 
009     *   http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed  under the  License is distributed on an "AS IS" BASIS,
013     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
014     * implied.
015     * 
016     * See the License for the specific language governing permissions and
017     * limitations under the License.
018     */
019     
020    package net.dpml.lang;
021    
022    import java.util.Map;
023    import java.io.Serializable;
024    
025    /**
026     * Basic enum class for type-safe enums. Should be used as an abstract base. For example:
027     *
028     * <pre>
029     * import net.dpml.lang.Enum;
030     *
031     * public final class Color extends Enum {
032     *   public static final Color RED = new Color( "Red" );
033     *   public static final Color GREEN = new Color( "Green" );
034     *   public static final Color BLUE = new Color( "Blue" );
035     *
036     *   private Color( final String color )
037     *   {
038     *     super( color );
039     *   }
040     * }
041     * </pre>
042     *
043     * If further operations, such as iterating over all items, are required, the
044     * {@link #Enum(String, Map)} constructor can be used to populate a <code>Map</code>, from which
045     * further functionality can be derived:
046     * <pre>
047     * public final class Color extends Enum {
048     *   static final Map map = new HashMap();
049     *
050     *   public static final Color RED = new Color( "Red", map );
051     *   public static final Color GREEN = new Color( "Green", map );
052     *   public static final Color BLUE = new Color( "Blue", map );
053     *
054     *   private Color( final String color, final Map map )
055     *   {
056     *     super( color, map );
057     *   }
058     *
059     *   public static Iterator iterator()
060     *   {
061     *     return map.values().iterator();
062     *   }
063     * }
064     * </pre>
065     *
066     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
067     * @version 1.1.0
068     */
069    public abstract class Enum implements Serializable
070    {
071        /**
072         * The string representation of the Enum.
073         */
074        private final String m_name;
075    
076        /**
077         * Constructor to add a new named item.
078         *
079         * @param name Name of the item.
080         */
081        protected Enum( final String name )
082        {
083            this( name, null );
084        }
085    
086        /**
087         * Constructor to add a new named item.
088         *
089         * @param name Name of the item.
090         * @param map A <code>Map</code> to which newly constructed instances will be added.
091         */
092        protected Enum( final String name, final Map map )
093        {
094            m_name = name;
095            if( null != map )
096            {
097                map.put( name, this );
098            }
099        }
100    
101        /**
102         * Tests for equality. Two Enum:s are considered equal
103         * if they are of the same class and have the same names.
104         *
105         * @param o the other object
106         * @return the equality status
107         */
108        public boolean equals( Object o )
109        {
110            if( this == o )
111            {
112                return true;
113            }
114            if( !( o instanceof Enum ) )
115            {
116                return false;
117            }
118            final Enum enumerated = (Enum) o;
119            if( !getClass().equals( enumerated.getClass() ) )
120            {
121                return false;
122            }
123            if( m_name != null ) 
124            {
125                if( !m_name.equals( enumerated.m_name ) )
126                {
127                    return false;
128                }
129            }
130            else
131            {
132                if( enumerated.m_name != null  )
133                {
134                    return false;
135                }
136            }
137            return true;
138        }
139    
140       /** 
141        * Compute the hashcode.
142        * @return the hashcode value
143        */
144        public int hashCode()
145        {
146            int result = 0;
147            if( m_name != null )
148            {
149                result = m_name.hashCode();
150            }
151            result = 29 * result + getClass().hashCode();
152            return result;
153        }
154    
155        /**
156         * Retrieve the name of this Enum item, set in the constructor.
157         * @return the name <code>String</code> of this Enum item
158         */
159        public final String getName()
160        {
161            return m_name;
162        }
163    
164        /**
165         * Human readable description of this Enum item in the form <code>type:name</code>, eg.:
166         * <code>Color:Red</code>.
167         * @return the string representation
168         */
169        public String toString()
170        {
171            return getClass().getName() + ":" + m_name;
172        }
173    }