View Javadoc

1   /*
2    * ControladorAmostragem.java
3    *
4    * Created on 13 de Março de 2007, 12:48
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.io.File;
13  import java.io.IOException;
14  import java.util.HashSet;
15  import java.util.Iterator;
16  import java.util.List;
17  import java.util.Set;
18  
19  /**
20   * Controla a execução de uma amostragem, monitorando o controlador de
21   * temperatura, o Timer e o Leitor de Espectro.
22   */
23  public class ControladorAmostragem implements
24          IControladorAmostragem {
25  
26      /**
27       * programação atual.
28       */
29      private IProgramacaoAmostragem programacao;
30  
31      /**
32       * controlador de temperatura atual.
33       */
34      private IControladorTemperatura controladorTemperatura;
35  
36      /**
37       * leitor de espectro atual.
38       */
39      private ILeitorEspectro leitorEspectro;
40  
41      /**
42       * Conjunto de ouvintes dos eventos deste controlador.
43       */
44      private Set<IOuvinteEventosControladorAmostragem> ouvintes;
45  
46      /**
47       * Status atual (muito mais que o estado atual).
48       */
49      private ControladorAmostragemStatus status;
50  
51      /**
52       * Tempo total da programação.
53       */
54      private long tempoTotalProgramacao;
55  
56      /**
57       * Estado do controlador.
58       */
59      private IControladorAmostragem.Estado estado;
60  
61      /**
62       * Iterator da programação atual.
63       */
64      private Iterator<IAmostragem> programacaoIterator;
65  
66      /**
67       * Timer atual.
68       */
69      private ITimer timer;
70  
71      /**
72       * Amostragem atual.
73       */
74      private IAmostragem amostragemAtual;
75  
76      /**
77       * Máxima variação de temperatura aceita.
78       */
79      private static final double MAX_DELTA_TEMPERATURA = 1.0;
80  
81      /**
82       * Cria um novo controlador de amostragem.
83       */
84      public ControladorAmostragem() {
85          limpaProgramacao();
86      }
87  
88      /**
89       * Obtém o status corrente.
90       * @return O status corrente.
91       */
92      public final IControladorAmostragem.Status getStatus() {
93          if (status == null) {
94              status = new ControladorAmostragemStatus();
95          } else {
96              status.setTemperaturaAtual(0.0);
97              status.setTempoDecorridoAmostragem(0);
98              status.setTempoDecorridoProgramacao(0);
99              status.setTempoTotalAmostragem(0);
100             status.setTempoTotalProgramacao(0);
101             status.setNomeAmostragemAtual("");
102             status.setTempoDaUltimaGravacao(0);
103         }
104 
105         status.setEstado(estado);
106 
107         if (!estado.equals(Estado.SEM_PROGRAMACAO)) {
108             status.setTempoTotalAmostragem(tempoTotalProgramacao);
109 
110             if (!(estado.equals(Estado.NAO_INICIADO)
111             || estado.equals(Estado.PROGRAMACAO_TERMINADA)
112             || estado.equals(Estado.CANCELADO))) {
113                 status.setNomeAmostragemAtual(amostragemAtual.getNome());
114                 status.setTempoTotalAmostragem(amostragemAtual.getDuracao());
115             }
116 
117             if (estado.equals(Estado.EM_AMOSTRAGEM)
118             || estado.equals(Estado.ESPERANDO_RETORNO_TEMPERATURA)) {
119                 status.setTempoDecorridoAmostragem(timer.getTempoDecorrido());
120                 status.setTemperaturaAtual(
121                         controladorTemperatura.getTemperatura());
122             }
123         }
124 
125         return status;
126     }
127 
128     /**
129      * Carrega uma programação de um arquivo.
130      * @param file O arquivo que será lido.
131      * @return A programação lida.
132      * @throws IOException Se ocorrer algum erro de leitura.
133      * @throws ClassNotFoundException Se o arquivo não tiver um
134      * uma programação gravada.
135      */
136     public final IProgramacaoAmostragem carregaProgramacao(final File file)
137     throws IOException, ClassNotFoundException {
138         return (IProgramacaoAmostragem)
139         Utilities.getUtilities().leSerializable(file);
140     }
141 
142     /**
143      * Grava uma programação para um arquivo.
144      * @param programacaoLocal Programação que será gravada
145      * @param file Arquivo que será gravado.
146      * @throws IOException Se ocorrer algum erro durante a gravação.
147      */
148     public final void gravaProgramacao(
149             final IProgramacaoAmostragem programacaoLocal,
150             final File file) throws IOException {
151         Utilities.getUtilities().gravaSerializable(file, programacaoLocal);
152     }
153 
154     /**
155      * Método que inicia o controlador com os objetos necessários para a
156      * execução da amostragem.
157      * Ele retorna o status indicando se a amostragem pode ou não prosseguir.
158      * @param prog Programação de Amostragem.
159      * @param control Controlador de Temperatura que será utilizado.
160      * @param leitor O Leitor de espectro que será utilizado.
161      * @param timerLocal O timer que será utilizado
162      * @return <code>true</code> caso a programação possa ser executada com
163      * este controlador, leitor de espectro e timer.
164      */
165     public final boolean aceita(final IProgramacaoAmostragem prog,
166             final IControladorTemperatura control,
167             final ILeitorEspectro leitor,
168             final ITimer timerLocal) {
169         //@TODO não está bom. Deveria retornar mais informações
170         // caso a programação não seja aceita.
171         boolean toReturn = true;
172 
173         List<IAmostragem> amostragens = prog.getAmostragens();
174         Iterator<IAmostragem> it = amostragens.iterator();
175         tempoTotalProgramacao = 0;
176         while (it.hasNext()) {
177             IAmostragem amostragem = it.next();
178             tempoTotalProgramacao = tempoTotalProgramacao
179                     + amostragem.getDuracao();
180             if (!control.aceitaTemperatura(amostragem.getTemperatura())) {
181                 toReturn = false;
182                 break;
183             }
184         }
185 
186         if (toReturn) {
187             programacao = prog;
188             controladorTemperatura = control;
189             leitorEspectro = leitor;
190             timer = timerLocal;
191         }
192 
193         estado = Estado.NAO_INICIADO;
194 
195         return toReturn;
196     }
197 
198     /**
199      * Limpa todos os recursos utilizados por este controlador, inclusive
200      * a programação atual.
201      */
202     public final void limpaProgramacao() {
203         programacao = null;
204         controladorTemperatura = null;
205         leitorEspectro = null;
206         ouvintes = null;
207         estado = Estado.SEM_PROGRAMACAO;
208         tempoTotalProgramacao = 0;
209         synchronized (this) {
210             programacaoIterator = null;
211         }
212         timer = null;
213         amostragemAtual = null;
214     }
215 
216     /**
217      * Adiciona um ouvinte aos eventos gerados por este controlador.
218      * @param ouvinte o ouvinte que será notificado sempre que o estado
219      * deste controlador mudar.
220      */
221     public final void addOuvinteEventosControladorAmostragem(
222             final IOuvinteEventosControladorAmostragem ouvinte) {
223         if (ouvintes == null) {
224             ouvintes = new
225                     HashSet <IOuvinteEventosControladorAmostragem>();
226         }
227 
228         ouvintes.add(ouvinte);
229     }
230 
231     /**
232      * Remove um ouvinte dos eventos deste controlador.
233      * @param ouvinte que não quer mais receber notificações
234      * de mudança de estado deste controlador.
235      */
236     public final void removeOuvinteEventosControladorAmostragem(
237             final IOuvinteEventosControladorAmostragem ouvinte) {
238         if (ouvintes != null) {
239             ouvintes.remove(ouvinte);
240         }
241     }
242 
243     /**
244      * Notifica os ouvintes que o estado deste controlador mudou.
245      */
246     private void fireNewStatus() {
247         if (ouvintes != null) {
248             Iterator<IOuvinteEventosControladorAmostragem>
249                     it = ouvintes.iterator();
250             while (it.hasNext()) {
251                 IOuvinteEventosControladorAmostragem ouvinte = it.next();
252                 ouvinte.novoStatusControladorAmostragem();
253             }
254         }
255     }
256 
257     /**
258      * Inicia a execução da programação atual.
259      */
260     public final void start() {
261         synchronized (this) {
262             programacaoIterator = programacao.getAmostragens().iterator();
263             estadoPreparaAmostragem();
264             trataProximaAmostragem();
265         }
266     }
267 
268     /**
269      * Cancela a execução da programação atual.
270      */
271     public final void cancel() {
272         synchronized (this) {
273             if (estado.equals(Estado.ESPERANDO_TEMPERATURA_INICIAL)) {
274                 timer.stop();
275                 
276                 controladorTemperatura.cancelaTemperaturaAlvo();
277             } else if (estado.equals(Estado.EM_AMOSTRAGEM)) {
278                 timer.stop();
279                 leitorEspectro.termina();
280                 controladorTemperatura.cancelaTemperaturaAlvo();
281                 gravaAmostragem();
282             } else if (estado.equals(Estado.ESPERANDO_RETORNO_TEMPERATURA)) {
283                 timer.stop();
284                 leitorEspectro.termina();
285                 controladorTemperatura.cancelaTemperaturaAlvo();
286                 gravaAmostragem();
287             }
288 
289             estadoCancelado();
290         }
291     }
292 
293     /**
294      * Verifica se tem mais uma amostragem na programação, e
295      * inicia sua execução.
296      */
297     private void trataProximaAmostragem() {
298         synchronized (this) {
299             if (estado.equals(Estado.PREPARA_AMOSTRAGEM)) {
300                 if (programacaoIterator.hasNext()) {
301                     amostragemAtual = programacaoIterator.next();
302                     controladorTemperatura.setTemperaturaAlvo(
303                             amostragemAtual.getTemperatura());
304                     controladorTemperatura.addIOuvinteMundancaTemperatura(this);
305                     timer.setTempoTotal(amostragemAtual.getDuracao());
306                     timer.addOuvinteTimer(this);
307                     estadoEsperandoTemperaturaInicial();
308                 } else {
309                     estadoProgramacaoTerminada();
310                     trataTerminoProgramacao();
311                 }
312             }
313         }
314     }
315 
316     /**
317      * Trata o final da programação.
318      */
319     private void trataTerminoProgramacao() {
320         estadoProgramacaoTerminada();
321     }
322 
323     /**
324      * Muda o estado para PREPARA_AMOSTRAGEM.
325      * Notifica os ouvintes que o estado deste controlador mudou.
326      */
327     private void estadoPreparaAmostragem() {
328         synchronized (this) {
329             estado = Estado.PREPARA_AMOSTRAGEM;
330             fireNewStatus();
331         }
332     }
333 
334     /**
335      * Muda o estado para ESPERANDO_TEMPERATURA_INICIAL.
336      * Notifica os ouvintes que o estado deste controlador mudou.
337      */
338     private void estadoEsperandoTemperaturaInicial() {
339         synchronized (this) {
340             estado = Estado.ESPERANDO_TEMPERATURA_INICIAL;
341             fireNewStatus();
342         }
343     }
344 
345     /**
346      * Muda o estado para EM_AMOSTRAGEM.
347      * Notifica os ouvintes que o estado deste controlador mudou.
348      */
349     private void estadoEmAmostragem() {
350         synchronized (this) {
351             estado = Estado.EM_AMOSTRAGEM;
352             fireNewStatus();
353         }
354     }
355 
356     /**
357      * Muda o estado para ESPERANDO_RETORNO_TEMPERATURA.
358      * Notifica os ouvintes que o estado deste controlador mudou.
359      */
360     private void estadoEsperandoRetornoTemperatura() {
361         synchronized (this) {
362             estado = Estado.ESPERANDO_RETORNO_TEMPERATURA;
363             fireNewStatus();
364         }
365     }
366 
367     /**
368      * Muda o estado para PROGRAMACAO_TERMINADA.
369      * Notifica os ouvintes que o estado deste controlador mudou.
370      */
371     private void estadoProgramacaoTerminada() {
372         synchronized (this) {
373             estado = Estado.PROGRAMACAO_TERMINADA;
374             fireNewStatus();
375         }
376     }
377 
378     /**
379      * Muda o estado para CANCELADO.
380      * Notifica os ouvintes que o estado deste controlador mudou.
381      */
382     private void estadoCancelado() {
383         synchronized (this) {
384             estado = Estado.CANCELADO;
385             fireNewStatus();
386         }
387     }
388 
389     /**
390      * Notificação do controlador de temperatura indicando que
391      * ele está em nova temperatura.
392      * O controlador de amosragem deve verificar
393      * se a temperatura está dentro dos limites estabelecidos.
394      * @param temperatura A temperatura atual do controlador.
395      */
396     public final void novaTemperatura(final double temperatura) {
397         synchronized (this) {
398             if (estado.equals(Estado.EM_AMOSTRAGEM)
399             && (Math.abs(temperatura - amostragemAtual.getTemperatura())
400             > MAX_DELTA_TEMPERATURA)) {
401                 leitorEspectro.pausa();
402                 timer.pause();
403                 estadoEsperandoRetornoTemperatura();
404             }
405         }
406     }
407 
408     /**
409      * Notificação do controlador de temperatura indicando
410      * que a temperatura alvo foi alcançada.
411      * O controlador de amostragem deve iniciar ou prosseguir
412      * na amostragem atual.
413      * @param temperatura A temperatura atual do controlador.
414      */
415     public final void temperaturaAlvoAlcancada(final double temperatura) {
416         if (estado.equals(Estado.ESPERANDO_TEMPERATURA_INICIAL)) {
417             leitorEspectro.inicia();
418             timer.start();
419             estadoEmAmostragem();
420         } else if (estado.equals(Estado.ESPERANDO_RETORNO_TEMPERATURA)) {
421             leitorEspectro.continua();
422             timer.continua();
423             estadoEmAmostragem();
424         }
425     }
426 
427     /**
428      * Evento do timer, indicando que um tick do relógio já passou.
429      * O controlador de amostragem deve gravar um espectro com resultados
430      * parciais.
431      */
432     public final void tickDoTimer() {
433         // grava amostra espectro.
434     }
435 
436     /**
437      * Evento do timer, indicando que o tempo total da amostragem atual
438      * foi alcançado.
439      * O controlador deve gravar a amostragem atual com os resultados
440      * finais, e prosseguir com a programação.
441      */
442     public final void tempoTotalTerminado() {
443         if (estado.equals(Estado.EM_AMOSTRAGEM)) {
444             leitorEspectro.termina();
445             controladorTemperatura.cancelaTemperaturaAlvo();
446             gravaAmostragem();
447             estadoPreparaAmostragem();
448             trataProximaAmostragem();
449         }
450     }
451 
452     /**
453      * Grava uma amostragem com os resultados atuais.
454      */
455     private void gravaAmostragem() {
456         // gravar a amostragem;
457     }
458 }