/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package TCM_MPI.Buffer;
import TCM_MPI.Buffer.Data.FragmentedData;
import TCM_MPI.Buffer.Events.BufferEvent;
import TCM_MPI.Buffer.Events.FragmentBufferListener;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
/**
*
* @author Rodrigo
*/
public class FragmentBuffer {
private BufferInfo _FINAL_BUFFER;
private ConcurrentHashMap<String,FragmentedData> _FRAG_HASHMAP;
private Collection<FragmentBufferListener> bufferListener = new ArrayList<FragmentBufferListener>();
public FragmentBuffer(BufferInfo FINAL_BUFFER){
this._FINAL_BUFFER = FINAL_BUFFER;
this._FRAG_HASHMAP = new ConcurrentHashMap<String,FragmentedData>();
}
/**
* Atualiza,Cria uma informacao fragmentada ou entao inseri<br>
* no Buffer final
*
* @param IDS ByteBuffer - Buffer com o cabecalho do pacote
* @param NUMS ByteBuffer - Buffer com as informacoes do pacote
*/
public synchronized void UpdateFragmentedData(ByteBuffer IDS,ByteBuffer NUMS){
int FROM_ID;
int TO_ID;
int TYPE_ID;
int TOTAL_NUMBERS;
int TOTAL_PACOTES;
int PACOTE_ATUAL;
long SEQUENCE_NUMBER;
// REMETENTE
FROM_ID = IDS.getInt(0);
// DESTINATARIO
TO_ID = IDS.getInt(4);
// TIPODE DADOS
TYPE_ID = IDS.getInt(8);
// TOTAL DE INFORMAÇÕES A RECEBER
TOTAL_NUMBERS = IDS.getInt(12);
// NUMERAÇÃO DE SEQUENCIA DO PACOTE
SEQUENCE_NUMBER = IDS.getLong(16);
// TOTAL DE PACOTES FRAGMENTADOS
TOTAL_PACOTES = IDS.getInt(24);
// NUMERO DO FRAGMENTO ATUAL
PACOTE_ATUAL = IDS.getInt(28);
// VERIFICA SE O TOTAL DE PACOTES É UM OU NÃO
if(TOTAL_PACOTES == 1){
InsertInFinalBuffer(FROM_ID, TYPE_ID, NUMS);
}else{
String KEY = FROM_ID + ":" + TYPE_ID + ":" + SEQUENCE_NUMBER;
FragmentedData FRAG;
if(this._FRAG_HASHMAP.containsKey(KEY)){
try{
FRAG = UpdateFragmentData(KEY, PACOTE_ATUAL, NUMS);
if(FRAG.NumberOfReceived() == FRAG.NumberOfFragments()){
NUMS = RemakeFragmentData(FRAG, KEY);
this._FINAL_BUFFER.InsertData(FROM_ID, TYPE_ID, NUMS);
this._FINAL_BUFFER.DisparaInfoInserted(FROM_ID + ":" + TYPE_ID);
}else{
this._FRAG_HASHMAP.put(KEY, FRAG);
}
}catch(Exception ex){
}finally{
}
}else{
try{
NewFragmentData(KEY, PACOTE_ATUAL, TOTAL_PACOTES, NUMS);
}catch(Exception ex){
}finally{
}
}
}
}
/**
* Inseri uma informação completa no buffer final
*
* @param FROM_ID int - id do remetente
* @param TYPE_ID int - tipagem dos dados
* @param NUMS ByteBuffer - buffer com a informação completa
*/
private void InsertInFinalBuffer(int FROM_ID,int TYPE_ID,ByteBuffer NUMS){
// INSERI NO BUFFER FINAL
this._FINAL_BUFFER.InsertData(FROM_ID, TYPE_ID, NUMS);
this._FINAL_BUFFER.DisparaInfoInserted(FROM_ID + ":" + TYPE_ID);
}
/**
* Cria um novo objeto de fragmento
*
* @param KEY String - chave do fragmento
* @param PACOTE_ATUAL int - numero do pacote atual
* @param TOTAL_PACOTES int - total de pacotes do fragmento
* @param NUMS ByteBuffer - buffer do pacote atual
*/
private void NewFragmentData(String KEY,int PACOTE_ATUAL,int TOTAL_PACOTES,ByteBuffer NUMS){
FragmentedData FRAG = new FragmentedData(TOTAL_PACOTES);
FRAG.SetByteBuffer(NUMS, (PACOTE_ATUAL - 1));
FRAG.IncrementReceived();
this._FRAG_HASHMAP.put(KEY, FRAG);
}
/**
* Atualiza o fragmento indicado por KEY e retorna o mesmo
*
* @param KEY String - chave do fragmento
* @param PACOTE_ATUAL int - numero do pacote atual
* @param NUMS ByteBuffer - buffer do pacote atual
* @return FragmentedData - fragmento atualizado
*/
private FragmentedData UpdateFragmentData(String KEY,int PACOTE_ATUAL,ByteBuffer NUMS){
FragmentedData FRAG = this._FRAG_HASHMAP.get(KEY);
//FRAG.ARR_BYTEBUFFER[PACOTE_ATUAL - 1] = NUMS;
FRAG.SetByteBuffer(NUMS, (PACOTE_ATUAL - 1));
NUMS = null;
FRAG.IncrementReceived();
return FRAG;
}
/**
* Reorganiza toda a informação do fragmento num unico buffer e retorna o mesmo
*
* @param FRAG FragmentedData - fragmento
* @param KEY String - chave de identificação do fragmento
* @return ByteBuffer - buffer com a informação completa
*/
private ByteBuffer RemakeFragmentData(FragmentedData FRAG,String KEY){
int TOTAL_BYTES = 0;
for(int x=0 ; x < FRAG.NumberOfFragments() ; x++){
TOTAL_BYTES += FRAG.GetByteBuffer(x).capacity();
}
ByteBuffer NUMS = ByteBuffer.allocate(TOTAL_BYTES);
for(int x=0 ; x < FRAG.NumberOfFragments() ; x++){
byte[] TEMP = FRAG.GetByteBuffer(x).array();
NUMS.put(TEMP, 0, TEMP.length);
FRAG.SetByteBuffer(null, x);
}
FragmentedData temp = this._FRAG_HASHMAP.remove(KEY);
return NUMS;
}
/**
* Adiciona um ouvinte do Buffer
*
* @param b BufferListener - ouvinte do Buffer
*/
public synchronized void addFragmentBufferListener(FragmentBufferListener b){
if(!this.bufferListener.contains(b)){
this.bufferListener.add(b);
}
}
/**
* Remove um ouvinte do Buffer
*
* @param b BufferListener - ouvinte do Buffer
*/
public synchronized void removeFragmentBufferListener(FragmentBufferListener b){
this.bufferListener.remove(b);
}
/**
* Dispara aos ouvintes que um determinado fragmento foi criado
*
* @param key String - chave do fragmento
*/
private void disparaFragmentoCriado(String key){
Collection<FragmentBufferListener> t1;
synchronized(this.bufferListener){
ArrayList<FragmentBufferListener> list_temp = (ArrayList<FragmentBufferListener>) this.bufferListener;
t1 = (Collection<FragmentBufferListener>) list_temp.clone();
}
BufferEvent evento = new BufferEvent(this);
for(FragmentBufferListener bl : t1){
bl.FragmentCreated(evento, key);
}
}
/**
* Dispara aos ouvintes que um determinado fragmento foi modificado
*
* @param key String - chave do fragmento
*/
private void disparaFragmentoModificado(String key){
Collection<FragmentBufferListener> t1;
synchronized(this.bufferListener){
ArrayList<FragmentBufferListener> list_temp = (ArrayList<FragmentBufferListener>) this.bufferListener;
t1 = (Collection<FragmentBufferListener>) list_temp.clone();
}
BufferEvent evento = new BufferEvent(this);
for(FragmentBufferListener bl : t1){
bl.FragmentUpdate(evento, key);
}
}
/**
* Dispara aos ouvintes que um determinado fragmento esta completo
*
* @param key String - chave do fragmento
*/
private void disparaFragmentoCompleto(String key){
Collection<FragmentBufferListener> t1;
synchronized(this.bufferListener){
ArrayList<FragmentBufferListener> list_temp = (ArrayList<FragmentBufferListener>) this.bufferListener;
t1 = (Collection<FragmentBufferListener>) list_temp.clone();
}
BufferEvent evento = new BufferEvent(this);
for(FragmentBufferListener bl : t1){
bl.FragmentComplete(evento, key);
}
}
}