//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : MachiningsMgr.cpp Data : 02.06.15 Versione : 1.6f1 // Contenuto : Implementazione gestore database lavorazioni. // // // // Modifiche : 02.06.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "MachiningsMgr.h" #include "MachiningDataFactory.h" #include "DllMain.h" #include "/EgtDEv/Include/EmkMachiningConst.h" #include "/EgtDEv/Include/EGnStringKeyVal.h" #include "/EgtDEv/Include/EGnStringUtils.h" #include "/EgtDEv/Include/EGnFileUtils.h" #include "/EgtDEv/Include/EGnScanner.h" #include "/EgtDEv/Include/EGnWriter.h" #include "/EgtDEv/Include/EgtPointerOwner.h" #include #include using namespace std ; //---------------------------------------------------------------------------- const string MF_HEADER = "[HEADER]" ; const string MF_VERSION = "VERSION" ; const string MF_TOTAL = "TOTAL" ; const string MF_SIZE = "SIZE" ; const int MF_CURR_VER = 1001 ; //---------------------------------------------------------------------------- MachiningsMgr::MachiningsMgr( void) { m_pTsMgr = nullptr ; m_suCIter = m_suData.cend() ; m_pCurrMach = nullptr ; m_bModified = false ; } //---------------------------------------------------------------------------- MachiningsMgr::~MachiningsMgr( void) { Clear() ; } //---------------------------------------------------------------------------- bool MachiningsMgr::Clear( void) { // libero la memoria dalle lavorazioni for ( auto iIter = m_umData.begin() ; iIter != m_umData.end() ; ++ iIter) { if ( iIter->second != nullptr) delete iIter->second ; } // reset puntatore a gestore utensili m_pTsMgr = nullptr ; // pulisco le tabelle m_umData.clear() ; m_suData.clear() ; // reinizializzo stato m_suCIter = m_suData.cend() ; if ( m_pCurrMach != nullptr) { delete m_pCurrMach ; m_pCurrMach = nullptr ; } m_bModified = false ; return true ; } //---------------------------------------------------------------------------- bool MachiningsMgr::Load( const string& sMachsFile, const ToolsMgr* pTsMgr) { // pulisco Clear() ; // salvo la path del file con i dati m_sMachsFile = sMachsFile ; { string sOut = "MachiningsMgr Init : " + m_sMachsFile ; LOG_INFO( GetEMkLogger(), sOut.c_str()) } // verifico il gestore degli utensili if ( pTsMgr == nullptr) { LOG_ERROR( GetEMkLogger(), "LoadMachinings : Error on ToolsMgr") return false ; } m_pTsMgr = pTsMgr ; // inizializzo lo scanner Scanner TheScanner ; if ( ! TheScanner.Init( m_sMachsFile, ";")) { LOG_ERROR( GetEMkLogger(), "LoadMachinings : Error on Init") return false ; } // variabili di stato della lettura bool bOk = true ; bool bEnd = false ; // leggo l'intestazione int nVersion = 0 ; int nTotal = 0 ; if ( ! LoadHeader( TheScanner, nVersion, nTotal, bEnd)) { bOk = false ; string sOut = "LoadMachinings : Error on Header" ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) } { string sOut = "LoadMachinings : FileVer = " + ToString( nVersion) + " CurrVer = " + ToString( MF_CURR_VER) ; LOG_INFO( GetEMkLogger(), sOut.c_str()) } // dimensiono map const int MIN_BUCKETS = 163 ; m_umData.rehash( MIN_BUCKETS) ; // ciclo di lettura delle lavorazioni do { if ( ! LoadOneMachining( TheScanner, bEnd)) { bOk = false ; string sOut = "LoadMachinings : Error on line " + ToString( TheScanner.GetCurrLineNbr()) ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) } } while ( bOk && ! bEnd) ; // termino lo scanner TheScanner.Terminate() ; return bOk ; } //---------------------------------------------------------------------------- bool MachiningsMgr::LoadHeader( Scanner& TheScanner, int& nVersion, int& nTotal, bool& bEnd) { // leggo la prossima linea string sLine ; if ( ! TheScanner.GetLine( sLine)) { // fine file bEnd = true ; return true ; } // deve essere intestazione if ( sLine != MF_HEADER) return false ; bool bOk = true ; // leggo le linee successive bEnd = true ; nVersion = 1000 ; nTotal = 0 ; while ( bOk && TheScanner.GetLine( sLine)) { // se utensile successivo if ( sLine.front() == '[' && sLine.back() == ']') { TheScanner.UngetLine( sLine) ; bEnd = false ; break ; } // separo chiave da valore string sKey, sVal ; SplitFirst( sLine, "=", sKey, sVal) ; // riconosco la chiave if ( ToUpper( sKey) == MF_VERSION) bOk = FromString( sVal, nVersion) ; else if ( ToUpper( sKey) == MF_TOTAL) bOk = FromString( sVal, nTotal) ; else bOk = false ; } return bOk ; } //---------------------------------------------------------------------------- bool MachiningsMgr::LoadOneMachining( Scanner& TheScanner, bool& bEnd) { // leggo la prossima linea string sLine ; if ( ! TheScanner.GetLine( sLine)) { // fine file bEnd = true ; return true ; } // deve essere intestazione if ( sLine.front() != '[' || sLine.back() != ']') return false ; Trim( sLine, "[]") ; // separo tipo da contatore string sType, sCount ; SplitFirst( sLine, "_", sType, sCount) ; ToUpper( sType) ; // alloco la lavorazione del tipo corrispondente PtrOwner pMch( MCHDATA_CREATE( MCHDATA_NAMETOTYPE( sType))) ; if ( IsNull( pMch)) return false ; bool bOk = true ; // imposto dimensione di default int nSize = 0 ; switch ( pMch->GetType()) { case MT_DRILLING : nSize = 11 ; break ; case MT_SAWING : nSize = 15 ; break ; case MT_MILLING : nSize = 26 ; break ; } // eventuale lettura da file if ( TheScanner.GetLine( sLine)) { if ( ! GetVal( sLine, MF_SIZE, nSize)) TheScanner.UngetLine( sLine) ; } // leggo i dati della lavorazione bEnd = true ; const int DIM_BS = 64 ; bitset Flag ; assert( nSize <= DIM_BS) ; while ( bOk && TheScanner.GetLine( sLine)) { // se lavorazione successiva if ( sLine.front() == '[' && sLine.back() == ']') { TheScanner.UngetLine( sLine) ; bEnd = false ; break ; } // interpreto la linea int nKey = - 1 ; bOk = pMch->FromString( sLine, nKey) ; // se tutto bene, dichiaro letto il campo if ( bOk) Flag.set( nKey) ; } // verifico di aver letto tutti i campi bOk = bOk && ( Flag.count() == nSize) ; // salvo i dati della lavorazione bOk = bOk && m_umData.emplace( pMch->m_Uuid, Get( pMch)).second ; bOk = bOk && m_suData.emplace( pMch->m_sName, pMch->m_Uuid).second ; Release( pMch) ; return bOk ; } //---------------------------------------------------------------------------- bool MachiningsMgr::Save( bool bCompressed) const { // se non ci sono state modifiche, esco subito if ( ! m_bModified) return true ; // faccio copia di backup del file originale CopyFileEgt( m_sMachsFile, m_sMachsFile + ".bak") ; // inizializzo il writer Writer TheWriter ; if ( ! TheWriter.Init( m_sMachsFile, bCompressed)) { LOG_ERROR( GetEMkLogger(), "SaveMachinings : Error on Init") return false ; } // scrivo linea di inizio file string sOut = "; --- " + m_sMachsFile + " " + CurrDateTime() + " ---" ; if ( ! TheWriter.OutText( sOut)) { LOG_ERROR( GetEMkLogger(), "SaveMachinings : Error on Start") return false ; } // scrivo l'intestazione if ( ! SaveHeader( TheWriter)) { LOG_ERROR( GetEMkLogger(), "SaveMachinings : Error on Header") return false ; } // ciclo su tutti i nomi delle lavorazioni int nCounter = 0 ; for ( auto iIter = m_suData.cbegin() ; iIter != m_suData.cend() ; ++ iIter) { // salvo l'utensile if ( ! SaveOneMachining( iIter->second, nCounter, TheWriter)) { string sOut = "SaveMachinings : Error on machining " + iIter->first ; LOG_ERROR( GetEMkLogger(), sOut.c_str()) return false ; } } // scrivo linea di fine file if ( ! TheWriter.OutText( "; --- End ---")) { LOG_ERROR( GetEMkLogger(), "SaveMachinings : Error on End") return false ; } // chiudo la scrittura TheWriter.Close() ; // dichiaro non più modificato rispetto al file m_bModified = false ; return true ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SaveHeader( Writer& TheWriter) const { // scrivo l'intestazione bool bOk = true ; string sOut ; sOut = MF_HEADER ; bOk = bOk && TheWriter.OutText( sOut) ; sOut = MF_VERSION + "=" + ToString( MF_CURR_VER) ; bOk = bOk && TheWriter.OutText( sOut) ; sOut = MF_TOTAL + "=" + ToString( int( m_umData.size())) ; bOk = bOk && TheWriter.OutText( sOut) ; return bOk ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SaveOneMachining( const EgtUUID& Uuid, int& nCounter, Writer& TheWriter) const { // recupero i dati della lavorazione auto iIter = m_umData.find( Uuid) ; if ( iIter == m_umData.end()) return false ; const MachiningData* pmData = iIter->second ; // scrivo i dati della lavorazione string sOut = "[" + pmData->GetTitle() + "_" + ToString( ++ nCounter, 3) + "]" ; bool bOk = TheWriter.OutText( sOut) ; sOut = MF_SIZE + "=" + ToString( pmData->GetSize()) ; bOk = bOk && TheWriter.OutText( sOut) ; for ( int i = 0 ; i < pmData->GetSize() ; ++ i) { string sOut = pmData->ToString( i) ; bOk = bOk && ! sOut.empty() && TheWriter.OutText( sOut) ; } return bOk ; } //---------------------------------------------------------------------------- bool MachiningsMgr::GetMachiningNewName( string& sName) const { // il parametro nome deve essere valido if ( &sName == nullptr) return false ; // se nome vuoto, assegno radice standard if ( sName.empty()) sName = "Mach" ; // verifico che il nome sia unico int nCount = 0 ; string sOrigName = sName ; while ( GetMachining( sName) != nullptr) { ++ nCount ; sName = sOrigName + "_" + ToString( nCount) ; } return true ; } //---------------------------------------------------------------------------- bool MachiningsMgr::AddMachining( const string& sName, int nType) { // verifico unicità del nome if ( m_suData.find( sName) != m_suData.end()) return false ; // verifico validità del tipo if ( ! IsValidMachiningType( nType)) return false ; // alloco la lavorazione del tipo corrispondente PtrOwner pMch( MCHDATA_CREATE( nType)) ; if ( IsNull( pMch)) return false ; bool bOk = true ; // assegno nome pMch->m_sName = sName ; CreateEgtUUID( pMch->m_Uuid) ; // salvo i dati della lavorazione bOk = bOk && m_umData.emplace( pMch->m_Uuid, Get( pMch)).second ; bOk = bOk && m_suData.emplace( pMch->m_sName, pMch->m_Uuid).second ; m_bModified = true ; // la rendo la nuova lavorazione corrente if ( m_pCurrMach != nullptr) delete m_pCurrMach ; m_pCurrMach = pMch->Clone() ; Release( pMch) ; return bOk ; } //---------------------------------------------------------------------------- bool MachiningsMgr::CopyMachining( const string& sSource, const string& sName) { // verifico unicità del nome if ( m_suData.find( sName) != m_suData.end()) return false ; // recupero la lavorazione sorgente const MachiningData* pMdata = GetMachining( sSource) ; if ( pMdata == nullptr) return false ; // ne faccio una copia PtrOwner pMch( pMdata->Clone()) ; if ( IsNull( pMch)) return false ; bool bOk = true ; // modifico nome e UUID pMch->m_sName = sName ; CreateEgtUUID( pMch->m_Uuid) ; // salvo i dati della lavorazione bOk = bOk && m_umData.emplace( pMch->m_Uuid, Get( pMch)).second ; bOk = bOk && m_suData.emplace( pMch->m_sName, pMch->m_Uuid).second ; m_bModified = true ; // la rendo la nuova lavorazione corrente if ( m_pCurrMach != nullptr) delete m_pCurrMach ; m_pCurrMach = pMch->Clone() ; Release( pMch) ; return bOk ; } //---------------------------------------------------------------------------- bool MachiningsMgr::RemoveMachining( const string& sName) { // cerco la lavorazione nell'elenco dei nomi e degli UUID auto iNameIter = m_suData.find( sName) ; if ( iNameIter == m_suData.end()) return true ; auto iIter = m_umData.find( iNameIter->second) ; // se era anche la lavorazione corrente, la resetto if ( m_pCurrMach != nullptr && m_pCurrMach->m_Uuid == iNameIter->second) { delete m_pCurrMach ; m_pCurrMach = nullptr ; } if ( iIter != m_umData.end()) { // libero la memoria della lavorazione delete iIter->second ; // rimuovo la lavorazione dal dizionario degli UUID m_umData.erase( iIter) ; } // rimuovo la lavorazione dall'elenco dei nomi m_suData.erase( iNameIter) ; // dichiaro la modifica m_bModified = true ; return true ; } //---------------------------------------------------------------------------- const MachiningData* MachiningsMgr::GetMachining( const EgtUUID& Uuid) const { auto iIter = m_umData.find( Uuid) ; if ( iIter == m_umData.end()) return nullptr ; return iIter->second ; } //---------------------------------------------------------------------------- const MachiningData* MachiningsMgr::GetMachining( const string& sName) const { auto iIter = m_suData.find( sName) ; if ( iIter == m_suData.end()) return nullptr ; return GetMachining( iIter->second) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::GetFirstMachining( int nType, string& sName) const { // recupero primo nome m_suCIter = m_suData.begin() ; // lo verifico if ( VerifyCurrMachining( nType, sName)) return true ; // continuo ricerca return GetNextMachining( nType, sName) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::GetNextMachining( int nType, string& sName) const { // mentre esiste utensile while ( m_suCIter != m_suData.end()) { // nome successivo ++ m_suCIter ; // lo verifico if ( VerifyCurrMachining( nType, sName)) return true ; } // non trovato return false ; } //---------------------------------------------------------------------------- bool MachiningsMgr::VerifyCurrMachining( int nType, string& sName) const { // il corrente deve esistere if ( m_suCIter == m_suData.end()) return false ; // relativa lavorazione auto iIter = m_umData.find( m_suCIter->second) ; if ( iIter == m_umData.end()) { m_suCIter = m_suData.end() ; return false ; } // se è del tipo richiesto, trovato if ( iIter->second->GetType() == nType) { sName = iIter->second->m_sName ; return true ; } return false ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SetCurrMachining( const string& sName) { // se c'è lavorazione corrente, la elimino if ( m_pCurrMach != nullptr) delete m_pCurrMach ; m_pCurrMach = nullptr ; // recupero i dati della lavorazione const MachiningData* pMdata = GetMachining( sName) ; if ( pMdata == nullptr) return false ; // li copio come correnti m_pCurrMach = pMdata->Clone() ; return ( m_pCurrMach != nullptr) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SaveCurrMachining( void) { // verifico validità lavorazione corrente if ( m_pCurrMach == nullptr) return false ; // recupero puntatore a lavorazione corrente nel DB auto iIter = m_umData.find( m_pCurrMach->m_Uuid) ; if ( iIter == m_umData.end()) return false ; // la lavorazione corrente e la sua origine nel DB devono essere dello stesso tipo if ( m_pCurrMach->GetType() != iIter->second->GetType()) return false ; // se cambiato nome, devo aggiornare tabella relativa if ( m_pCurrMach->m_sName != iIter->second->m_sName) { // cerco la lavorazione nell'elenco dei nomi auto iNameIter = m_suData.find( iIter->second->m_sName) ; if ( iNameIter != m_suData.end()) { // rimuovo vecchio nome m_suData.erase( iNameIter) ; // inserisco nuovo m_suData.emplace( m_pCurrMach->m_sName, m_pCurrMach->m_Uuid) ; } } // eseguo salvataggio m_bModified = true ; iIter->second->CopyFrom( m_pCurrMach) ; return true ; } //---------------------------------------------------------------------------- bool MachiningsMgr::IsCurrMachiningModified( void) const { // verifico validità lavorazione corrente if ( m_pCurrMach == nullptr) return false ; // recupero puntatore a lavorazione corrente nel DB auto iIter = m_umData.find( m_pCurrMach->m_Uuid) ; if ( iIter == m_umData.end()) return false ; // eseguo confronto return ( ! SameMachining( m_pCurrMach, iIter->second)) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SetCurrMachiningParam( int nType, bool bVal) { return ( ( m_pCurrMach != nullptr) ? m_pCurrMach->SetParam( nType, bVal) : false) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SetCurrMachiningParam( int nType, int nVal) { return ( ( m_pCurrMach != nullptr) ? m_pCurrMach->SetParam( nType, nVal) : false) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SetCurrMachiningParam( int nType, double dVal) { return ( ( m_pCurrMach != nullptr) ? m_pCurrMach->SetParam( nType, dVal) : false) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::SetCurrMachiningParam( int nType, const std::string& sVal) { // deve esistere lavorazione corrente if ( m_pCurrMach == nullptr) return false ; // non è possibile cambiare UUID e Tool UUID if ( nType == MPA_UUID || nType == MPA_TUUID) return false ; // è possibile cambiare il nome, solo se il nuovo non è già presente nel DB (esclusa lavorazione corrente) if ( nType == MPA_NAME) { const MachiningData* pMch = GetMachining( sVal) ; if ( pMch != nullptr && pMch->m_Uuid != m_pCurrMach->m_Uuid) return false ; } // è possibile cambiare l'utensile, solo se esiste else if ( nType == MPA_TOOL) { const ToolData* pTdata ; if ( ! m_pCurrMach->VerifyTool( m_pTsMgr, sVal, pTdata)) return false ; return ( m_pCurrMach->SetParam( MPA_TOOL, sVal) && m_pCurrMach->SetParam( MPA_TUUID, ::ToString( pTdata->m_Uuid))) ; } // eseguo return m_pCurrMach->SetParam( nType, sVal) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::GetCurrMachiningParam( int nType, bool& bVal) const { return ( ( m_pCurrMach != nullptr) ? m_pCurrMach->GetParam( nType, bVal) : false) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::GetCurrMachiningParam( int nType, int& nVal) const { return ( ( m_pCurrMach != nullptr) ? m_pCurrMach->GetParam( nType, nVal) : false) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::GetCurrMachiningParam( int nType, double& dVal) const { return ( ( m_pCurrMach != nullptr) ? m_pCurrMach->GetParam( nType, dVal) : false) ; } //---------------------------------------------------------------------------- bool MachiningsMgr::GetCurrMachiningParam( int nType, std::string& sVal) const { return ( ( m_pCurrMach != nullptr) ? m_pCurrMach->GetParam( nType, sVal) : false) ; }