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