Completato l'oggetto per la gestione della tabella analisi e dei saldi:

corretta la gestione dei link


git-svn-id: svn://10.65.10.50/trunk@6000 c028cbd2-c16b-5b4b-a496-9718f37d4682
This commit is contained in:
sauro 1998-01-22 08:50:45 +00:00
parent 8b22f99c2a
commit 0d6392c697
3 changed files with 200 additions and 58 deletions

View File

@ -47,7 +47,7 @@ void test_saldi()
if (err!=NOERR)
CHECK (FALSE,"Errore nella letture del record di testata");
saldo.write();
//saldo.write();
//saldo.remove();
}

View File

@ -138,7 +138,8 @@ int TABsaldo::read_body(bool lockstruct)
{
naviga_movdett();
}
// _inter_tree->write_cache(); //solo per debug
//_inter_tree->write_cache(); //solo per debug
//prova_inserimento(); //Solo debug per inserimento diretto di un nodo
return 0;
}
@ -153,7 +154,7 @@ void TABsaldo::naviga_movdett()
pather_id = _mov->curr().get_real(ABMD_IDPADRE);
lbrother_id = _mov->curr().get_real(ABMD_IDPREC);
*_newrec = _mov->curr();
_inter_tree->insert_node(*_newrec,lbrother_id,pather_id,my_id,TRASFERITO);
_inter_tree->insert_node(*_newrec,lbrother_id,pather_id,my_id);
if (_mov->has_rbrother())
{
@ -175,6 +176,22 @@ void TABsaldo::naviga_movdett()
}
// Questa rudimentale funzione serve solo per il debug: richiama direttamente
//la insert_node di un saldo IMMETTENDO un nuovo nodo nella struttura.
// Cambiando i parametri id posiziona il nodo in posizione diverse
void TABsaldo::prova_inserimento()
{
TRectype prova(LF_MOVDETT);
TNumeric_id lbrother_id,pather_id,my_id;
lbrother_id = 13;
pather_id = 0;
prova.put(ABMD_CODDITTA,"00001");
prova.put(ABMD_ANNO,"1996");
prova.put(ABMD_CODPDB,"001");
prova.put(ABMD_TIPOBIL,"E2");
prova.put(ABMD_CODCBL,"000000000200");
_inter_tree->insert_node(prova,lbrother_id,pather_id,my_id,IMMESSO);
}
/**************************************************************************************************/
// TAnalisi_bil
@ -290,7 +307,9 @@ int TAnalisi_bil::read_body(bool lock_struct )
if (_ana->goto_root())
id_relana=_ana->curr().get_real(ABRA_ID);
naviga_relazioni(id_relana,ID_NULLO,ID_NULLO);
}
}
//_inter_tree->write_cache(); //solo per debug
//prova_inserimento(); //Solo debug per inserimento diretto di un nodo
return 0;
}
@ -302,7 +321,7 @@ void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNum
_relaz->curr_id(key_rel);
_newrec = sincronizza_relana(begin_relana, id_relana);
currid=_newrec->get_real(ABRA_ID);
_inter_tree->insert_node(*_newrec,id_prec,id_padre,currid,TRASFERITO);
_inter_tree->insert_node(*_newrec,id_prec,id_padre,currid);
//Controllo se c'è un fratello di rel_voci
if (_relaz->has_rbrother())
@ -320,6 +339,10 @@ void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNum
error_box ("Errore di consistenza nei dati di relvoci: è previsto un fratello ma non è stato trovato");
}
} // Il record di _relaz non ha un fratello destro
_inter_tree->link_succ_zero(currid); //Azzera link fratello
if (_relaz->goto_firstson())
{ //Figlio di rel_voci trovato
//Cerco il figlio di rel_ana: se non si trova c'è una inconsistenza nei dati
@ -333,6 +356,8 @@ void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNum
naviga_relazioni(id_relana, ID_NULLO , currid);
}//Se non trovo il figlio di una relazione, potrebbe essere una foglia di un ramo dell'albero
_relaz->goto_node(key_rel); //Per risalire al nodo che mi ha chiamato in relvoci
_inter_tree->link_son_zero(currid); //azzera link filgio
}
//Sincronizza relana con quello che trovo in relaz: relaz è navigato da naviga_relazioni
@ -378,7 +403,7 @@ TRectype *TAnalisi_bil::sincronizza_relana(const TNumeric_id &begin_relana,TNume
_newrec->put(ABRA_CODVC,_relaz->curr().get(ABRL_CODCOMP));
_newrec->put(ABRA_NCOMP,_relaz->curr().get(ABRL_IDCOMP));
id_relana = ID_NULLO; // Serve per eseguire correttamente la new_id
_newrec->put(ABRA_ID,_ana->new_id(id_relana));
_newrec->put(ABRA_ID,_ana->new_id(id_relana)); //Questa è stata spostata alla insert_node
_inter_tree->set_status_node(_newrec->get_real(ABRA_ID),NODO_AGGIUNTO);
}
@ -424,6 +449,20 @@ bool TAnalisi_bil::TArray_fratelli::used(TObject *o)
return ((TRectype *)o)->empty();
}
// Questa rudimentale funzione serve solo per il debug: richiama direttamente
//la insert_node di un saldo IMMETTENDO un nuovo nodo nella struttura.
// Cambiando i parametri id posiziona il nodo in posizione diverse
void TAnalisi_bil::prova_inserimento()
{
TRectype prova(LF_RELANA);
TNumeric_id lbrother_id,pather_id,my_id;
lbrother_id = 0;
pather_id = 14;
prova.put(ABRA_CODAN,"A1");
_inter_tree->insert_node(prova,lbrother_id,pather_id,my_id,IMMESSO);
}
/**************************************************************************************************/
// TLocal_relana3 & TLocal_balance3
/**************************************************************************************************/
@ -575,7 +614,7 @@ void TAlbero_locale::set_status_node(const TNumeric_id &id, const char *status)
TNumeric_id &TAlbero_locale::new_id(TNumeric_id id)
{
if (id == ID_NULLO)
_last_insert_id+1;
_last_insert_id=_last_insert_id+1;
else
_last_insert_id = max(_last_insert_id,id);
return _last_insert_id;
@ -587,22 +626,27 @@ bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, cons
{
const char* dirty_value=NODO_MODIFICATO;
TNumeric_id id_succ;
TToken_string key;
key=get_headkey();
TRectype parente(current());
if (id == ID_NULLO)
id = new_id(id);
if (id == ID_NULLO)
{
id = new_id(id);
set_status_node(id,NODO_AGGIUNTO);
}
else
new_id(id);
//Cerco il mio fratello precedente
if (id_prec != ID_NULLO)
{ //Aggiorno il successivo del mio precedente dicendogli che il suo successivo sono io
key.add(id_prec.string());
parente = _local_cache->get(key);
if (parente.get_real(idsucc_fieldname()) != id)
goto_node(id_prec);
if (_currnode->get_real(idsucc_fieldname()) != id)
{// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status
parente.put(idsucc_fieldname(),id.string());
_local_cache->put(parente);
// Se il nodo è IMMESSO devo mantenere il link con il successivo per mantenere integra la struttutra
if (flag_it == IMMESSO)
{
id_succ = _currnode->get_real(idsucc_fieldname());
}
_currnode->put(idsucc_fieldname(),id.string());
_local_cache->put(*_currnode);
set_status_node(id_prec,dirty_value); //Setto l'eventuale flag di array modificato per il fratello
}
}
@ -610,19 +654,52 @@ bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, cons
{ //Se non ho il mio precedente, allora o sono una radice principale o divento il primo figlio:
if (id_padre != ID_NULLO)
{ //Sono un primo figlio: rintraccio mio padre e gli dico che il suo primo figlio ora, sono io
key.add(id_padre.string());
parente = _local_cache->get(key);
if(parente.get_real(idson_fieldname()) != id)
goto_node(id_padre);
if(_currnode->get_real(idson_fieldname()) != id)
{// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status
parente.put(idson_fieldname(),id.string());
_local_cache->put(parente);
if (flag_it == IMMESSO)
{
id_succ = _currnode->get_real(idson_fieldname());
}
_currnode->put(idson_fieldname(),id.string());
_local_cache->put(*_currnode);
set_status_node(id_padre,dirty_value); //Setto l'eventuale flag di array modificato per il padre
}
} // Sono una radice principale e quindi sono orfana di padre
} // Sono una radice principale e quindi sono orfana di padre: posso essere solo un nuovo nodo IMMESSO direttamente
else
{
if (flag_it == IMMESSO)
{
goto_root();
id_succ = _currnode->get_real(id_fieldname());
}
}
}
//Ora aggiorno me stesso
// Se il nodo è immesso controllo che ci sia un link al successivo da ripristinare
if (flag_it == IMMESSO)
{
if (id_succ != ID_NULLO)
{ //Esiste un nodo che prima era il successivo dell'attuale mio precedente: devo modificarlo per
//dirgli che ora il suo precedente sono io
goto_node(id_succ);
// Il mio successivo deve essere effettivamente modificato
if (_currnode->get_real(idprec_fieldname()) != id)
{
_currnode->put(idprec_fieldname(),id.string());
_local_cache->put(*_currnode);
set_status_node(id_succ,dirty_value); //Setto l'eventuale flag di array modificato per il fratello
}// Altrimenti il nodo non è da modificare
//Aggiorno me stesso
node.put(idsucc_fieldname(),id_succ.string());
node.put(idson_fieldname(),ID_NULLO);
//set_current(node);
}
}
//Ora aggiorno me stesso: solo quella parte che rimane da aggiornare
put_headkey(node);
node.put(id_fieldname(),id.string());
if ((node.get_real(idprec_fieldname()) != id_prec) ||
(node.get_real(idfather_fieldname()) != id_padre))
{// Il nodo è effettivamente modificato: apporto le modifiche e setto lo status
@ -630,13 +707,6 @@ bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, cons
node.put(idfather_fieldname(),id_padre.string());
set_status_node(id,dirty_value);
}
if (flag_it == IMMESSO)
{
node.put(idsucc_fieldname(),id_succ.string());
node.put(idson_fieldname(),ID_NULLO);
//set_current(node);
}
_local_cache->put(node);
goto_node(node);
return TRUE;
@ -860,6 +930,55 @@ void TAlbero_locale::goto_node(const TNumeric_id id)
*_currnode = _local_cache->get(key);
}
void TAlbero_locale::link_succ_zero(const TNumeric_id currid)
{ // Se il nodo è da rimuovere non eseguo nessuna operazione: potrebbe causre problemi alla cache
TString *status = get_status_node(currid);
if ((status != NULL) && (*status != NODO_RIMOSSO))
{ //Posiziono il nodo che sto aggiornando
goto_node(currid);
//Tento di posizionarmi sul fratello se questo può avere senso
if (current().get_real(idsucc_fieldname()) != ID_NULLO)
{ //Secondo il link, ci dovrebbe essere un fratello
status = get_status_node(current().get_real(idsucc_fieldname()));
if ((status != NULL) && (*status != NODO_RIMOSSO))
{ // Entro qui solo se il nodo esite, e lo status è stato fissato ad un valore diverso dal RIMOSSO
goto_node(current().get_real(idsucc_fieldname()));
if (current().empty())
{ // Se però non esiste modifico il record
goto_node(currid);
current().put(idsucc_fieldname(),ID_NULLO);
_local_cache->put(current());
set_status_node(currid,NODO_MODIFICATO);
}
}
}
}
}
void TAlbero_locale::link_son_zero(const TNumeric_id currid)
{ // Se il nodo è da rimuovere non eseguo nessuna operazione: potrebbe causre problemi alla cache
TString *status = get_status_node(currid);
if ((status != NULL) && (*status != NODO_RIMOSSO))
{ //Posiziono il nodo che sto aggiornando
goto_node(currid);
//Tento di posizionarmi sul fratello se questo può avere senso
if (current().get_real(idson_fieldname()) != ID_NULLO)
{ //Secondo il link, ci dovrebbe essere un fratello
status = get_status_node(current().get_real(idson_fieldname()));
if ((status != NULL) && (*status != NODO_RIMOSSO))
{ // Entro qui solo se il nodo esite, e lo status è stato fissato ad un valore diverso dal RIMOSSO
goto_node(current().get_real(idson_fieldname()));
if (current().empty())
{ // Se però non esiste modifico il record
goto_node(currid);
current().put(idson_fieldname(),ID_NULLO);
_local_cache->put(current());
set_status_node(currid,NODO_MODIFICATO);
}
}
}
}
}
/**************************************************************************************************/
// TAlbero_relana
@ -1192,23 +1311,34 @@ void TAlbero_relvoci::node2id(const TObject * node,TNodeId & id) const
/**************************************************************************************************/
TAlbero_movdett::TAlbero_movdett( const char * tabcode)
{
_codtab=tabcode;
_codtab = tabcode;
_movdett=new TLocalisamfile(LF_MOVDETT);
/* _relana->put(ABRA_CODAN,_codtab);
_relana->put(ABRA_ID,MAX_ID_REL);
//Trova l'ultimo id usato in relana: DA COMPLETARE !!!
int err = _relana->read(_isgteq); //Codifica errori in TIsamerr
/* _movdett->put(ABMD_CODDITTA,_codtab.get(0));
_movdett->put(ABMD_ANNO,_codtab.get(1));
_movdett->put(ABMD_CODPDB,_codtab.get(2));
_movdett->put(ABMD_TIPOBIL,_codtab.get(3));
_movdett->put(ABMD_CODCBL,_codtab.get(4));
_movdett->put(ABMD_ID,MAX_ID_MOVDETT);
//Trova l'ultimo id usato in MOVDETT: DA COMPLETARE !!!
int err = _movdett->read(_isgteq); //Codifica errori in TIsamerr
if (err == NOERR)
{ // Ho trovato il primo della tabella successiva: leggendo il precedente
// ho l'ultimo record dalla tabella cercata
_relana->prev();
if (_relana->get(ABRA_CODAN) != _codtab)
{ // Ho trovato il primo della "categoria" successiva: leggendo il precedente
// ho l'ultimo record cercato
_movdett->prev();
TString16 format =_movdett->get(ABMD_CODDITTA);
TToken_string controllo = format.right_just(5,'0');
controllo.add(_movdett->get(ABMD_ANNO));
controllo.add(_movdett->get(ABMD_CODPDB));
controllo.add(_movdett->get(ABMD_TIPOBIL));
controllo.add(_movdett->get(ABMD_CODCBL));
if (controllo != _codtab)
{ // Non esiste la tabella
; //_last_id viene lasciato a 0
}
_last_id = _relana->get_real(ABRA_ID);
_last_id = _movdett->get_real(ABMD_ID);
}
if (err == _isemptyfile)
@ -1218,13 +1348,19 @@ TAlbero_movdett::TAlbero_movdett( const char * tabcode)
if (err == _iseof)
{ // La tabella successiva non esiste: provo a leggere l'ultimo record
_relana->last();
if (_relana->get(ABRA_CODAN) != _codtab)
_movdett->last();
TString16 format =_movdett->get(ABMD_CODDITTA);
TToken_string controllo = format.right_just(5,'0');
controllo.add(_movdett->get(ABMD_ANNO));
controllo.add(_movdett->get(ABMD_CODPDB));
controllo.add(_movdett->get(ABMD_TIPOBIL));
controllo.add(_movdett->get(ABMD_CODCBL));
if (controllo != _codtab)
{ //Tabella non trovata
; //_last_id viene lasciato a 0
}
//Tabella trovata: prendo l'id dell'ultimo record
_last_id = _relana->get_real(ABRA_ID);
_last_id = _movdett->get_real(ABMD_ID);
} */
}
@ -1364,5 +1500,3 @@ void TAlbero_movdett::node2id(const TObject * node,TNodeId & id) const
{
id.format("%ld",_movdett->recno());
}

