View Javadoc

1   /*
2    *  File: TimeMachine.java 
3    *  Copyright (c) 2004-2007  Peter Kliem (Peter.Kliem@jaret.de)
4    *  A commercial license is available, see http://www.jaret.de.
5    *
6    * All rights reserved. This program and the accompanying materials
7    * are made available under the terms of the Common Public License v1.0
8    * which accompanies this distribution, and is available at
9    * http://www.eclipse.org/legal/cpl-v10.html
10   */
11  package de.jaret.util.date.timemachine;
12  
13  import java.util.Date;
14  import java.util.List;
15  import java.util.Vector;
16  
17  /**
18   * Implementation of a time supplier that can be controlled by various options. This is useful to cut dependencies on
19   * system time. The class should usually be used as a singleton, but is no singleton itself.
20   * 
21   * @author kliem
22   * @version $Id: TimeMachine.java 702 2007-12-30 11:54:55Z kliem $
23   */
24  public class TimeMachine implements ITimeProvider {
25      /** the current time. */
26      private volatile long _currentTime;
27      /** listener list. */
28      private List<ITimeMachineListener> _listeners = new Vector<ITimeMachineListener>();
29  
30      /** flag indicating forward movement in time only. */
31      private boolean _forwardOnly = true;
32      /** flag indicating autoincrement. */
33      private boolean _autoIncrement = false;
34      /** flag indicating the time machine supplies realtime. */
35      private boolean _realTime = false;
36  
37      /**
38       * Construct the time machine with an initial time.
39       * 
40       * @param initialTime time (millis)
41       */
42      public TimeMachine(long initialTime) {
43          _currentTime = initialTime;
44      }
45  
46      /**
47       * {@inheritDoc} base method that supplies the timea nd might auto increment the time value.
48       */
49      public long getCurrentTime() {
50          if (_realTime) {
51              return System.currentTimeMillis();
52          }
53          if (_autoIncrement) {
54              synchronized (this) {
55                  long time = _currentTime;
56                  increment();
57                  return time;
58              }
59          } else {
60              return _currentTime;
61          }
62      }
63  
64      /**
65       * {@inheritDoc} Wraps millis from getCurrentTime in a Date object.
66       */
67      public Date getCurentTimeAsDate() {
68          return new Date(getCurrentTime());
69      }
70  
71      private void increment() {
72          _currentTime++;
73          fireTimeChanged(_currentTime - 1, _currentTime);
74      }
75  
76      /**
77       * Set the time of the timemachine.
78       * 
79       * @param time millis
80       */
81      public synchronized void setTime(long time) {
82          if (_realTime) {
83              throw new IllegalArgumentException("Time machine is in real time mode.");
84          }
85          if (_forwardOnly && time < _currentTime) {
86              throw new IllegalArgumentException("Time must move forward");
87          }
88          long oldTime = _currentTime;
89          _currentTime = time;
90          fireTimeChanged(oldTime, _currentTime);
91      }
92  
93      /**
94       * Add a listener to the timemachine.
95       * 
96       * @param timeMachineListener time machine listener
97       */
98      public synchronized void addTimeMachineListener(ITimeMachineListener timeMachineListener) {
99          if (!_listeners.contains(timeMachineListener)) {
100             _listeners.add(timeMachineListener);
101         }
102     }
103 
104     /**
105      * Remove a listener from the time machine.
106      * 
107      * @param timeMachineListener listener to remove
108      */
109     public synchronized void remTimeMachineListener(ITimeMachineListener timeMachineListener) {
110         _listeners.remove(timeMachineListener);
111     }
112 
113     /**
114      * Inform listeners about a change.
115      * 
116      * @param oldTime last time
117      * @param newTime current (= new) time
118      */
119     protected void fireTimeChanged(long oldTime, long newTime) {
120         for (ITimeMachineListener listener : _listeners) {
121             listener.timeChanged(this, oldTime, newTime);
122         }
123     }
124 
125     /**
126      * true if the time will always be going towards the future.
127      * 
128      * @return <code>true</code> for ongoing time only
129      */
130     public boolean isForwardOnly() {
131         return _forwardOnly;
132     }
133 
134     /**
135      * Set forward protection: if set to <code>true</code> time shifts going before the current time will be
136      * disallowed. Forward only is the default.
137      * 
138      * @param forwardOnly <code>true</code> for forward only mode.
139      */
140     public void setForwardOnly(boolean forwardOnly) {
141         _forwardOnly = forwardOnly;
142     }
143 
144     /**
145      * If autoincrement is <code>true</code> the time will be incremented by 1 millisecond with each time request.
146      * 
147      * @return <code>true</code> if autoincrement is set
148      */
149     public boolean isAutoIncrement() {
150         return _autoIncrement;
151     }
152 
153     /**
154      * set autoincrement mode.
155      * 
156      * @param autoIncrement if sert to <code>true</code> the time will be increased by 1 millisecond which each
157      * request
158      */
159     public void setAutoIncrement(boolean autoIncrement) {
160         _autoIncrement = autoIncrement;
161     }
162 
163     /**
164      * If this return <code>true</code> the time machine is in real time mode always providing the system's current
165      * time.
166      * 
167      * @return true for real time mode
168      */
169     public boolean isRealTime() {
170         return _realTime;
171     }
172 
173     /**
174      * Set the realtime mode.
175      * 
176      * @param realTime if set to <code>true</code> the time machine will be disabled, always returning the systems's
177      * current time
178      */
179     public void setRealTime(boolean realTime) {
180         _realTime = realTime;
181     }
182 }