001    package sale;
002    
003    import sale.events.*;
004    
005    import util.*;
006    
007    /**
008     * This is a rather simple implementation of the {@link Timer Timer} interface.
009     *
010     * <p>It requires a Time object to work with. Every increasing of the timer has
011     * to be explicitly triggered by the {@link #goAhead goAhead()} method.</p>
012     *
013     * @author Stephan Gambke
014     * @version 2.0 11/06/1999
015     * @since v2.0
016     */
017    public class StepTimer extends Object implements Timer {
018    
019        /**
020             * ID for serialization.
021             */
022            private static final long serialVersionUID = -5909676359937433717L;
023    
024            /**
025         * The current Time.
026         *
027         * @serial
028         */
029        protected Time m_tTime;
030    
031        /**
032         * The current interval for the {@link #goAhead} method.
033         *
034         * @serial
035         */
036        private Object m_oInterval;
037    
038        /**
039         * The listeners registered with this timer.
040         *
041         * @serial
042         */
043        protected ListenerHelper m_lhListeners = new ListenerHelper();
044    
045        /**
046         * The number of the current time stamp.
047         *
048         * @serial
049         */
050        private long m_lTimeStamps;
051    
052        /**
053         * Create a new timer wich uses an instance of {@link Step Step} as the time object.
054         */
055        public StepTimer() {
056            this(new Step());
057        }
058    
059        /**
060         * Create a new timer wich uses the given {@link Time Time} object.
061         *
062         * @param tTimeObject the time object to use
063         */
064        public StepTimer(Time tTimeObject) {
065            super();
066    
067            m_tTime = tTimeObject;
068            m_oInterval = m_tTime.getDefaultInterval();
069        }
070    
071        /**
072         * Set the time and fire a <code>timeSet</code> event.
073         *
074         * <p>The time has to be in a format that can be processed by the {@link Time Time} object.</p>
075         *
076         * @override Never
077         *
078         * @param oTime the time to set
079         *
080         * @exception IllegalArgumentException if the set time does not meet the time object's class or format
081         * requirements
082         */
083        public void setTime(Object oTime) throws IllegalArgumentException {
084            m_tTime.setTime(oTime);
085            fireTimeSet();
086        }
087    
088        /**
089         * Get the current time. This is delegated to the {@link Time} object.
090         *
091         * @override Never
092         *
093         * @return an Object representing the current time, the exact type depends on the time object
094         */
095        public Object getTime() {
096            return m_tTime.getTime();
097        }
098    
099        /**
100         * Returns the object that contains the time.
101         *
102         * @override Never
103         *
104         * @return the Time object.
105         */
106        public Time getTimeObject() {
107            return m_tTime;
108        }
109    
110        /**
111         * Set the interval to be used by the {@link #goAhead goAhead()} method.
112         *
113         * <p>The given interval has to be of a proper type to be used with the time object's
114         * {@link Time#goAhead goAhead()} method.</p>
115         *
116         * @override Never
117         *
118         * @param oInterval the interval to be used
119         */
120        public void setInterval(Object oInterval) {
121            m_oInterval = oInterval;
122            fireIntervalSet();
123        }
124    
125        /**
126         * Get the current interval.
127         *
128         * @override Never
129         *
130         * @return an Object representing the current interval
131         */
132        public Object getInterval() {
133            return m_oInterval;
134        }
135    
136        /**
137         * Add a {@link sale.events.TimerListener TimerListener} which will receive
138         * {@link sale.events.TimerEvent TimerEvents} triggered by this timer.
139         *
140         * @override Never
141         *
142         * @param tlListener the listener to be registered.
143         */
144        public void addTimerListener(TimerListener tlListener) {
145            m_lhListeners.add(TimerListener.class, tlListener);
146        }
147    
148        /**
149         * Remove the given {@link sale.events.TimerListener TimerListener}.
150         *
151         * @override Never
152         *
153         * @param tlListener the listener to be deregistered.
154         */
155        public void removeTimerListener(TimerListener tlListener) {
156            m_lhListeners.remove(TimerListener.class, tlListener);
157        }
158    
159        /**
160         * Increase the time by the current interval.
161         *
162         * <p>If no interval has been set yet, the interval given by the {@link Time#getDefaultInterval()} method
163         * of the time object is used.</p>
164         *
165         * @override Never
166         *
167         * @exception IllegalArgumentException if the interval does not meet the time object's class or format
168         * requirements
169         */
170        public void goAhead() throws IllegalArgumentException {
171            m_tTime.goAhead(m_oInterval);
172            m_lTimeStamps = 0;
173            fireGoneAhead();
174        }
175    
176        /**
177         * Create and return a fresh time stamp.
178         *
179         * @override Never
180         *
181         * @return a fresh time stamp.
182         */
183        public Comparable<String> getTimeStamp() {
184            return m_tTime.getTimeStamp(++m_lTimeStamps);
185        }
186    
187        /**
188         * Fire a <code>timeSet</code> event.
189         *
190         * @override Never
191         */
192        protected void fireTimeSet() {
193            Object[] listeners = m_lhListeners.getListenerList();
194            TimerEvent e = null;
195    
196            for (int i = listeners.length - 2; i >= 0; i -= 2) {
197                if (listeners[i] == TimerListener.class) {
198                    if (e == null) {
199                        e = new TimerEvent(this);
200                    }
201                    ((TimerListener)listeners[i + 1]).onTimeSet(e);
202                }
203            }
204        }
205    
206        /**
207         * Fire an <code>intervalSet</code> event.
208         *
209         * @override Never
210         */
211        protected void fireIntervalSet() {
212            Object[] listeners = m_lhListeners.getListenerList();
213            TimerEvent e = null;
214    
215            for (int i = listeners.length - 2; i >= 0; i -= 2) {
216                if (listeners[i] == TimerListener.class) {
217                    if (e == null) {
218                        e = new TimerEvent(this);
219                    }
220                    ((TimerListener)listeners[i + 1]).onIntervalSet(e);
221                }
222            }
223        }
224    
225        /**
226         * Fire a <code>goneAhead</code> event.
227         *
228         * @override Never
229         */
230        protected void fireGoneAhead() {
231            Object[] listeners = m_lhListeners.getListenerList();
232            TimerEvent e = null;
233    
234            for (int i = listeners.length - 2; i >= 0; i -= 2) {
235                if (listeners[i] == TimerListener.class) {
236                    if (e == null) {
237                        e = new TimerEvent(this);
238                    }
239                    ((TimerListener)listeners[i + 1]).onGoneAhead(e);
240                }
241            }
242        }
243    }