001    /*
002     * Copyright 2005 Stephen J. McConnell.
003     *
004     * Licensed  under the  Apache License,  Version 2.0  (the "License");
005     * you may not use  this file  except in  compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *   http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed  under the  License is distributed on an "AS IS" BASIS,
012     * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
013     * implied.
014     *
015     * See the License for the specific language governing permissions and
016     * limitations under the License.
017     */
018    
019    package net.dpml.state;
020    
021    import java.io.Serializable;
022    
023    
024    /**
025     * Default implemention of a state transition descriptor.
026     * 
027     * @author <a href="http://www.dpml.net">Digital Product Meta Library</a>
028     * @version 1.2.0
029     */
030    public class DefaultTransition implements Transition, Serializable
031    {
032        private final String m_name;
033        private final String m_target;
034        private final Operation m_operation;
035        
036        private transient State m_state;
037        
038       /**
039        * Creation of a new transition.
040        * @param name the transition name
041        * @param target the transit target state name
042        */
043        public DefaultTransition( final String name, final String target )
044        {
045            this( name, target, null );
046        }
047        
048       /**
049        * Creation of a new transition.
050        * @param name the transition name
051        * @param target the transit target state name
052        * @param operation optional transition operation
053        */
054        public DefaultTransition( final String name, final String target, final Operation operation )
055        {
056            if( null == name )
057            {
058                throw new NullPointerException( "name" );
059            }
060            if( null == target )
061            {
062                throw new NullPointerException( "target" );
063            }
064            m_name = name;
065            m_target = target;
066            m_operation = operation;
067        }
068        
069       /**
070        * Set the state that this transition is a part of.
071        * @param state the owning state
072        */
073        public void setState( State state )
074        {
075            if( null == state )
076            {
077                throw new NullPointerException( "state" );
078            }
079            if( null == m_state )
080            {
081                m_state = state;
082            }
083            else
084            {
085                throw new IllegalStateException( "State already set." );
086            }
087        }
088        
089       /**
090        * Return the state that this transition is a part of.
091        * @return the owning state
092        */
093        public State getState()
094        {
095            if( null != m_state )
096            {
097                return m_state;
098            }
099            else
100            {
101                throw new IllegalStateException( "Enclosing state has not been declared." );
102            }
103        }
104        
105       /**
106        * Return the transition name
107        * @return the name
108        */
109        public String getName()
110        {
111            return m_name;
112        }
113        
114       /**
115        * Return the transition target state name
116        * @return the target state name
117        */
118        public String getTargetName()
119        {
120            return m_target;
121        }
122        
123       /**
124        * Return an operation associated with the transition.
125        * @return a possibly null operation
126        */
127        public Operation getOperation()
128        {
129            return m_operation;
130        }
131        
132       /**
133        * Compare this object to another for equality.
134        * @param other the other object
135        * @return true if the object is equal to this object
136        */
137        public boolean equals( Object other )
138        {
139            if( null == other )
140            {
141                return false;
142            }
143            else if( other instanceof DefaultTransition )
144            {
145                DefaultTransition transition = (DefaultTransition) other;
146                if( !m_name.equals( transition.getName() ) )
147                {
148                    return false;
149                }
150                else if( !equals( m_target, transition.getTargetName() ) )
151                {
152                    return false;
153                }
154                else 
155                {
156                    return equals( m_operation, transition.getOperation() );
157                }
158            }
159            else
160            {
161                return false;
162            }
163        }
164        
165       /**
166        * Compute the hashcode for this instance.
167        * @return the hashcode value
168        */
169        public int hashCode()
170        {
171            int hash = m_name.hashCode();
172            hash ^= m_target.hashCode();
173            if( m_operation != null )
174            {
175                hash ^= m_operation.hashCode();
176            }
177            return hash;
178        }
179        
180        private boolean equals( Object a, Object b )
181        {
182            if( null == a )
183            {
184                return null == b;
185            }
186            else
187            {
188                return a.equals( b );
189            }
190        }
191        
192       /**
193        * Return a string representation of the instance.
194        * @return the string value
195        */
196        public String toString()
197        {
198            return "transition:" + getName() + " (target=" + m_target + ")";
199        }
200    }