View File

@ -32,6 +32,7 @@
#include "saldi.h"
#include "movdett.h"
#define MAX_ID_REL 999999999
#define MAX_ID_MOVDETT 999999
#define NODO_AGGIUNTO "A"
#define NODO_MODIFICATO "M"
#define NODO_RIMOSSO "R"
@ -130,7 +131,7 @@ class TAlbero_movdett : public TAlbero_bidir
{
TToken_string _codtab;
TLocalisamfile *_movdett;
TNumeric_id _last_id;
// TNumeric_id _last_id;
protected:
virtual void node2id(const TObject * node,TNodeId & id) const;
public:
@ -168,7 +169,7 @@ public:
// @cmember Inserisce un nodo nella struttura ad albero
//bool insert_node(real id);
// @cmember Restituisce un nuovo id (il primo disponibile)
TNumeric_id &new_id(real id);
// TNumeric_id &new_id(real id);
// @cmember Costruttore
TAlbero_movdett( const char * tabcode);
// @cmember Distruttore
@ -296,13 +297,13 @@ class TAlbero_locale : public TAlbero_bidir
virtual const char * idsucc_fieldname() pure;
virtual const char * idprec_fieldname() pure;
virtual const char * id_fieldname() pure;
virtual const char * get_headkey() pure; // {return " ";} //DA FARE
virtual const char * get_headkey() pure;
public:
// debug
void write_cache() { _local_cache->flush(); }
// @cmember Inserisce un nodo in una struttura di tipo lista doppiamente lincata: trasf_immes è un flag che dice se il nodo è trasferito o immesso
bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id, const char trasf_immes);
bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id, const char trasf_immes = TRASFERITO);
// @cmember Elimina un nodo da una struttura di tipo lista doppiamente lincata
bool delete_node(const TNumeric_id &id);
// @cmember Lancia la rimozione di tutto l'albero
@ -333,9 +334,11 @@ class TAlbero_locale : public TAlbero_bidir
// @cmember Setta lo stato del nodo: valori ammessi = nodo <A>ggiunto, nodo <M>odificato, nodo <R>imosso
void set_status_node(const TNumeric_id &id, const char *status);
// @cmember Ritorna lo stato di un nodo
const char* get_status_node(const TNumeric_id &id);
public:
TString* get_status_node(const TNumeric_id &id)
{return (TString*)_status_node.objptr(id.string());}
void link_succ_zero(const TNumeric_id currid);
void link_son_zero(const TNumeric_id currid);
// @cmember Costruttore
TAlbero_locale(int filenum);
// @cmember Distruttore
@ -353,8 +356,7 @@ protected:
virtual const char * idprec_fieldname(){return ABRA_IDPREC;}
virtual const char * id_fieldname(){return ABRA_ID;}
virtual const char * get_headkey() {return " ";}
virtual void put_headkey(TRectype & node) {node.put(ABRA_CODAN,get_headkey());}
virtual void put_headkey(TRectype & node) {node.put(ABRA_CODAN,get_headkey());}
public:
// @cmember Costruttore
@ -376,7 +378,7 @@ protected:
virtual void put_headkey(TRectype & node) ;
public:
// @cmember Costruttore
TLocal_balance3();
// @cmember Distruttore
@ -451,6 +453,9 @@ class TAnalisi_bil: public TAlbero_AB
virtual int read_body(bool lockstruct);
// @cmember Copia la chiave sul record dei nodi dell'albero
virtual void put_headkey(TRectype &rec) const;
//Serve solo per il debug: lancia l'iserimento
//diretto e manuale di un nodo, testo la funzione di inserimento
void prova_inserimento();
public:
// @cmember Costruttore
TAnalisi_bil();
@ -475,8 +480,11 @@ class TABsaldo: public TAlbero_AB
virtual int read_body(bool lockstruct);
// @cmember Copia la chiave sul record dei nodi dell'albero
virtual void put_headkey(TRectype &rec) const;
//
// @cmember Naviga l'albero dei movimenti e dettagli
void naviga_movdett();
//Serve solo per il debug: lancia l'iserimento
//diretto e manuale di un nodo, testo la funzione di inserimento
void prova_inserimento();
public:
// @cmember Costruttore
TABsaldo();