/*
 *  Este ficheiro pretende ser um esqueleto de uma
 *  aplicacao que le dados do utilizador e os coloca
 *  numa camada Appia para serem enviados.
 *  So esta exposto o codigo mais importante e nao
 *  pretende ser um exemplo funcional.
 *  Espero que esclareca algumas duvidas.
 *
 *  Pedro Vicente.
 * 
 */
public class ClientSession{
    //declarar a thread que le os dados do teclado
    ReaderThread reader;
    .
    .
    .
    void handle(Event e){
	.
        .
        .
        //se recebe um evento asyncrono. E necessario adicionar a Layer
        //que se pretende receber este tipo de eventos!
        if(e instanceof AsyncEvent){
	    Dados d;
	    //faz lock ao objecto para evitar o acesso concorrente
	    synchronized(reader){
		if(reader.dados!=null){
		    //vai buscar os dados a thread
		    d=reader.dados;
		    //cria evento e envia
		    .
		    .
		    .			
		    //apaga os dados partilhados com a thread
		    reader.dados=null;
		    //e avisa a thread que pode ler mais coisas
		    reader.notify();
		}
	    }
	}
	//trata channelinit
	if(e instanceof ChannelInit){
	    //guarda referencia para o canal
	    channel=e.getChannel();
	    try{
		//envia o channelinit para inicializar o resto do canal
		e.go();
	    }
	    catch(AppiaEventException ex){
		System.err.println("Error Sending Event");
	    }
	    
	    //inicializa a thread
	    reader=new ReaderThread(channel);
	    reader.start();
	}
	.
	.
    }
    .
    .
    .    
}


//classe que implementa a thread que faz o interface do utilizador
class ReaderThread{
    //referencia publica para os dados
    public Dados dados;
    //referencia privada para os dados
    private Dados aux;
    //referencia para o canal
    private Channel channel;
    
    //construtor
    public ReaderThread(Channel c){
	channel=c;
    }
    
    //metodo chamado quando se faz reader.start()
    public void run(){
	while(true){
	    //le os dados do teclado e constroe a informacao para o Appia
	    aux=le_do_teclado();
	    
	    //faz lock para evitar acesso concorrente
	    synchronized(this){
		//preenche a variavel partilhada
		dados=aux;
		try{
		    //este metodo coloca um evento Async no canal
		    //serve para avisar que ha dados novos a colocar no canal
		    channel.makeAsyn();
		}
		catch(AppiaEventException ex){
		    System.err.println("Error making async "+ex.type);
		}
		
		//espera ate os dados serem tratados
		while(dados!=null){
		    try{
			wait();
		    }
		    catch(InterruptedException ex){
			ex.printStackTrace();			
		    }
		}
		    
	    }
	}
    }

    private Dados le_do_teclado(){
	//codigo do interface
	.
        .
    }
}