From 0d6392c697ff363b1f7b9ddea71ad90b467ebce7 Mon Sep 17 00:00:00 2001 From: sauro Date: Thu, 22 Jan 1998 08:50:45 +0000 Subject: [PATCH] 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 --- ab/ab3100.cpp | 2 +- ab/ablib01.cpp | 226 +++++++++++++++++++++++++++++++++++++++---------- ab/ablib01.h | 30 ++++--- 3 files changed, 200 insertions(+), 58 deletions(-) diff --git a/ab/ab3100.cpp b/ab/ab3100.cpp index 9c2ab9232..153ad0f20 100755 --- a/ab/ab3100.cpp +++ b/ab/ab3100.cpp @@ -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(); } diff --git a/ab/ablib01.cpp b/ab/ablib01.cpp index abae7f0cb..956c2134a 100755 --- a/ab/ablib01.cpp +++ b/ab/ablib01.cpp @@ -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()); } - - diff --git a/ab/ablib01.h b/ab/ablib01.h index dd10393da..559f69f60 100755 --- a/ab/ablib01.h +++ b/ab/ablib01.h @@ -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 ggiunto, nodo odificato, nodo 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();