View Javadoc

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 }