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 }