From 2039d9bb9eb648a4858d6114fcbc1da57f29d90e Mon Sep 17 00:00:00 2001 From: sauro Date: Mon, 19 Jan 1998 15:42:10 +0000 Subject: [PATCH] Aggiunti/modificati oggetti per la gestione anche della struttura ad albero dei saldi, movimenti e dettagli git-svn-id: svn://10.65.10.50/trunk@5972 c028cbd2-c16b-5b4b-a496-9718f37d4682 --- ab/ab3100.cpp | 40 +++- ab/ablib01.cpp | 487 ++++++++++++++++++++++++++++++++++++++++++------- ab/ablib01.h | 124 +++++++++---- 3 files changed, 544 insertions(+), 107 deletions(-) diff --git a/ab/ab3100.cpp b/ab/ab3100.cpp index 2aed717dd..5027c444f 100755 --- a/ab/ab3100.cpp +++ b/ab/ab3100.cpp @@ -2,25 +2,26 @@ #include "ablib01.h" -void TTest::main_loop() -{ - //Questa parte di funzione serve per testare la read, write, delete_node, delete_tree, delete_subtree ecc +void test_analisi() +{ + //Questa parte di funzione serve per testare la read, write, delete_node, delete_tree, delete_subtree ecc TLocalisamfile anas(LF_ANALISI); anas.set_curr(new TAnalisi_bil()); anas.put(ABAN_CODAN,"A1"); anas.read(); + // readat -> vedi dopo anas.remove(); //Solo per il test della delete_node o la rimozione di una intera tabella //anas.write(); - /*Questa parte della funzione serve solo per testare la readat + /*Questa parte della funzione serve solo per testare la readat - TRecnotype nrec = 10; //Per capire quale numero ci va scommenta la riga successiva e provare col debug - //nrec = anas.recno(); //nrec è un TRecnotype: dice quale numero ci va dopo + TRecnotype nrec = 14; //Per capire quale numero ci va scommenta la riga di nrec e provare col debug TLocalisamfile anas1(LF_ANALISI); + // nrec = anas1.recno(); //nrec è un TRecnotype: dice quale numero ci va dopo anas1.set_curr(new TAnalisi_bil()); anas1.readat(nrec); //Abilitare solo una di queste funzioni @@ -30,6 +31,33 @@ void TTest::main_loop() E deve esserci solo questo pezzo: tutto il resto deve essere commentato */ } +void test_saldi() +{ + TLocalisamfile saldo(LF_ABSALDI); +// TRecnotype nrec = 96; //Abilitare questa riga per testare la readat + + saldo.set_curr(new TABsaldo()); + saldo.put(ABMD_CODDITTA,"00001"); + saldo.put(ABMD_ANNO,"1996"); + saldo.put(ABMD_CODPDB,"001"); + saldo.put(ABMD_TIPOBIL,"E2"); + saldo.put(ABMD_CODCBL,"000000000200"); +// saldo.readat(nrec); //Se si abilita il test della readat, commentare le righe che riguardano la read + int err=saldo.read(); + if (err!=NOERR) + CHECK (FALSE,"Errore nella letture del record di testata"); + + saldo.write(); + //saldo.remove(); +} + + +void TTest::main_loop() +{ + test_analisi(); //Esegue il test delle funzioni e degli oggetti per l'analisi + //test_saldi(); //Esegue il test delle funzioni e degli oggetti per l'analisi +} + void ab3100(int argc, char **argv) { diff --git a/ab/ablib01.cpp b/ab/ablib01.cpp index 3ab6f50f9..ac91d2ff6 100755 --- a/ab/ablib01.cpp +++ b/ab/ablib01.cpp @@ -5,9 +5,8 @@ #define NODO_MODIFICATO "M" #define NODO_RIMOSSO "R" - /**************************************************************************************************/ -// TAnalisi_bil +// TAlbero_AB /**************************************************************************************************/ TAlbero_AB::TAlbero_AB(int filenum) @@ -22,6 +21,10 @@ int TAlbero_AB::write(TBaseisamfile &analisi) const { commit_body(); } + else + { + err = rewrite(analisi); + } if (err) CHECK (FALSE,"Errore di scrittura del record sull'isamfile"); return err; @@ -40,9 +43,9 @@ int TAlbero_AB::rewrite(TBaseisamfile &analisi) const } //Leggo la "testata" del record -int TAlbero_AB::read(TBaseisamfile& analisi, word isop, word lockop) +int TAlbero_AB::read(TBaseisamfile& saldi, word isop, word lockop) { - int err=TRectype::read(analisi, isop, lockop); + int err=TRectype::read(saldi, isop, lockop); if (err==NOERR) read_body(FALSE); return err; @@ -60,23 +63,23 @@ int TAlbero_AB::readat(TBaseisamfile& analisi, TRecnotype nrec, word lockop) int TAlbero_AB::remove(TBaseisamfile& f) const { -/*Abilitare questa parte solo per effettuare un debug della delete_node +//*Abilitare questa parte solo per effettuare un debug della delete_node // anche se messa in questa posizione, la chiamata non ha senso - TLocalisamfile lf(LF_RELANA); + // TLocalisamfile lf(LF_RELANA); TNumeric_id id; id = 17; _inter_tree->delete_node(id); - int errc = commit_body(lf); + int errc = commit_body(); if (errc != NOERR) { message_box("Errore nell'aggiornameno del file dati"); //return errc; } return 0; -*/ + -//*Abilitare solo questa parte per il test della remove_tree +/*Abilitare solo questa parte per il test della remove_tree _inter_tree->delete_tree(); int errc = commit_body(); if (errc != NOERR) @@ -85,7 +88,7 @@ int TAlbero_AB::remove(TBaseisamfile& f) const //return errc; } int err = TRectype::remove(f); - return err; + return err; */ } void TAlbero_AB::zero() @@ -95,6 +98,148 @@ void TAlbero_AB::zero() } +/**************************************************************************************************/ +// TABsaldo +/**************************************************************************************************/ +TABsaldo::TABsaldo() + :TAlbero_AB(LF_ABSALDI) +{ + _saldi = new TLocalisamfile(LF_ABSALDI); + _movdett = new TLocalisamfile(LF_MOVDETT); +// _relaz = NULL; +// _ana = NULL; + _inter_tree = new TLocal_balance3(); + _newrec = new TRectype(LF_MOVDETT); +} + +TABsaldo::~TABsaldo() +{ + delete _saldi; + delete _movdett; + delete _inter_tree; + delete _newrec; +} + +void TABsaldo::put_headkey(TRectype &rec) const +{ + rec.put(ABMD_CODDITTA, get(ABS_CODDITTA)); + rec.put(ABMD_ANNO, get(ABS_ANNO)); + rec.put(ABMD_CODPDB, get(ABS_CODPDB)); + rec.put(ABMD_TIPOBIL, get(ABS_TIPOBIL)); + rec.put(ABMD_CODCBL, get(ABS_CODCBL)); +} + +int TABsaldo::commit_body() const +{ + _inter_tree->write_cache(); + TRectype rec(_inter_tree->current().num()); + TLocalisamfile filebody(rec.num()); + TString status; + //Estraggo un nodo per volta basandomi sull'assoc_array degli status + while (_inter_tree->dirty_nodes() > 0) + { + TNumeric_id id; + //int prova = _inter_tree->dirty_nodes(); //solo debug + + id=ID_NULLO; + rec= _inter_tree->extract_dirtynode(id, status); + put_headkey(rec); + + //Ho un rectype e uno status node + if (status == NODO_AGGIUNTO) + { + if (filebody.curr().empty()) + { //Se il cursor di relana è posizionato in modo errato: + //lo sistemo sull'ultimo record del file + //DOMANDA: - Perchè ??? + //TENATATIVO DI RISPOSTA: - Quando l'ultima azione effettuata (prima di questa "aggiunta") è la rimozione + // dell'ultimo record probabilmente (ma non sono sicuro) il cursore non è posizionato (o forse + // è posizionato in modo errato come ad es. dopo l'EOF, visto che l'EOF era sull'ultimo record rimosso) + // e quando eseguo un tentativo di scrittura da un errore di chiave duplicata (anche se questa non esiste); + // In tutti gli altri casi (quando l'ultima azione è stata una write o una rewrite o una remove di un record + // che non sia l'ultimo) questo problema non esiste. + //RISPOSTA ESATTA: - Bho !!! + filebody.last(); + } + int err = filebody.write(rec); + if (err != NOERR) + return err; + } + if (status == NODO_MODIFICATO) + { + int err = filebody.rewrite(rec); + if (err != NOERR) + return err; + } + if (status == NODO_RIMOSSO) + { + filebody.read(rec); //Devo leggere sul file per posizionare il cursore: stesso motivo di prima + int err = filebody.remove(rec); + if (err != NOERR) + return err; + } + // In tutti gli altri casi il nodo non viene modificato + } + return NOERR; +} + +//Leggo il "corpo" del record +int TABsaldo::read_body(bool lockstruct) +{ + //_ana = new TAlbero_relana(get(ABAN_CODAN)); + TString codditta = get(ABS_CODDITTA); + TToken_string key = codditta.right_just(5,'0'); + key.add(get(ABS_ANNO)); + key.add(get(ABS_CODPDB)); + key.add(get(ABS_TIPOBIL)); + key.add(get(ABS_CODCBL)); + _mov = new TAlbero_movdett(key); + + if (_mov->goto_root()) + { + //TNumeric_id id_movdett; + //id_movdett = _mov->curr().get_real(ABMD_ID); + naviga_movdett(); + } + //_inter_tree->write_cache(); //solo per debug + return 0; +} + +//Naviga l'albero dei movimenti-dettagli +void TABsaldo::naviga_movdett() +{ + TNodeId key_rel; + _mov->curr_id(key_rel); + TNumeric_id lbrother_id, pather_id, my_id; + TRectype new_node(LF_MOVDETT); + + my_id = _mov->curr().get_real(ABMD_ID); + pather_id = _mov->curr().get_real(ABMD_IDPADRE); + lbrother_id = _mov->curr().get_real(ABMD_IDPREC); + new_node = _mov->curr(); + _inter_tree->insert_node(new_node,lbrother_id,pather_id,my_id); + + if (_mov->has_rbrother()) + { + if (_mov->goto_rbrother()) + { //Fratello di movdett trovato + naviga_movdett(); + _mov->goto_node(key_rel); + } + } + + if (_mov->has_son()) + { + if (_mov->goto_firstson()) + { //Fratello di movdett trovato + naviga_movdett(); + _mov->goto_node(key_rel); + } + } +} + + + /**************************************************************************************************/ // TAnalisi_bil /**************************************************************************************************/ @@ -137,7 +282,7 @@ int TAlbero_AB::commit_body() const while (_inter_tree->dirty_nodes() > 0) { TNumeric_id id; - int prova = _inter_tree->dirty_nodes(); +// int prova = _inter_tree->dirty_nodes(); solo debug id=ID_NULLO; rec= _inter_tree->extract_dirtynode(id, status); @@ -209,9 +354,10 @@ 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); - } + } return 0; } + //Naviga l'albero delle relazioni void TAnalisi_bil::naviga_relazioni(const TNumeric_id & begin_relana, const TNumeric_id & id_prec,const TNumeric_id & id_padre) { @@ -345,8 +491,9 @@ bool TAnalisi_bil::TArray_fratelli::used(TObject *o) } /**************************************************************************************************/ -// TAlbero_locale +// TLocal_relana3 & TLocal_balance3 /**************************************************************************************************/ + TLocal_relana3::TLocal_relana3() : TAlbero_locale(LF_RELANA) { @@ -364,26 +511,29 @@ TLocal_balance3::~TLocal_balance3() {} +/**************************************************************************************************/ +// TAlbero_locale +/**************************************************************************************************/ TAlbero_locale::TAlbero_locale(int filenum) { // versione definitiva: // _currnode = new TRectype(filenum); -// _local_cahe = new TRWrecord_cache(new TIsamtempfile(filenum,"",TRUE,TRUE)); +// _local_cache = new TRWrecord_cache(new TIsamtempfile(filenum,"",TRUE,TRUE)); // debug mods: _currnode = new TRectype(filenum); if (filenum==LF_RELANA) _f= new TIsamtempfile(filenum,"/com/relana",FALSE,FALSE); else - _f= new TIsamtempfile(filenum,"",FALSE,FALSE); - _local_cahe = new TRWrecord_cache(_f); + _f= new TIsamtempfile(filenum,"/com/movdett",FALSE,FALSE); + _local_cache = new TRWrecord_cache(_f); //zero(); // resetta l'albero locale } TAlbero_locale::~TAlbero_locale() { - delete _local_cahe; + delete _local_cache; delete _f; } @@ -418,12 +568,12 @@ TRectype TAlbero_locale::extract_dirtynode(TNumeric_id &id, TString &status) if (status != NODO_RIMOSSO) { key.add(id.string()); //La chiave è completamente ricostruita per la ricerca sulla cache - rec = _local_cahe->get(key); //passo la chiave (formata da codtab e id) e ritorna il rectype + rec = _local_cache->get(key); //passo la chiave (formata da codtab e id) e ritorna il rectype } else { //Riempio manualmente il record che deve essere rimosso: inserisco solo la chiave //rec.put(ABRA_CODAN, ??? ); - rec.put(ABRA_ID,id.string()); + rec.put(id_fieldname(),id.string()); } //A questo punto il record è completo e so già quale operazione devo compierci sopra @@ -503,9 +653,9 @@ bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, cons 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_cahe->get(key); - parente.put(ABRA_IDSUCC,id.string()); - _local_cahe->put(parente); + parente = _local_cache->get(key); + parente.put(idsucc_fieldname(),id.string()); + _local_cache->put(parente); set_status_node(id_prec,NODO_MODIFICATO); //Setto l'eventuale flag di array modificato per il fratello } else @@ -513,19 +663,21 @@ bool TAlbero_locale::insert_node(TRectype & node,const TNumeric_id id_prec, cons 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_cahe->get(key); - parente.put(ABRA_IDFIGLIO,id.string()); - _local_cahe->put(parente); + parente = _local_cache->get(key); + parente.put(idson_fieldname(),id.string()); + _local_cache->put(parente); set_status_node(id_padre,NODO_MODIFICATO); //Setto l'eventuale flag di array modificato per il padre } // Sono una radice principale e quindi sono orfana di padre } //Ora aggiorno me stesso - node.put(ABRA_IDPREC,id_prec.string()); - node.put(ABRA_IDPADRE,id_padre.string()); - node.put(ABRA_IDSUCC,id_succ.string()); - node.put(ABRA_IDFIGLIO,ID_NULLO); - _local_cahe->put(node); + madekey(node); +// node.put(ABRA_CODAN,get_headkey()); //Eseguo un combio della chiave: non serve avere il codice della tabella nella cache + node.put(idprec_fieldname(),id_prec.string()); + node.put(idfather_fieldname(),id_padre.string()); + node.put(idsucc_fieldname(),id_succ.string()); + node.put(idson_fieldname(),ID_NULLO); + _local_cache->put(node); //set_current(node); goto_node(node); set_status_node(id,NODO_MODIFICATO); @@ -541,54 +693,62 @@ bool TAlbero_locale::delete_node(const TNumeric_id &id) TNumeric_id id_padre, id_figlio, id_prec, id_succ; goto_node(id); - TToken_string key = get_headkey(); + TToken_string key; // id = _currnode->get_real(ABRA_ID); - id_padre = _currnode->get_real(ABRA_IDPADRE); - id_figlio = _currnode->get_real(ABRA_IDFIGLIO); - id_prec = _currnode->get_real(ABRA_IDPREC); - id_succ = _currnode->get_real(ABRA_IDSUCC); + id_padre = _currnode->get_real(idfather_fieldname()); + id_figlio = _currnode->get_real(idson_fieldname()); + id_prec = _currnode->get_real(idprec_fieldname()); + id_succ = _currnode->get_real(idsucc_fieldname()); //Ricerco il padre per modificare il suo primo figlio, solo se io sono il suo primo figlio if (id_padre != ID_NULLO) { - key.add(id_padre.string(),1); - parente=_local_cahe->get(key); //padre - if (parente.get(ABRA_IDFIGLIO) == id.string()) + key.cut(0); + key = get_headkey(); + key.add(id_padre.string()); + parente=_local_cache->get(key); //padre + if (parente.get(idson_fieldname()) == id.string()) { //Il nodo che sta per essere rimosso è il primo figlio di un padre - parente.put(ABRA_IDFIGLIO,id_succ.string()); //Aggiorno il padre - _local_cahe->put(parente); + parente.put(idson_fieldname(),id_succ.string()); //Aggiorno il padre + _local_cache->put(parente); } } //Ricerco il mio fratello precedente per dirgli che io non sono più //suo fratello successivo, e gli dico anche quale sarà il suo successivo if (id_prec != ID_NULLO) - { - key.add(id_prec.string(),1); - parente=_local_cahe->get(key); //fratello sinistro - parente.put(ABRA_IDSUCC,id_succ.string()); //Assegno al mio fratello sinistro il mio fratello destro - _local_cahe->put(parente); + { + key.cut(0); + key = get_headkey(); + key.add(id_prec.string()); + parente=_local_cache->get(key); //fratello sinistro + parente.put(idsucc_fieldname(),id_succ.string()); //Assegno al mio fratello sinistro il mio fratello destro + _local_cache->put(parente); } //Dico a mio fratello successivo chi il suo precedente non sono più io, //e gli dico che il suo precedente è il MIO precedente if (id_succ != ID_NULLO) - { - key.add(id_succ.string(),1); - parente=_local_cahe->get(key); //fratello destro - parente.put(ABRA_IDPREC,id_prec.string()); //Assegno al mio fratello destro il mio fratello sinistro - _local_cahe->put(parente); + { + key.cut(0); + key = get_headkey(); + key.add(id_succ.string()); + parente=_local_cache->get(key); //fratello destro + parente.put(idprec_fieldname(),id_prec.string()); //Assegno al mio fratello destro il mio fratello sinistro + _local_cache->put(parente); } //I miei vicini mi hanno già escluso: non sono più raggiungibile //Ricostruisco la chiave //Elimino i miei link dai fratelli - key.add(id.string(),1); + key.cut(0); + key = get_headkey(); + key.add(id.string()); //node.put(ABRA_IDPADRE,ID_NULLO); - _currnode->put(ABRA_IDPREC,ID_NULLO); - _currnode->put(ABRA_IDSUCC,ID_NULLO); - _local_cahe->put(*_currnode); + _currnode->put(idprec_fieldname(),ID_NULLO); + _currnode->put(idsucc_fieldname(),ID_NULLO); + _local_cache->put(*_currnode); //Elimino i miei figli TNumeric_id nextnode_id; @@ -624,11 +784,12 @@ void TAlbero_locale::zero() { delete_tree(); // cancella l'albero _status_node.destroy(); - _currnode->put(ABRA_ID,ID_NULLO); + _currnode->put(id_fieldname(),ID_NULLO); } bool TAlbero_locale::delete_tree() { + //write_cache(); goto_root(); remove_subtree(ID_NULLO); //Non eliminando il link coi fratelli della radice, remove_subtree naviga tutto l'albero return TRUE; @@ -641,7 +802,7 @@ bool TAlbero_locale::remove_subtree(const TNumeric_id return_id) //cerco il figlio if (has_son()) { - myself_id = _currnode->get_real(ABRA_ID); + myself_id = _currnode->get_real(id_fieldname()); goto_firstson(); remove_subtree(myself_id); } @@ -649,11 +810,11 @@ bool TAlbero_locale::remove_subtree(const TNumeric_id return_id) //cerco il fratello if (has_rbrother()) { - myself_id = _currnode->get_real(ABRA_ID); + myself_id = _currnode->get_real(id_fieldname()); goto_rbrother(); remove_subtree(myself_id); } - TNumeric_id id = _currnode->get(ABRA_ID); + TNumeric_id id = _currnode->get(id_fieldname()); //Questa parte esegue la gestione dell'assoc_array degli stati //in modo tale da mantenerlo allineato con il contenuto della cache @@ -679,30 +840,30 @@ bool TAlbero_locale::remove_subtree(const TNumeric_id return_id) if (return_id != ID_NULLO) goto_node(return_id); else - _currnode->put(ABRA_ID,ID_NULLO); + _currnode->put(id_fieldname(),ID_NULLO); return TRUE; } bool TAlbero_locale::has_son() { - return (_currnode->get_real(ABRA_IDFIGLIO) != ID_NULLO); + return (_currnode->get_real(idson_fieldname()) != ID_NULLO); } bool TAlbero_locale::goto_firstson() { - goto_node(_currnode->get_real(ABRA_IDFIGLIO)); + goto_node(_currnode->get_real(idson_fieldname())); return TRUE; } bool TAlbero_locale::has_rbrother() { - return (_currnode->get_real(ABRA_IDSUCC) != ID_NULLO); + return (_currnode->get_real(idsucc_fieldname()) != ID_NULLO); } bool TAlbero_locale::goto_rbrother() { - goto_node(_currnode->get_real(ABRA_IDSUCC)); + goto_node(_currnode->get_real(idsucc_fieldname())); return TRUE; } @@ -713,20 +874,26 @@ bool TAlbero_locale::goto_root() TToken_string key; TNumeric_id id_prec, id_padre; key=get_headkey(); - key.add(_currnode->get(ABRA_ID)); + key.add(_currnode->get(id_fieldname())); do { - *_currnode = _local_cahe->get(key); - id_prec = _currnode->get_real(ABRA_IDPREC); - id_padre = _currnode->get_real(ABRA_IDPADRE); + *_currnode = _local_cache->get(key); + id_prec = _currnode->get_real(idprec_fieldname()); + id_padre = _currnode->get_real(idfather_fieldname()); if (id_prec != ID_NULLO) { - key.add(id_prec.string(),1); + key.cut(0); + key=get_headkey(); + key.add(id_prec.string()); } else { if (id_padre != ID_NULLO) - key.add(id_padre.string(),1); + { + key.cut(0); + key=get_headkey(); + key.add(id_padre.string()); + } } } while (id_prec != ID_NULLO || id_padre != ID_NULLO); return TRUE; @@ -737,7 +904,7 @@ void TAlbero_locale::goto_node(const TNumeric_id id) TToken_string key; key=get_headkey(); key.add(id.string()); - *_currnode = _local_cahe->get(key); + *_currnode = _local_cache->get(key); } @@ -1066,3 +1233,183 @@ void TAlbero_relvoci::node2id(const TObject * node,TNodeId & id) const { id.format("%ld",_relvoci->recno()); } + +/**************************************************************************************************/ +// TAlbero_movdett +/**************************************************************************************************/ +TAlbero_movdett::TAlbero_movdett( const char * 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 + 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) + { // Non esiste la tabella + ; //_last_id viene lasciato a 0 + } + _last_id = _relana->get_real(ABRA_ID); + } + + if (err == _isemptyfile) + { //Il file è vuoto + ;//_last_id viene lasciato a 0 + } + + if (err == _iseof) + { // La tabella successiva non esiste: provo a leggere l'ultimo record + _relana->last(); + if (_relana->get(ABRA_CODAN) != _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); + } */ +} + + +//Posiziona relana sul record voluto +bool TAlbero_movdett::goto_id(const TNumeric_id &id) +{ + _movdett->put(ABMD_CODDITTA,_codtab); + _movdett->put(ABMD_ID,id); + if (_movdett->read() == NOERR) + return TRUE; + return FALSE; //Non sono riuscito a posizionarmi sul nodo +} + +//Ricerca la radice di relana +bool TAlbero_movdett::goto_root() +{ + _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)); + //No so nulla sull'id + _movdett->read(_isgteq); //Leggo la prima chiave che si avvicina a quella specificata + TString fctrl = _movdett->get(ABMD_CODDITTA); + TToken_string controllo = fctrl.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) + { + while (has_father()) + { + goto_father(); + } // Ho raggiunto il primo livello + while (has_lbrother()) + { + goto_lbrother(); + }// Ho raggiunto la radice + return TRUE; + } + //Non ho trovato una voce con codice tabella richiesta + return FALSE; +} + +//Dice se un nodo di relana ha il primo figlio +bool TAlbero_movdett::has_son() const +{ + return _movdett->get_real(ABMD_IDFIGLIO)!=ID_NULLO; +} + +//Ricerca il primo filglio di un nodo di relana +bool TAlbero_movdett::goto_firstson() +{ + TNumeric_id id_figlio(_movdett->get_real(ABMD_IDFIGLIO)); + if (id_figlio > 0) + { //Ci deve essere un figlio: lo cerco + //Il CODAN deve rimanere uguale a quello del padre + _movdett->put(ABMD_ID,_movdett->get(ABMD_IDFIGLIO)); + if (_movdett->read() == NOERR) + return TRUE; //Figlio trovato con successo + } + //Non c'è un figlio: non si dovrebbe mai verificare visto che + //si entra in questa funzione solo quando è previsto che ci sia un figlio. + return FALSE; +} + +//Dice se un nodo di relana ha un fratello destro +bool TAlbero_movdett::has_rbrother() const +{ + return _movdett->get_real(ABMD_IDSUCC) != ID_NULLO; +} + +//Ricerca il fratello destro di un nodo di relana +bool TAlbero_movdett::goto_rbrother() +{ + TNumeric_id id_fratello(_movdett->get_real(ABMD_IDSUCC)); + if (id_fratello > 0) + { //Ci deve essere un fratello: lo cerco + //Il CODAN deve rimanere uguale a quello del fratello precedente + _movdett->put(ABMD_ID,_movdett->get(ABMD_IDSUCC)); + if (_movdett->read() == NOERR) + return TRUE; //Fratello trovato con successo + } + //Non c'è un fratello: non si dovrebbe mai verificare visto che + //si entra in questa funzione solo quando è previsto che ci sia un fratello. + return FALSE; +} + +//Dice se un nodo di relana ha un padre +bool TAlbero_movdett::has_father() const +{ + return _movdett->get_real(ABMD_IDPADRE) != ID_NULLO; +} + +//Ricerca il padre del nodo di relana +bool TAlbero_movdett::goto_father() +{ + _movdett->put(ABMD_ID,_movdett->get(ABMD_IDPADRE)); + if (_movdett->read() != NOERR) + CHECK (FALSE,"ERRORE DI PADRE"); //*!*!*!*! DA gestire + else + return TRUE; + return FALSE; +} + +//Ritrona il nodo corrente di relana +TObject *TAlbero_movdett::curr_node() const +{ + return &_movdett->curr(); +} + +//Dice se un nodo di relana ha un fratello sinistro +bool TAlbero_movdett::has_lbrother() const +{ + return _movdett->get_real(ABMD_IDPREC) != ID_NULLO; +} + +//Ricerca il fratello sinistro di un nodo di relana +bool TAlbero_movdett::goto_lbrother() +{ + TNumeric_id id_fratello(_movdett->get_real(ABMD_IDPREC)); + if (id_fratello > 0) + {//Ci deve essere un fratello: lo cerco + //Il CODAN deve rimanere uguale a quello del fratello successivo + _movdett->put(ABMD_ID,_movdett->get(ABMD_IDPREC)); + if (_movdett->read() == NOERR) + return TRUE; //Fratello trovato con successo + } + //ERRORE !!! + return FALSE; +} + +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 86db32503..8994ee5b3 100755 --- a/ab/ablib01.h +++ b/ab/ablib01.h @@ -118,10 +118,60 @@ public: {} };*/ + +class TAlbero_movdett : public TAlbero_bidir +{ + TToken_string _codtab; + TLocalisamfile *_movdett; + TNumeric_id _last_id; +protected: + virtual void node2id(const TObject * node,TNodeId & id) const; +public: + // @cmember Ritorna TRUE se riesce a trovare il primo figlio + virtual bool has_son() const; + // @cmember Ritorna TRUE se riesce a trovare il fratello destro + virtual bool has_rbrother() const; + // @cmember Ritorna TRUE se riesce a trovare il padre + virtual bool has_father() const; + // @cmember Ritorna TRUE se riesce a trovare il fratello sinistro + virtual bool has_lbrother() const; + // @cmember Si posiziona sulla radice principale + virtual bool goto_root(); + // @cmember Si posiziona sul primo figlio + virtual bool goto_firstson(); + // @cmember Si posiziona sul padre + virtual bool goto_father(); + // @cmember Si posiziona sul fratello destro + virtual bool goto_rbrother(); + // @cmember Si posiziona sul fratello sinistro + virtual bool goto_lbrother(); + // @cmember Ritorna TRUE se può posizionarsi sul nodo indicato dall'id specificato + virtual bool goto_node(TNodeId & id) + {return(_movdett->readat(atol(id))==NOERR); } + // @cmember Si posiziona sul nodo specificato dall'id + bool goto_id(const TNumeric_id &id); + // @cmember Ritorna il nodo corrente + virtual TObject * curr_node() const; + // @cmember Ritorna il nodo corrente + TRectype & curr() {return (TRectype &)*curr_node();} + // @cmember Esegue un lock +// bool lock(); + // @cmember Esegue un unlock +// void unlock(); + // @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); + // @cmember Costruttore + TAlbero_movdett( const char * tabcode); + // @cmember Distruttore + virtual ~TAlbero_movdett() {;} +}; + //Classe per gestire l'albero di relana class TAlbero_relana : public TAlbero_bidir { - TString16 _codtab; + TString _codtab; TLocalisamfile *_relana; TNumeric_id _last_id; protected: @@ -172,7 +222,7 @@ public: // basandosi sull'albero di relvoci class TAlbero_relvoci : public TAlbero { - TString16 _codtab; + TString _codtab; TLocalisamfile *_relvoci; protected: virtual void node2id(const TObject * node, TNodeId & id) const; @@ -210,10 +260,11 @@ public: // @cmember Distruttore virtual ~TAlbero_relvoci() ; }; + // Struttura da albero basata su un file temporaneo cached class TAlbero_locale : public TAlbero_bidir { - TRWrecord_cache * _local_cahe; + TRWrecord_cache * _local_cache; TLocalisamfile *_f; // da rimuovere !! @@ -221,26 +272,28 @@ class TAlbero_locale : public TAlbero_bidir TNumeric_id _last_insert_id; TAssoc_array _status_node; -protected: -// debug - void write_cache() { _local_cahe->flush(); } - + protected: + // @cmember Elimina il sottoalbero dei figli di un nodo // @cmember che sta per essere eliminato da un struttura di tipo lista doppiamente lincata bool remove_subtree(const TNumeric_id lastnode_id); // @cmember genera/setta il nuovo id TNumeric_id &new_id(TNumeric_id); - + void goto_node(const TNumeric_id id); void goto_node(TRectype &node) {*_currnode = node;} - - virtual const char * idfather_fieldname() pure ; - virtual const char * idson_fieldname() pure; - virtual const char * idsucc_fieldname() pure; - virtual const char * idprec_fieldname() pure; - virtual const char * id_fieldname() pure; - virtual const char * get_headkey(); + + virtual void madekey(TRectype &) pure; + virtual const char * idfather_fieldname() pure ; + virtual const char * idson_fieldname() pure; + 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 public: + // debug + void write_cache() { _local_cache->flush(); } + // @cmember Inserisce un nodo in una struttura di tipo lista doppiamente lincata bool insert_node(TRectype &node, const TNumeric_id id_prec, const TNumeric_id id_padre, TNumeric_id id); // @cmember Elimina un nodo da una struttura di tipo lista doppiamente lincata @@ -286,12 +339,13 @@ protected: class TLocal_relana3 : public TAlbero_locale { protected: - + + virtual void madekey(TRectype & node) {node.put(ABRA_CODAN,get_headkey());} virtual const char * idfather_fieldname() {return ABRA_IDPADRE;} virtual const char * idson_fieldname(){return ABRA_IDFIGLIO;} virtual const char * idsucc_fieldname(){return ABRA_IDSUCC;} virtual const char * idprec_fieldname(){return ABRA_IDPREC;} - virtual const char * id_fieldname(){return ABRA_IDPADRE;} + virtual const char * id_fieldname(){return ABRA_ID;} virtual const char * get_headkey() {return " ";} public: @@ -306,13 +360,20 @@ protected: class TLocal_balance3 : public TAlbero_locale { protected: - + virtual void madekey(TRectype & node) + { + node.put(ABMD_CODDITTA," "); + node.put(ABMD_ANNO," "); + node.put(ABMD_CODPDB," "); + node.put(ABMD_TIPOBIL," "); + node.put(ABMD_CODCBL," "); + } virtual const char * idfather_fieldname() {return ABMD_IDPADRE;} virtual const char * idson_fieldname(){return ABMD_IDFIGLIO;} virtual const char * idsucc_fieldname(){return ABMD_IDSUCC;} virtual const char * idprec_fieldname(){return ABMD_IDPREC;} - virtual const char * id_fieldname(){return ABMD_IDPADRE;} - virtual const char * get_headkey() {return " | | | ";} + virtual const char * id_fieldname(){return ABMD_ID;} + virtual const char * get_headkey() {return " | | | | ";} public: @@ -329,14 +390,14 @@ class TAlbero_AB: public TRectype // @cmember Esegue la scrittura del body del record virtual int commit_body() const; // @cmember Esegue la lettura del body del rocord - virtual int read_body(bool lockstruct); + virtual int read_body(bool lockstruct) {return 0;} //DA FARE // @cmember Copia la chiave sul record dei nodi dell'albero - virtual void put_headkey(TRectype &rec) const; + virtual void put_headkey(TRectype &rec) const {;} //DA FARE public: // @cmember Costruttore TAlbero_AB(int filenum); // #cmember Distruttore - virtual ~TAlbero_AB() ; + virtual ~TAlbero_AB() {;} //DA FARE // @cmember Esegue la lettura della testata di un record da LF_ANALISI e del suo "body" virtual int read(TBaseisamfile& analisi, word isop=_isequal, word lockop=_nolock); // @cmember Esegue la lettura della testata di un record alla posizione nrec da LF_ANALISI e del suo "body" @@ -352,8 +413,6 @@ class TAlbero_AB: public TRectype TAlbero_locale * user_tree() {return _inter_tree;} }; - - class TAnalisi_bil: public TAlbero_AB { @@ -370,7 +429,7 @@ class TAnalisi_bil: public TAlbero_AB TLocalisamfile *_voci; TAlbero_relvoci *_relaz; TAlbero_relana *_ana; - TLocal_relana3 *_inter_tree; + //TLocal_relana3 *_inter_tree; TRectype * _newrec; //buffer per l'inserimento dodo per nodo protected: // @cmember Esegue una navigazione dell'albero di rel_voci e di rel_ana @@ -387,7 +446,7 @@ class TAnalisi_bil: public TAlbero_AB // @cmember Sblocca una tabella di analisi bool unlock_tabella(); // @cmember Esegue la scrittura del body del record scrive il contenuto di una tabella di analisi - virtual int commit_body() const; + //virtual int commit_body() const; // @cmember Esegue la lettura del body del rocord: legge il contenuto di una tabella di analisi virtual int read_body(bool lockstruct); // @cmember Copia la chiave sul record dei nodi dell'albero @@ -403,11 +462,12 @@ class TAnalisi_bil: public TAlbero_AB void set_type(const char * tipo) {put(ABAN_TIPOAN,tipo);} }; -class TABsaldo: public TRectype +class TABsaldo: public TAlbero_AB { TLocalisamfile *_saldi; - TAlbero_relana *_movdett; - TLocal_balance3 *_inter_tree; + TAlbero_movdett *_mov; + TLocalisamfile *_movdett; + //TLocal_balance3 *_inter_tree; TRectype * _newrec; //buffer per l'inserimento dodo per nodo protected: // @cmember Esegue la scrittura del body del record scrive il contenuto di una tabella di analisi @@ -416,11 +476,13 @@ class TABsaldo: public TRectype virtual int read_body(bool lockstruct); // @cmember Copia la chiave sul record dei nodi dell'albero virtual void put_headkey(TRectype &rec) const; + // + void naviga_movdett(); public: // @cmember Costruttore TABsaldo(); // #cmember Distruttore - virtual ~ TABsaldo() ; + virtual ~ TABsaldo(); };