1 /*
2 * AbstractTimer.java
3 *
4 * Created on 28 de Março de 2007, 17:02
5 *
6 * To change this template, choose Tools | Template Manager
7 * and open the template in the editor.
8 */
9
10 package tempcontroller.base;
11
12 import java.util.HashSet;
13 import java.util.Iterator;
14 import java.util.Set;
15
16 /**
17 * Implementação auxiliar de um Timer. Controla o tempo decorrido.
18 */
19 public abstract class AbstractTimer implements ITimer {
20 /**
21 * Tempo decorrido antes do último pause ou stop.
22 */
23 private long tempoDecorridoAntigo;
24
25 /**
26 * Início do último 'start' ou 'continue'.
27 */
28 private long inicio;
29
30 /**
31 * Quantidade de tempo que o Timer tem
32 * que contar até encerrar sua contagem.
33 */
34 private long tempoTotal;
35
36 /**
37 * Quantidade de tempo entre cada evento de Tick.
38 */
39 private long tick;
40
41 /**
42 * Conjunto de ouvintes do timer.
43 */
44 private Set<IOuvinteTimer> ouvintes = null;
45
46 /**
47 * Estado inicial do Timer.
48 */
49 private ITimer.Estado estado = ITimer.Estado.NAO_INICIADO;
50
51 /**
52 * Define o tempo total deste timer. Tempo total é a quantidade
53 * de tempo que o timer deve esperar até enviar um único evento
54 * de tempo total terminado.
55 * @param tempoTotalLocal Tempo total do timer.
56 */
57 public void setTempoTotal(final long tempoTotalLocal) {
58 tempoTotal = tempoTotalLocal;
59 setTempoTotalImpl(tempoTotalLocal);
60 }
61
62 /**
63 * Obtém o tempo total deste timer. Tempo total é a quantidade
64 * de tempo que o timer deve esperar até enviar um único evento
65 * de tempo total terminado.
66 * @return O tempo total deste timer.
67 */
68 public long getTempoTotal() {
69 return tempoTotal;
70 }
71
72 /**
73 * Define o tick do timer. Tick é o tempo que o timer
74 * deve esperar para enviar eventos de 'tick' periodicamente.
75 * @param tempo Quantidade de tempo do tick.
76 */
77 public void setTick(final long tempo) {
78 tick = tempo;
79 setTickImpl(tempo);
80 }
81
82 /**
83 * Obtém o tick do timer. Tick é o tempo que o timer
84 * deve esperar para enviar eventos de 'tick' periodicamente.
85 * @return Quantidade de tempo do tick.
86 */
87 public long getTick() {
88 return tick;
89 }
90
91 /**
92 * Adiciona um ouvinte do Timer. Este receberá os eventos
93 * de tick e de tempo total.
94 * @param ouvinte Ouvinte dos eventos deste timer.
95 */
96 public void addOuvinteTimer(final IOuvinteTimer ouvinte) {
97 if (ouvintes == null) {
98 ouvintes = new HashSet<IOuvinteTimer>();
99 }
100 if (!ouvintes.contains(ouvinte)) {
101 ouvintes.add(ouvinte);
102 }
103 }
104
105 /**
106 * Remove um ouvinte do conjunto de ouvintes deste timer.
107 * @param ouvinte Ouvinte que não quer mais receber
108 * eventos deste timer.
109 */
110 public void removeOuvinteTimer(final IOuvinteTimer ouvinte) {
111 if (ouvintes != null) {
112 ouvintes.remove(ouvinte);
113 }
114 }
115
116 /**
117 * Notifica todos os ouvintes que o tempo total foi
118 * alcançado.
119 */
120 protected void fireTempoTotalTerminado() {
121 Iterator<IOuvinteTimer> it = ouvintes.iterator();
122 while (it.hasNext()) {
123 IOuvinteTimer ouvinte = it.next();
124 ouvinte.tempoTotalTerminado();
125 }
126 }
127
128 /**
129 * Notifica todos os ouvintes com um evento de tick.
130 */
131 protected void fireTickDoTimer() {
132 Iterator<IOuvinteTimer> it = ouvintes.iterator();
133 while (it.hasNext()) {
134 IOuvinteTimer ouvinte = it.next();
135 ouvinte.tickDoTimer();
136 }
137 }
138
139 /**
140 * Inicia a contagem do tempo.
141 */
142 public void start() {
143 tempoDecorridoAntigo = 0;
144 privContinua();
145 startImpl();
146 }
147
148 /**
149 * Termina a contagem do tempo.
150 */
151 public void stop() {
152 atualizaTempoDecorridoAntigo();
153 estado = ITimer.Estado.NAO_INICIADO;
154 stopImpl();
155 }
156
157 /**
158 * Pausa a contagem do tempo.
159 */
160 public void pause() {
161 atualizaTempoDecorridoAntigo();
162 estado = ITimer.Estado.PAUSADO;
163 pauseImpl();
164 }
165
166 /**
167 * Atualiza o tempo de corrido antigo. Deve ser chamado a cada
168 * stop ou pause.
169 */
170 private void atualizaTempoDecorridoAntigo() {
171 tempoDecorridoAntigo = tempoDecorridoAntigo
172 + (getCurrentTime() - inicio);
173 }
174
175 /**
176 * Retoma a contagem do tempo, depois de um pause.
177 */
178 public void continua() {
179 privContinua();
180 continuaImpl();
181 }
182
183 /**
184 * Inicia a contagem do tempo. Deve ser
185 * chamada a cada continue ou start.
186 */
187 private void privContinua() {
188 inicio = getCurrentTime();
189 estado = ITimer.Estado.CRONOMETRANDO;
190 }
191
192 /**
193 * Obtém o tempo decorrido total. Ignora
194 * os períodos que o timer estava pausado.
195 * @return O tempo decorrido.
196 */
197 public long getTempoDecorrido() {
198 long toReturn = 0;
199 if (estado.equals(ITimer.Estado.CRONOMETRANDO)) {
200 toReturn = (getCurrentTime() - inicio) + tempoDecorridoAntigo;
201 } else {
202 toReturn = tempoDecorridoAntigo;
203 }
204 return toReturn;
205 }
206
207 /**
208 * Obtém o estado atual do timer.
209 * @return O estado atual do timer.
210 */
211 public ITimer.Estado getEstado() {
212 return estado;
213 }
214
215 /**
216 * Não faz nada. Chamado pelo método
217 * 'setTempoTotal' desta classe.
218 * Subclasses podem sobrepor este método
219 * para um controle próprio.
220 * @param tempoTotalLocal Tempo Total do timer.
221 */
222 protected void setTempoTotalImpl(final long tempoTotalLocal) {
223 // Por default não faz nada.
224 }
225
226 /**
227 * Não faz nada. Chamdo pelo método
228 * 'start' desta classe.
229 * Subclasses podem sobrepor este método
230 * para um controle próprio.
231 */
232 protected void startImpl() {
233 // Não faz nada. Subclasses podem implementar este método.
234 }
235
236 /**
237 * Não faz nada. Chamado pelo
238 * método 'stop' desta classe.
239 * Subclasses podem sobrepor este método
240 * para um controle próprio.
241 */
242 protected void stopImpl() {
243 // Não faz nada. Subclasses podem implementar este método.
244 }
245
246 /**
247 * Não faz nada. Chamado pelo método 'setTick' desta
248 * classe. Subclasses podem sobrepor este método
249 * para controle próprio.
250 * @param tempo Quantidade de tempo do tick.
251 */
252 protected void setTickImpl(final long tempo) {
253 // Não faz nada. Subclasses podem implementar este método.
254 }
255
256 /**
257 * Obtém o instante atual do relógio do sistema.
258 * Chamado diversas vezes por
259 * esta classe para implementar o controle do tempo.
260 * Por padrão, obtém o tempo atual através de
261 * <code>System.currentTimeMillis()</code>
262 * @return O valor do instante atual, de acordo com o relógio do
263 * systema.
264 */
265 protected long getCurrentTime() {
266 return System.currentTimeMillis();
267 }
268
269 /**
270 * Não faz nada. Chamado pelo método 'pause'.
271 * Subclasses podem implementar este método para
272 * um controle próprio.
273 */
274 protected void pauseImpl() {
275 // Não faz nada. Subclasses podem sobrepor este
276 // método para um controle próprio.
277 }
278
279 /**
280 * Não faz nada. Chamado pelo método 'continua'.
281 * Subclasses podem sobrepor este método para um
282 * controle próprio.
283 */
284 protected void continuaImpl() {
285 // Não faz nada. Subclasses podem sobrepor este
286 // método para um controle próprio.
287 }
288 }