Tag: odbmacros_2_5 User: fs Date: 2008-02-14 22:25:03+0000 Added: dba/dbaccess/source/ext/macromigration/migrationprogress.hxx dba/dbaccess/source/ext/macromigration/rangeprogressbar.hxx
Modified: dba/dbaccess/source/ext/macromigration/macromigration.src dba/dbaccess/source/ext/macromigration/macromigrationdialog.cxx dba/dbaccess/source/ext/macromigration/macromigrationdialog.hxx dba/dbaccess/source/ext/macromigration/macromigrationpages.cxx dba/dbaccess/source/ext/macromigration/macromigrationpages.hxx dba/dbaccess/source/ext/macromigration/migrationengine.cxx dba/dbaccess/source/ext/macromigration/migrationengine.hxx Log: #i49133# ingegrate the migration engine (though not yet finished) into the wizard File Changes: Directory: /dba/dbaccess/source/ext/macromigration/ =================================================== File [changed]: macromigration.src Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/macromigration.src?r1=1.1.2.5.2.1&r2=1.1.2.5.2.2 Delta lines: +4 -2 ------------------- --- macromigration.src 2008-02-14 12:16:43+0000 1.1.2.5.2.1 +++ macromigration.src 2008-02-14 22:25:00+0000 1.1.2.5.2.2 @@ -4,9 +4,9 @@ * * $RCSfile: macromigration.src,v $ * - * $Revision: 1.1.2.5.2.1 $ + * $Revision: 1.1.2.5.2.2 $ * - * last change: $Author: fs $ $Date: 2008/02/14 12:16:43 $ + * last change: $Author: fs $ $Date: 2008/02/14 22:25:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -265,6 +265,7 @@ Size = MAP_APPFONT( TAB_PAGE_WIDTH - ( TAB_PAGE_CONTENT_MARGIN + 60 ) - TAB_PAGE_CONTENT_MARGIN, PROGRESS_HEIGHT ); Border = TRUE; + BorderStyle = WINDOW_BORDER_MONO; }; FixedText FT_ALL_PROGRESS_LABEL @@ -294,6 +295,7 @@ Size = MAP_APPFONT( TAB_PAGE_WIDTH - ( TAB_PAGE_CONTENT_MARGIN + 60 ) - TAB_PAGE_CONTENT_MARGIN, PROGRESS_HEIGHT ); Border = TRUE; + BorderStyle = WINDOW_BORDER_MONO; }; FixedText FT_MIGRATION_DONE File [changed]: macromigrationdialog.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/macromigrationdialog.cxx?r1=1.1.2.8.2.1&r2=1.1.2.8.2.2 Delta lines: +34 -3 -------------------- --- macromigrationdialog.cxx 2008-02-14 12:16:43+0000 1.1.2.8.2.1 +++ macromigrationdialog.cxx 2008-02-14 22:25:00+0000 1.1.2.8.2.2 @@ -4,9 +4,9 @@ * * $RCSfile: macromigrationdialog.cxx,v $ * - * $Revision: 1.1.2.8.2.1 $ + * $Revision: 1.1.2.8.2.2 $ * - * last change: $Author: fs $ $Date: 2008/02/14 12:16:43 $ + * last change: $Author: fs $ $Date: 2008/02/14 22:25:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -42,6 +42,7 @@ #include "macromigration.hrc" #include "macromigrationdialog.hxx" #include "macromigrationpages.hxx" +#include "migrationengine.hxx" /** === begin UNO includes === **/ #include <com/sun/star/sdb/application/XDatabaseDocumentUI.hpp> @@ -137,16 +138,35 @@ enableState( STATE_MIGRATE, false ); enableState( STATE_SUMMARY, false ); break; + case STATE_BACKUP_DBDOC: enableState( STATE_MIGRATE, true ); // Note that the state is automatically disabled if the current page // (SaveDBDocPage) returns false in its canAdvance, not caring that // we enabled it here. break; + case STATE_MIGRATE: + { + // disable everything. The process we will start here cannot be cancelled, the user + // needs to wait 'til it's finished. + enableState( STATE_CLOSE_SUB_DOCS, false ); + enableState( STATE_BACKUP_DBDOC, false ); + enableState( STATE_SUMMARY, false ); + + enableButtons( WZB_FINISH | WZB_CANCEL | WZB_PREVIOUS | WZB_NEXT, false ); + + bool bSuccess = impl_autoStartMigration(); + + enableButtons( ( bSuccess ? WZB_FINISH | WZB_NEXT : 0 ), true ); + enableState( STATE_SUMMARY, bSuccess ); + updateTravelUI(); + } break; + case STATE_SUMMARY: break; + default: OSL_ENSURE( false, "MacroMigrationDialog::enterState: unhandled state!" ); } @@ -198,6 +218,17 @@ } //-------------------------------------------------------------------- + bool MacroMigrationDialog::impl_autoStartMigration() const + { + ProgressPage& rProgressPage( dynamic_cast< ProgressPage& >( *GetPage( STATE_MIGRATE ) ) ); + MigrationEngine aEngine( m_aContext, m_xDocument, rProgressPage ); + + rProgressPage.setDocumentCounts( aEngine.getFormCount(), aEngine.getReportCount() ); + + return aEngine.migrateAll(); + } + + //-------------------------------------------------------------------- void MacroMigrationDialog::impl_showCloseDocsError( bool _bShow ) { PreparationPage* pPreparationPage = dynamic_cast< PreparationPage* >( GetPage( STATE_CLOSE_SUB_DOCS ) ); File [changed]: macromigrationdialog.hxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/macromigrationdialog.hxx?r1=1.1.2.4&r2=1.1.2.4.2.1 Delta lines: +3 -2 ------------------- --- macromigrationdialog.hxx 2008-02-05 09:12:46+0000 1.1.2.4 +++ macromigrationdialog.hxx 2008-02-14 22:25:00+0000 1.1.2.4.2.1 @@ -4,9 +4,9 @@ * * $RCSfile: macromigrationdialog.hxx,v $ * - * $Revision: 1.1.2.4 $ + * $Revision: 1.1.2.4.2.1 $ * - * last change: $Author: fs $ $Date: 2008/02/05 09:12:46 $ + * last change: $Author: fs $ $Date: 2008/02/14 22:25:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -79,6 +79,7 @@ void impl_showCloseDocsError( bool _bShow ); bool impl_closeSubDocs_nothrow(); bool impl_backupDocument_nothrow() const; + bool impl_autoStartMigration() const; private: ::comphelper::ComponentContext m_aContext; File [changed]: macromigrationpages.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/macromigrationpages.cxx?r1=1.1.2.8.2.1&r2=1.1.2.8.2.2 Delta lines: +58 -5 -------------------- --- macromigrationpages.cxx 2008-02-14 12:16:43+0000 1.1.2.8.2.1 +++ macromigrationpages.cxx 2008-02-14 22:25:00+0000 1.1.2.8.2.2 @@ -4,9 +4,9 @@ * * $RCSfile: macromigrationpages.cxx,v $ * - * $Revision: 1.1.2.8.2.1 $ + * $Revision: 1.1.2.8.2.2 $ * - * last change: $Author: fs $ $Date: 2008/02/14 12:16:43 $ + * last change: $Author: fs $ $Date: 2008/02/14 22:25:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -225,15 +225,14 @@ ,m_aCurrentAction ( this, MacroMigrationResId( FT_CURRENT_PROGRESS ) ) ,m_aCurrentProgress ( this, MacroMigrationResId( WND_CURRENT_PROGRESS ) ) ,m_aAllProgressLabel ( this, MacroMigrationResId( FT_ALL_PROGRESS_LABEL ) ) - ,m_aObjectCountProgress ( this, MacroMigrationResId( FT_OBJECT_COUNT_PROGRESS ) ) + ,m_aAllProgressText ( this, MacroMigrationResId( FT_OBJECT_COUNT_PROGRESS ) ) ,m_aAllProgress ( this, MacroMigrationResId( WND_ALL_PROGRESS ) ) ,m_aMigrationDone ( this, MacroMigrationResId( FT_MIGRATION_DONE ) ) { FreeResource(); // TODO: remove when this prototype becomes real - m_aCurrentProgress.SetValue( 30 ); - m_aAllProgress.SetValue( 65 ); + m_aAllProgress.SetValue( (sal_uInt32)65 ); } //-------------------------------------------------------------------- @@ -242,6 +241,60 @@ return new ProgressPage( dynamic_cast< MacroMigrationDialog& >( _rParentDialog ) ); } + //-------------------------------------------------------------------- + void ProgressPage::setDocumentCounts( const sal_Int32 _nForms, const sal_Int32 _nReports ) + { + String sText( m_aObjectCount.GetText() ); + sText.SearchAndReplaceAscii( "$forms$", String::CreateFromInt32( _nForms ) ); + sText.SearchAndReplaceAscii( "$reports$", String::CreateFromInt32( _nReports ) ); + m_aObjectCount.SetText( sText ); + } + + //-------------------------------------------------------------------- + void ProgressPage::startObject( const ::rtl::OUString& _rObjectName, const ::rtl::OUString& _rCurrentAction, const sal_uInt32 _nRange ) + { + m_aCurrentObject.SetText( _rObjectName ); + m_aCurrentAction.SetText( _rCurrentAction ); + m_aCurrentProgress.SetRange( _nRange ); + m_aCurrentProgress.SetValue( (sal_uInt32)0 ); + } + + //-------------------------------------------------------------------- + void ProgressPage::setObjectProgressText( const ::rtl::OUString& _rText ) + { + m_aCurrentAction.SetText( _rText ); + } + + //-------------------------------------------------------------------- + void ProgressPage::setObjectProgressValue( const sal_uInt32 _nValue ) + { + m_aCurrentProgress.SetValue( _nValue ); + } + + //-------------------------------------------------------------------- + void ProgressPage::endObject() + { + m_aCurrentProgress.SetValue( m_aCurrentProgress.GetRange() ); + } + + //-------------------------------------------------------------------- + void ProgressPage::start( const sal_uInt32 _nOverallRange ) + { + m_aAllProgress.SetRange( _nOverallRange ); + } + + //-------------------------------------------------------------------- + void ProgressPage::setOverallProgressText( const ::rtl::OUString& _rText ) + { + m_aAllProgressText.SetText( _rText ); + } + + //-------------------------------------------------------------------- + void ProgressPage::setOverallProgressValue( const sal_uInt32 _nValue ) + { + m_aAllProgress.SetValue( _nValue ); + } + //==================================================================== //= ResultPage //==================================================================== File [changed]: macromigrationpages.hxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/macromigrationpages.hxx?r1=1.1.2.6.2.1&r2=1.1.2.6.2.2 Delta lines: +28 -14 --------------------- --- macromigrationpages.hxx 2008-02-14 12:16:43+0000 1.1.2.6.2.1 +++ macromigrationpages.hxx 2008-02-14 22:25:00+0000 1.1.2.6.2.2 @@ -4,9 +4,9 @@ * * $RCSfile: macromigrationpages.hxx,v $ * - * $Revision: 1.1.2.6.2.1 $ + * $Revision: 1.1.2.6.2.2 $ * - * last change: $Author: fs $ $Date: 2008/02/14 12:16:43 $ + * last change: $Author: fs $ $Date: 2008/02/14 22:25:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -36,7 +36,9 @@ #ifndef DBACCESS_MACROMIGRATIONPAGES_HXX #define DBACCESS_MACROMIGRATIONPAGES_HXX -#include <svtools/prgsbar.hxx> +#include "migrationprogress.hxx" +#include "rangeprogressbar.hxx" + #include <svtools/svmedit.hxx> #include <svtools/urlcontrol.hxx> #include <svtools/wizardmachine.hxx> @@ -128,23 +130,35 @@ //==================================================================== //= ProgressPage //==================================================================== - class ProgressPage : public MacroMigrationPage + class ProgressPage : public MacroMigrationPage, public IMigrationProgress { public: ProgressPage( MacroMigrationDialog& _rParentDialog ); static TabPage* Create( ::svt::RoadmapWizard& _rParentDialog ); + void setDocumentCounts( const sal_Int32 _nForms, const sal_Int32 _nReports ); + + protected: + // IMigrationProgress + virtual void startObject( const ::rtl::OUString& _rObjectName, const ::rtl::OUString& _rCurrentAction, const sal_uInt32 _bRange ); + virtual void setObjectProgressText( const ::rtl::OUString& _rText ); + virtual void setObjectProgressValue( const sal_uInt32 _nValue ); + virtual void endObject(); + virtual void start( const sal_uInt32 _nOverallRange ); + virtual void setOverallProgressText( const ::rtl::OUString& _rText ); + virtual void setOverallProgressValue( const sal_uInt32 _nValue ); + private: FixedText m_aObjectCount; FixedText m_aCurrentObjectLabel; FixedText m_aCurrentObject; FixedText m_aCurrentActionLabel; FixedText m_aCurrentAction; - ProgressBar m_aCurrentProgress; + RangeProgressBar m_aCurrentProgress; FixedText m_aAllProgressLabel; - FixedText m_aObjectCountProgress; - ProgressBar m_aAllProgress; + FixedText m_aAllProgressText; + RangeProgressBar m_aAllProgress; FixedText m_aMigrationDone; }; File [changed]: migrationengine.cxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/migrationengine.cxx?r1=1.1.2.1&r2=1.1.2.2 Delta lines: +107 -14 ---------------------- --- migrationengine.cxx 2008-02-14 12:16:19+0000 1.1.2.1 +++ migrationengine.cxx 2008-02-14 22:25:00+0000 1.1.2.2 @@ -4,9 +4,9 @@ * * $RCSfile: migrationengine.cxx,v $ * - * $Revision: 1.1.2.1 $ + * $Revision: 1.1.2.2 $ * - * last change: $Author: fs $ $Date: 2008/02/14 12:16:19 $ + * last change: $Author: fs $ $Date: 2008/02/14 22:25:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -40,12 +40,17 @@ #include "dbmm_module.hxx" #include "docerrorhandling.hxx" #include "migrationengine.hxx" +#include "migrationprogress.hxx" /** === begin UNO includes === **/ +#include <com/sun/star/sdb/XFormDocumentsSupplier.hpp> +#include <com/sun/star/sdb/XReportDocumentsSupplier.hpp> /** === end UNO includes === **/ #include <comphelper/string.hxx> #include <tools/string.hxx> +#include <tools/diagnose_ex.h> +#include <rtl/ustrbuf.hxx> #include <vector> @@ -67,6 +72,10 @@ using ::com::sun::star::uno::Any; using ::com::sun::star::uno::makeAny; using ::com::sun::star::sdb::XOfficeDatabaseDocument; + using ::com::sun::star::sdb::XFormDocumentsSupplier; + using ::com::sun::star::sdb::XReportDocumentsSupplier; + using ::com::sun::star::container::XNameAccess; + using ::com::sun::star::uno::Sequence; /** === end UNO using === **/ //==================================================================== @@ -83,6 +92,12 @@ { SubDocumentType eType; ::rtl::OUString sHierarchicalName; + + SubDocument( const SubDocumentType _eType, const ::rtl::OUString& _rName ) + :eType( _eType ) + ,sHierarchicalName( _rName ) + { + } }; typedef ::std::vector< SubDocument > SubDocuments; @@ -100,17 +115,25 @@ ); ~MigrationEngine_Impl(); + inline sal_Int32 getFormCount() const { return m_nFormCount; } + inline sal_Int32 getReportCount()const { return m_nReportCount; } bool migrateAll(); private: ::comphelper::ComponentContext m_aContext; const Reference< XOfficeDatabaseDocument > m_xDocument; IMigrationProgress& m_rProgress; + SubDocuments m_aSubDocs; + size_t m_nFormCount; + size_t m_nReportCount; private: /** collects a description of all sub documents of our database document + + @return + <TRUE/> if and only if collecting the documents was successful */ - void impl_collectSubDocuments_nothrow( SubDocuments& _out_rDocs ) const; + bool impl_collectSubDocuments_nothrow(); /** reports the given error (usually an exception caught on the caller's side) to the user, using the document's interaction handler, if any. @@ -131,7 +154,11 @@ :m_aContext( _rContext ) ,m_xDocument( _rxDocument ) ,m_rProgress( _rProgress ) + ,m_aSubDocs() + ,m_nFormCount( 0 ) + ,m_nReportCount( 0 ) { + OSL_VERIFY( impl_collectSubDocuments_nothrow() ); } //-------------------------------------------------------------------- @@ -142,28 +169,27 @@ //-------------------------------------------------------------------- bool MigrationEngine_Impl::migrateAll() { - SubDocuments aDocuments; - impl_collectSubDocuments_nothrow( aDocuments ); - if ( aDocuments.empty() ) + if ( m_aSubDocs.empty() ) { OSL_ENSURE( false, "MigrationEngine_Impl::migrateAll: no forms/reports found!" ); // The whole migration wizard is not expected to be called when there are no forms/reports // with macros, not to mention when there are no forms/reports at all. + return false; } // initialize global progress - sal_Int32 nOverallRange( aDocuments.size() ); + sal_Int32 nOverallRange( m_aSubDocs.size() ); String sProgressSkeleton = String( MacroMigrationResId( STR_OVERALL_PROGRESS ) ); sProgressSkeleton.SearchAndReplaceAscii( "$overall$", String::CreateFromInt32( nOverallRange ) ); m_rProgress.start( nOverallRange ); - for ( SubDocuments::const_iterator doc = aDocuments.begin(); - doc != aDocuments.end(); + for ( SubDocuments::const_iterator doc = m_aSubDocs.begin(); + doc != m_aSubDocs.end(); ++doc ) { - sal_Int32 nOverallProgressValue( doc - aDocuments.begin() ); + sal_Int32 nOverallProgressValue( doc - m_aSubDocs.begin() + 1 ); // update overall progress text ::rtl::OUString sOverallProgress( sProgressSkeleton ); ::comphelper::string::searchAndReplaceAsciiI( sOverallProgress, "$current$", ::rtl::OUString::valueOf( nOverallProgressValue ) ); @@ -181,10 +207,65 @@ } //-------------------------------------------------------------------- - void MigrationEngine_Impl::impl_collectSubDocuments_nothrow( SubDocuments& _out_rDocs ) const + namespace { - // TODO - (void)_out_rDocs; + size_t lcl_collectHierarchicalElementNames_throw( + const Reference< XNameAccess >& _rxContainer, const ::rtl::OUString& _rContainerLoc, + SubDocuments& _out_rDocs, const SubDocumentType _eType ) + { + size_t nAddedElements = 0; + + const ::rtl::OUString sHierarhicalBase( + _rContainerLoc.getLength() ? ::rtl::OUStringBuffer( _rContainerLoc ).appendAscii( "/" ).makeStringAndClear() + : ::rtl::OUString() ); + + Sequence< ::rtl::OUString > aElementNames( _rxContainer->getElementNames() ); + for ( const ::rtl::OUString* elementName = aElementNames.getConstArray(); + elementName != aElementNames.getConstArray() + aElementNames.getLength(); + ++elementName + ) + { + Any aElement( _rxContainer->getByName( *elementName ) ); + ::rtl::OUString sElementName( ::rtl::OUStringBuffer( sHierarhicalBase ).append( *elementName ) ); + + Reference< XNameAccess > xSubContainer( aElement, UNO_QUERY ); + if ( xSubContainer.is() ) + { + nAddedElements += lcl_collectHierarchicalElementNames_throw( xSubContainer, sElementName, _out_rDocs, _eType ); + } + else + { + _out_rDocs.push_back( SubDocument( _eType, sElementName ) ); + ++nAddedElements; + } + } + return nAddedElements; + } + } + + //-------------------------------------------------------------------- + bool MigrationEngine_Impl::impl_collectSubDocuments_nothrow() + { + try + { + ::rtl::OUString sRootLocation; + + Reference< XFormDocumentsSupplier > xSuppForms( m_xDocument, UNO_QUERY_THROW ); + Reference< XNameAccess > xDocContainer( xSuppForms->getFormDocuments(), UNO_SET_THROW ); + m_nFormCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, sRootLocation, m_aSubDocs, eForm ); + + Reference< XReportDocumentsSupplier > xSuppReports( m_xDocument, UNO_QUERY_THROW ); + xDocContainer.set( xSuppReports->getReportDocuments(), UNO_SET_THROW ); + m_nReportCount = lcl_collectHierarchicalElementNames_throw( xDocContainer, sRootLocation, m_aSubDocs, eReport ); + } + catch( const Exception& ) + { + // TODO: check whether we can handle this error + DBG_UNHANDLED_EXCEPTION(); + return false; + } + + return true; } //-------------------------------------------------------------------- @@ -225,6 +306,18 @@ } //-------------------------------------------------------------------- + sal_Int32 MigrationEngine::getFormCount() const + { + return m_pImpl->getFormCount(); + } + + //-------------------------------------------------------------------- + sal_Int32 MigrationEngine::getReportCount() const + { + return m_pImpl->getReportCount(); + } + + //-------------------------------------------------------------------- bool MigrationEngine::migrateAll() { return m_pImpl->migrateAll(); File [changed]: migrationengine.hxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/migrationengine.hxx?r1=1.1.2.1&r2=1.1.2.2 Delta lines: +9 -19 -------------------- --- migrationengine.hxx 2008-02-14 12:16:19+0000 1.1.2.1 +++ migrationengine.hxx 2008-02-14 22:25:00+0000 1.1.2.2 @@ -4,9 +4,9 @@ * * $RCSfile: migrationengine.hxx,v $ * - * $Revision: 1.1.2.1 $ + * $Revision: 1.1.2.2 $ * - * last change: $Author: fs $ $Date: 2008/02/14 12:16:19 $ + * last change: $Author: fs $ $Date: 2008/02/14 22:25:00 $ * * The Contents of this file are made available subject to * the terms of GNU Lesser General Public License Version 2.1. @@ -53,25 +53,12 @@ { //........................................................................ - //==================================================================== - //= MigrationProgress - //==================================================================== - class SAL_NO_VTABLE IMigrationProgress - { - public: - virtual void startObject( const ::rtl::OUString& _rObjectName, const ::rtl::OUString& _rCurrentAction, const sal_Int32 _bRange ) = 0; - virtual void setObjectProgressText( const ::rtl::OUString& _rText ) = 0; - virtual void setObjectProgressValue( const sal_Int32 _nValue ) = 0; - virtual void endObject() = 0; - virtual void start( const sal_Int32 _nOverallRange ); - virtual void setOverallProgressText( const ::rtl::OUString& _rText ) = 0; - virtual void setOverallProgressValue( const sal_Int32 _nValue ) = 0; - }; + class IMigrationProgress; - class MigrationEngine_Impl; //==================================================================== //= MigrationEngine //==================================================================== + class MigrationEngine_Impl; class MigrationEngine { public: @@ -90,6 +77,9 @@ ~MigrationEngine(); + sal_Int32 getFormCount() const; + sal_Int32 getReportCount() const; + /** starts migrating the scripts and macros in the forms/reports to the database document. File [added]: migrationprogress.hxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/migrationprogress.hxx?rev=1.1.2.1&content-type=text/vnd.viewcvs-markup Added lines: 0 -------------- File [added]: rangeprogressbar.hxx Url: http://dba.openoffice.org/source/browse/dba/dbaccess/source/ext/macromigration/rangeprogressbar.hxx?rev=1.1.2.1&content-type=text/vnd.viewcvs-markup Added lines: 0 -------------- --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
