// #############################################################################################
    // static entrance (Main)
    // #############################################################################################
//! [DOXYGEN_CREATE_INIFILE]
    static void Main( string[] args )
    {
        // first attach INI file to config system...
        IniFile iniFile= new IniFile();
        ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );

        // .. then initialize ALox Logging Library
        ALox.Init( args );

        //...
//! [DOXYGEN_CREATE_INIFILE]

        if ( iniFile.FileComments.IsEmpty() )
        {
            iniFile.FileComments._(
            "##################################################################################################\n" +
            "# ALox Samples INI file (created when running ALox Samples)\n"                                        +
            "#\n"                                                                                                  +
            "# (c) 2013-2016 A-Worx GmbH, Germany\n"                                                               +
            "# Published under MIT License (Open Source License, see LICENSE.txt)\n"                               +
            "##################################################################################################\n"
            );
        }

        // Suppress setting "writeback" as default verbosities. We need to do this as this main()
        // method invokes a list of independent samples. Those would now read from the INI file wrong
        // values written in other sample methods and thus the samples would not work any more
        // (because INI file settings overrules settings in the code)
        Variable var= new Variable();
        var.Define( "ALOX", "LOG_DEBUG_LOGGER_VERBOSITY"  ).Store( "" );
        var.Define( "ALOX", "RELEASELOX_CONSOLE_VERBOSITY").Store( "" );
        var.Define( "ALOX", "LOG_MEMORY_VERBOSITY"        ).Store( "" );
        var.Define( "ALOX", "RELEASELOX_MEMORY_VERBOSITY" ).Store( "" );
        var.Define( "ALOX", "LOG_TEXTFILE_VERBOSITY"      ).Store( "" );

        // do some release logging tests.
        Console.WriteLine( "PRINT: Debug logging:" );
            AloxSamples.DebugLogging();
        ALoxSampleReset();

        // do some release logging tests.
        Console.WriteLine( "PRINT: Release logging:" );
            AloxSamples.ReleaseLogging();
        ALoxSampleReset();

        // do some performance tests.
        Console.WriteLine( "PRINT: Performance test (debug logging):" );
           AloxSamples.PerformanceTest();
        ALoxSampleReset();

        // do some performance tests.
        Console.WriteLine( "PRINT: Performance test (release logging):" );
           AloxSamples.PerformanceTestRL();
        ALoxSampleReset();

        // test class TextFileLogger
        Console.WriteLine( "PRINT: test class TextFileLogger:" );
            AloxSamples.TextFileLogger();
        ALoxSampleReset();

        // test class terminal test (colors and styles)
        Console.WriteLine( "PRINT: Colors (depending on detected terminal):" );
            AloxSamples.ColorTest();
        ALoxSampleReset();

        Console.WriteLine( "PRINT: Thats it!" );

        // sample ALib report facility through ALox
        AloxSamples.SampleALibReport();

//! [DOXYGEN_REMOVE_INIFILE]
        //...
        ALIB.Config.RemovePlugin( iniFile );
        ALIB.Config.FetchFromDefault( iniFile );
        iniFile.WriteFile();

        ALIB.TerminationCleanUp();
    }
 /** ********************************************************************************************
 * Log_TextLogger_FormatConfig
 **********************************************************************************************/
 void testFormatConfig( String testFormat,
                        String expFmt,
                        String expFmtError    = null,
                        String expFmtWarning  = null,
                        String expFmtInfo     = null,
                        String expFmtVerbose  = null
                      )
 {
     Variable var= new Variable();
     var.Define(ALox.ConfigCategoryName, "TESTML_FORMAT", ',').Store( testFormat  );
 
     Lox lox= new Lox("TEST");   
     MemoryLogger ml= new MemoryLogger("TESTML");
     lox.SetVerbosity( ml, Verbosity.Info );
     lox.RemoveLogger( ml );
     ALox.Register( lox, ContainerOp.Remove );
 
                                  UT_EQ( expFmt       , ml.MetaInfo.Format );
     if( expFmtError  != null ) { UT_EQ( expFmtError  , ml.MetaInfo.VerbosityError   ); }
     if( expFmtWarning!= null ) { UT_EQ( expFmtWarning, ml.MetaInfo.VerbosityWarning ); }
     if( expFmtInfo   != null ) { UT_EQ( expFmtInfo   , ml.MetaInfo.VerbosityInfo    ); }
     if( expFmtVerbose!= null ) { UT_EQ( expFmtVerbose, ml.MetaInfo.VerbosityVerbose ); }
 }
    // #############################################################################################
    // public interface
    // #############################################################################################

        /** ****************************************************************************************
         * Constructs a scope info.
         * @param name              The name of the Lox we belong to.
         *                          Will be converted to upper case.
         * @param threadDictionary  A dictionary to map thread IDs to user friendly names which is
         *                          managed outside of this class.
         ******************************************************************************************/
        public ScopeInfo( String name,  Dictionary<int, String> threadDictionary )
        {
            loxName= name.ToUpper();
            ALIB.ASSERT_ERROR( !loxName.Equals( "GLOBAL" ), "Name \"GLOBAL\" not allowed for Lox instances" );

            this.threadDictionary= threadDictionary;

            cache=  new SourceFile[cacheSize= DefaultCacheSize];
            for ( int i= 0; i< cacheSize; i++ )
                cache[i]= new SourceFile();
            actual= cache[0];

            // read trim rules from config
            // do 2 times, 0== local list, 1== global list
            List<SourcePathTrimRule> trimInfoList;
            for( int trimInfoNo= 0; trimInfoNo < 2 ; trimInfoNo++ )
            {
                // check if done... or set list
                Variable variable= new Variable();
                if ( trimInfoNo == 0 )
                {
                    trimInfoList= LocalSPTRs;
                    variable.Define(ALox.SPTR_LOX, loxName).Load();
                }
                else
                {
                    if ( GlobalSPTRsReadFromConfig )
                        continue;
                    GlobalSPTRsReadFromConfig= true;
                    trimInfoList= GlobalSPTRs;
                    variable.Define(ALox.SPTR_GLOBAL).Load();
                }

                if( variable.Priority != 0 )
                {
                    Tokenizer ruleTok = new Tokenizer();
                    for( int ruleNo= 0; ruleNo< variable.Size(); ruleNo++ )
                    {
                        try {
                            ruleTok.Set( variable.GetString( ruleNo ), ',' );
                            SourcePathTrimRule rule= new SourcePathTrimRule();
                            rule.Priority= variable.Priority;
                            rule.Path= new AString();
                            ruleTok.Next();
                            if( ! ( rule.IsPrefix= !ruleTok.Actual.StartsWith( "*" ) ) )
                                ruleTok.Actual.Consume(1);
                            rule.Path._( ruleTok.Actual );
                            if ( rule.Path.CharAtEnd() == '*' )
                                rule.Path.DeleteEnd( 1 );
                            if ( rule.Path.IsEmpty() )
                                continue;

                            if( Path.DirectorySeparatorChar == '/' )
                                rule.Path.SearchAndReplaceAll( "\\", "/"  );
                            else
                                rule.Path.SearchAndReplaceAll( "/" , "\\" );


                            rule.IncludeString = ALIB.ReadInclusion( ruleTok.Next() );

                            if ( ruleTok.HasNext () )
                                ruleTok.Next().ConsumeInteger( out rule.TrimOffset );

                            rule.Sensitivity = ALIB.ReadCase( ruleTok.Next() );

                            if ( ruleTok.HasNext () )
                                rule.TrimReplacement= ruleTok.Next().ToString();

                            trimInfoList.Add( rule );
                        }
                        catch( Exception )
                        {
                            ALIB.ERROR( "Error reading source path trim rule from configuration. Invalid String: "
                                        + variable.GetString( ruleNo ).ToString() );
                        }
                    }
                }
            }
        }
        /** ****************************************************************************************
         * Invokes grand-parent's method and in addition, de-registers with
         * \ref cs::aworx::lib::ALIB::StdOutputStreamsLock "ALIB.StdOutputStreamsLock"
         * @param acquirer The acquirer to remove.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public override int   RemoveAcquirer( ThreadLock acquirer )
        {
            // d-register with ALIB lockers (if not done yet)
            if ( usesStdStreams )
            {
                ALIB.Lock.Acquire();
                    int  stdStreamLockRegistrationCounter= --this.stdStreamLockRegistrationCounter;
                ALIB.Lock.Release();

                if ( stdStreamLockRegistrationCounter == 0 )
                    ALIB.StdOutputStreamsLock.RemoveAcquirer( this );
            }

            Variable variable= new Variable();

            // export autosizes to configuration
            variable.Define( ALox.AUTO_SIZES, GetName() );
            AutoSizes.Export( variable.AddString() );
            variable.Store();

            // export "max elapsed time" to configuration
            variable.Define( ALox.MAX_ELAPSED_TIME, GetName() );
            AString destVal=  variable.Load() != 0  ?  variable.GetString()
                                                    :  variable.AddString();
            destVal._()._( MetaInfo.MaxElapsedTime.InSeconds() );
            variable.Store();

            // call parents' implementation
            return base.RemoveAcquirer( acquirer );
        }
        public int FetchFromDefault( ConfigurationPlugin dest)
        {
            int cntCopied= 0;
            Variable variable= new Variable();
            for( int sNo= 0; sNo < DefaultValues.Sections.Count ; sNo++ )
            {
                InMemoryPlugin.Section section= DefaultValues.Sections[sNo];
                for( int vNo= 0; vNo < section.Entries.Count ; vNo++ )
                {
                    InMemoryPlugin.Entry entry= section.Entries[vNo];
                    if( !dest.Load( variable.Define(section.Name, entry.Name ), true ) )
                    {
                        DefaultValues.Load  ( variable );
                        dest.Store( variable );
                        cntCopied++;
                    }
                }
            }

            return  cntCopied;
        }
    public void Log_Domain_IniFile()
    {
        UT_INIT();

        // Without priorities
        {
            // create iniFile
            IniFile iniFile= new IniFile("*"); // don't read
            Variable var= new Variable();
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT"),  "%Sp" );
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "T_LOX_TESTML_VERBOSITY",';'),
                             "/DOM_VERB  = VerboseXX  ;" // xx is allowed!
                          +  "/DOM_INFO  = Info       ;"
                          +  "/DOM_WARN  = WARNING    ;"
                          +  "/DOM_ERR   = erRor      ;"
                          +  "/DOM_OFF   = off        ;"
                          +  "/DOM_OFF2  = xxx        ;"
                          +  "/ATSTART*  = Info       ;"
                          +  "*ATEND     = Info       ;"
                          +  "*SUBSTR*   = Info       ;"
                          +  "/OVERWRITE = Info       ;"
                        );
            ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );


            // test
            Lox lox= new Lox("T_LOX", false);

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            // pre-create one of the domains to test if loggers added later get config for existing domains
            lox.Verbose( "DOM_INFO"     , "test" );

            MemoryLogger ml= new MemoryLogger("TESTML");
            lox.SetVerbosity( ml, Verbosity.Off );
            lox.Info   (                  "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "NOSETTING"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "DOM_VERB"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "DOM_INFO"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "DOM_INFO"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Info   ( "DOM_WARN"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Warning( "DOM_WARN"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Warning( "DOM_ERR"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "DOM_ERR"      , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.Error  ( "DOM_OFF"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "DOM_OFF2"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "ATSTART"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATSTART"      , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "ATSTARTXX"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATSTARTXX"    , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XXATSTART"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XXATSTART"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XATSTARTX"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XATSTARTX"    , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "ATEND"        , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATEND"        , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "ATENDXX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "ATENDXX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XXATEND"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XXATEND"      , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XATENDX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XATENDX"      , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.Verbose( "SUBSTR"       , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "SUBSTR"       , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "SUBSTRXX"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "SUBSTRXX"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XXSUBSTR"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XXSUBSTR"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "XSUBSTRX"     , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "XSUBSTRX"     , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            // overwrite config
            lox.Verbose( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/OVERWRITE"   , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Warning, "/OVERWRITE" ); // does not overwrite
            lox.Verbose( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/OVERWRITE"   , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Warning, "/OVERWRITE", 1000 ); // does overwrite
            lox.Verbose( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/OVERWRITE"   , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Warning( "/OVERWRITE"   , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            // overwrite non-config
            lox.Error  ( "/A"           , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Error  ( "/A/C"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Info, "/A/B", Configuration.PrioDefault -1 ); // does not overwrite
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Info, "/A/B", Configuration.PrioDefault ); // does overwrite
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Info, "/A/B", Configuration.PrioDefault + 1 ); // one higher
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            lox.SetVerbosity( ml , Verbosity.Verbose, "/A" );
            lox.Verbose( "/A"           , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "/A/B"         , "test" );    UT_EQ(  0, ml.CntLogs ); ml.CntLogs= 0;
            lox.Info   ( "/A/B"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;
            lox.Verbose( "/A/C"         , "test" );    UT_EQ(  1, ml.CntLogs ); ml.CntLogs= 0;

            //lox.State( "", Verbosity.Info, "Configuration now is:" ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            ALIB.Config.RemovePlugin( iniFile );
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }


    }
    // #############################################################################################
    // Reimplementing interface of grand-parent class SmartLock
    // #############################################################################################

        /** ****************************************************************************************
         * Invokes grand-parent's method and in addition, if field #usesStdStreams is set,
         * registers with
         * \ref cs::aworx::lib::ALIB::StdOutputStreamsLock "ALIB.StdOutputStreamsLock", respectively
         *
         * @param newAcquirer The acquirer to add.
         * @return The new number of \e acquirers set.
         ******************************************************************************************/
        public override int   AddAcquirer( ThreadLock newAcquirer )
        {
            // register with ALIB lockers (if not done yet)
            if ( usesStdStreams )
            {
                ALIB.Lock.Acquire();
                    int  stdStreamLockRegistrationCounter= this.stdStreamLockRegistrationCounter++;
                ALIB.Lock.Release();
                if ( stdStreamLockRegistrationCounter == 0 )
                    ALIB.StdOutputStreamsLock.AddAcquirer( this );
            }

            Variable variable= new Variable();

            // import autosizes from configuration (last session)
            if ( variable.Define( ALox.AUTO_SIZES, GetName()).Load() != 0 )
                AutoSizes.Import( variable.GetString() );

            // import "max elapsed time" from configuration (last session)
            if ( variable.Define( ALox.MAX_ELAPSED_TIME, GetName()).Load()  != 0 )
            {
                long maxInSecs= variable.GetInteger();
                Substring attrValue= new Substring();
                if ( variable.GetAttribute( "limit", attrValue ) )
                {
                    long maxMax;
                    attrValue.ConsumeLong( out maxMax );
                    if ( maxInSecs > maxMax )
                        maxInSecs= maxMax;
                }
                MetaInfo.MaxElapsedTime.FromSeconds( maxInSecs );
            }

            // Variable  <name>_FORMAT / <typeName>_FORMAT:
            ALIB.ASSERT_WARNING( ALox.FORMAT.DefaultValue == null,
                                 "Default value of variable FORMAT should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT, GetName() );
                variable.AddString( MetaInfo.Format            );
                variable.AddString( MetaInfo.VerbosityError    );
                variable.AddString( MetaInfo.VerbosityWarning  );
                variable.AddString( MetaInfo.VerbosityInfo     );
                variable.AddString( MetaInfo.VerbosityVerbose  );
                variable.Store();
            }
            else
            {
                                           MetaInfo.Format          ._()._( variable.GetString(0) );
                if( variable.Size() >= 2 ) MetaInfo.VerbosityError  = variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) MetaInfo.VerbosityWarning= variable.GetString(2).ToString();
                if( variable.Size() >= 4 ) MetaInfo.VerbosityInfo   = variable.GetString(3).ToString();
                if( variable.Size() >= 5 ) MetaInfo.VerbosityVerbose= variable.GetString(4).ToString();
            }
        
            // Variable  <name>_FORMAT_DATE_TIME / <typeName>_FORMAT_DATE_TIME:
            ALIB.ASSERT_WARNING( ALox.FORMAT_DATE_TIME.DefaultValue == null,
                                 "Default value of variable FORMAT_DATE_TIME should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT_DATE_TIME, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT_DATE_TIME, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT_DATE_TIME, GetName() );
                variable.AddString( MetaInfo.DateFormat        );
                variable.AddString( MetaInfo.TimeOfDayFormat   );
                variable.AddString( MetaInfo.TimeElapsedDays   );
                variable.Store();
            }
            else
            {
                                           MetaInfo.DateFormat      = variable.GetString(0).ToString();
                if( variable.Size() >= 2 ) MetaInfo.TimeOfDayFormat = variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) MetaInfo.TimeElapsedDays = variable.GetString(2).ToString();
            }
        
            // Variable  <name>FORMAT_TIME_DIFF / <typeName>FORMAT_TIME_DIFF:
            ALIB.ASSERT_WARNING( ALox.FORMAT_TIME_DIFF.DefaultValue == null,
                                 "Default value of variable FORMAT_TIME_DIFF should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT_TIME_DIFF, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT_TIME_DIFF, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT_TIME_DIFF, GetName() );
                variable.AddInteger   ( MetaInfo.TimeDiffMinimum);
                variable.AddString( MetaInfo.TimeDiffNone   );
                variable.AddString( MetaInfo.TimeDiffNanos  );
                variable.AddString( MetaInfo.TimeDiffMicros );
                variable.AddString( MetaInfo.TimeDiffMillis );
                variable.AddString( MetaInfo.TimeDiffSecs   );
                variable.AddString( MetaInfo.TimeDiffMins   );
                variable.AddString( MetaInfo.TimeDiffHours  );
                variable.AddString( MetaInfo.TimeDiffDays   );
                variable.Store();
            }
            else
            {
                                           MetaInfo.TimeDiffMinimum= variable.GetInteger   (0);
                if( variable.Size() >= 2 ) MetaInfo.TimeDiffNone   = variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) MetaInfo.TimeDiffNanos  = variable.GetString(2).ToString();
                if( variable.Size() >= 4 ) MetaInfo.TimeDiffMicros = variable.GetString(3).ToString();
                if( variable.Size() >= 5 ) MetaInfo.TimeDiffMillis = variable.GetString(4).ToString();
                if( variable.Size() >= 6 ) MetaInfo.TimeDiffSecs   = variable.GetString(5).ToString();
                if( variable.Size() >= 7 ) MetaInfo.TimeDiffMins   = variable.GetString(6).ToString();
                if( variable.Size() >= 8 ) MetaInfo.TimeDiffHours  = variable.GetString(7).ToString();
                if( variable.Size() >= 9 ) MetaInfo.TimeDiffDays   = variable.GetString(8).ToString();
            }

            // Variable  <name>FORMAT_MULTILINE / <typeName>FORMAT_MULTILINE:
            ALIB.ASSERT_WARNING( ALox.FORMAT_MULTILINE.DefaultValue == null,
                                 "Default value of variable FORMAT_MULTILINE should be kept null" );
            if(    0 ==  variable.Define( ALox.FORMAT_MULTILINE, GetName()     ).Load()
                && 0 ==  variable.Define( ALox.FORMAT_MULTILINE, GetTypeName() ).Load() )
            {
                // no variable created, yet. Let's create a 'personal' one on our name
                variable.Define( ALox.FORMAT_MULTILINE, GetName() );
                variable.AddInteger( MultiLineMsgMode );
                variable.AddString ( FmtMultiLineMsgHeadline   );
                variable.AddString ( FmtMultiLinePrefix  );
                variable.AddString ( FmtMultiLineSuffix );
                variable.Store();
            }
            else
            {
                                           MultiLineMsgMode=        (int) variable.GetInteger(0)  ;
                if( variable.Size() >= 2 ) FmtMultiLineMsgHeadline= variable.GetString(1).ToString();
                if( variable.Size() >= 3 ) FmtMultiLinePrefix     = variable.GetString(2).ToString();
                if( variable.Size() >= 4 ) FmtMultiLineSuffix     = variable.GetString(3).ToString();
                if( variable.Size() >= 5 ) { if (variable.GetString(4).Equals( "nulled" , Case.Ignore ) )
                                                MultiLineDelimiter= null;
                                             else
                                                MultiLineDelimiter= variable.GetString(4).ToString();
                                           }
                if( variable.Size() >= 6 ) MultiLineDelimiterRepl = variable.GetString(5).ToString();
            }

            // call parents' implementation
            return base.AddAcquirer( newAcquirer );
        }
public void CommandLineArgs()
{
    String[] args=
    {
        "-SingleHyphen=12",
        "--DoubleHyphen=yes",
        "--Empty",
        "--Whitespaces   =  Hello Test  ",
        "--integer =  42",
        "--double =  3.14",
        "-Home=overwritten",
        "--ALIB_TEST=passed",
    };

    Configuration cfg= new Configuration();
    cfg.SetCommandLineArgs( args );
    Variable var= new Variable();
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "SingleHyphen" )) );   UT_EQ( "12",            var.GetString()       );
                                         cfg.Load   ( var.Define( "",      "DoubleHyphen" ));     UT_EQ( true,            var.IsTrue()    );
    UT_EQ( Configuration.PrioCmdLine,    var.Priority);

    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "Empty"        )) );   UT_EQ( "",              var.GetString()       );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "Whitespaces"  )) );   UT_EQ( "Hello Test",    var.GetString()       );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "HOME"         )) );   UT_EQ( "overwritten",   var.GetString()       );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "integer"      )) );   UT_EQ( 42,              var.GetInteger()    );
    UT_EQ( 0,                            cfg.Load   ( var.Define( "",      "notexistent"  )) );   UT_EQ( 0,               var.GetInteger()    );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "integer"      )) );   UT_EQ( 42,              var.GetInteger()    );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "double"       )) );   UT_EQ( 3.14,            var.GetFloat() );
    UT_EQ( 0,                            cfg.Load   ( var.Define( "",      "notexistent"  )) );   UT_EQ( 0.0,             var.GetFloat() );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "",      "double"       )) );   UT_EQ( 3.14,            var.GetFloat() );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load   ( var.Define( "ALIB",  "test"         )) );   UT_EQ( "passed",        var.GetString()       );
}
public void IniFileTest()
{
    // write sample config file
    //UT_PRINT(""); UT_PRINT( "### Configuration with IniFile ###" );
    String iniFileContents=
     "##########################################################################"  +"\n"
    +"## unit test config file"                                                    +"\n"
    +"##########################################################################"  +"\n"
    +"// this is also a comment"                                                   +"\n"
    +"; and this is as well"                                                       +"\n"
    +""                                                                            +"\n"
    +"HOME= overwritten_by_environment"                                            +"\n"
    +"HOMEPATH= overwritten_by_environment"                                        +"\n"
    +""                                                                            +"\n"
    +"concat=    start =5,          \\"                                            +"\n"
    +"           end   =32,       \\"                                              +"\n"
    +"           \\#no comment,   \\"                                              +"\n"
    +"           \\;nocomment,   \\"                                               +"\n"
    +"           ;a comment,   \\"                                                 +"\n"
    +"           getsLonger,    \\"                                                +"\n"
    +"           getsLongerxxx,   \\"                                              +"\n"
    +"           getsshorter,    \\"                                               +"\n"
    +"           getsLongerxxxxx,  \\"                                             +"\n"
    +"           getsLongerxxxxxxxxx,  \\"                                         +"\n"
    +"           getsshorterxx,    \\"                                             +"\n"
    +"           last"                                                             +"\n"
    +""                                                                            +"\n"
    +""                                                                            +"\n"
    +"CUBA=a country"                                                              +"\n"
    +"# The size "                                                                 +"\n"
    +" SIZE=  25 "                                                                 +"\n"
    +""                                                                            +"\n"
    +"# doble comment line"                                                        +"\n"
    +"# double, i meant"                                                           +"\n"
    +"2Comments= much talk"                                                        +"\n"
    +""                                                                            +"\n"
    +"# A great section"                                                           +"\n"
    +"[Great Section] "                                                            +"\n"
    +"SectionVar=5"                                                                +"\n"
    +"Double=12.3"                                                                 +"\n"
    +"Tricky=  backslash\\\\"                                                      +"\n"
    +"# A 2nd section"                                                             +"\n"
    +"[2nd Section] "                                                              +"\n"
    +"SectionVar=6"                                                                +"\n"
    +""                                                                            +"\n"
    +""                                                                            +"\n"
    +"[Great Section] "                                                            +"\n"
    +"SECTION_CONTINUED   = yEs"                                                   +"\n"
    +""                                                                            +"\n"
    +""                                                                            +"\n"
    +"[ESC] "                                                                      +"\n"
    +"Blanks=  \" x \""                                                            +"\n"
    +"Blanks2= \" x \" \\"                                                         +"\n"
    +"         \" y \" "                                                           +"\n"
    +"Tabs=\t\t\\tx\\t"                                                            +"\n"
    +"nrslash= \"\\n\\r//\\\\\""                                                   +"\n"
   ;

    String fileName= Environment.CurrentDirectory + "/unittest_testiniFile.cfg";

    // write sample config file
    {
        StreamWriter file= new StreamWriter( fileName );
        file.Write( iniFileContents );
        file.Close();
    }

    IniFile iniFile= new IniFile( fileName );
    UT_TRUE( (IniFile.Status.OK == iniFile.LastStatus) );

    // check some values
    Variable var= new Variable();
    iniFile.Load( var.Define( "",    "CUBA") );         UT_EQ( "a country",      var.GetString() );
    iniFile.Load( var.Define( "",    "cUbA") );         UT_EQ( "a country",      var.GetString() );
    iniFile.Load( var.Define( "",    "SIZE") );         UT_EQ( "25",             var.GetString() );
    iniFile.Load( var.Define( "",    "concat", ',') );  UT_EQ( 11 , var.Size());
                                                        UT_EQ( "start =5"       , var.GetString(0) );
                                                        UT_EQ( "end   =32"      , var.GetString(1) );
                                                        UT_EQ( "#no comment"    , var.GetString(2) );
                                                        UT_EQ( ";nocomment"     , var.GetString(3) );

    iniFile.Load( var.Define( "ESC", "Blanks"  ) );   UT_EQ( " x "      , var.GetString() );
    iniFile.Load( var.Define( "ESC", "Blanks2" ) );   UT_EQ( " x  y "   , var.GetString() );
    iniFile.Load( var.Define( "ESC", "Tabs"    ) );   UT_EQ( "\tx\t"    , var.GetString() );
    iniFile.Load( var.Define( "ESC", "nrslash" ) );   UT_EQ( "\n\r//\\" , var.GetString() );

    iniFile.Load( var.Define( "Great Section",  "SectionVar"       ) );   UT_EQ( "5"  , var.GetString() );
    iniFile.Load( var.Define( "2nd Section",    "SectionVar"       ) );   UT_EQ( "6"  , var.GetString() );
    iniFile.Load( var.Define( "Great Section",  "SECTION_CONTINUED") );   UT_EQ( "yEs", var.GetString() );
    iniFile.Load( var.Define( "Great Section",  "Tricky"           ) );   UT_EQ( "backslash\\", var.GetString() );

    // add it to ALIB config
    ALox.Init();
    ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );
    ALIB.Config.Load( var.Define( "",               "CUBA"              ) );   UT_EQ( "a country"  , var.GetString() );
    ALIB.Config.Load( var.Define( "",               "cUbA"              ) );   UT_EQ( "a country"  , var.GetString() );
    ALIB.Config.Load( var.Define( "",               "SIZE"              ) );   UT_EQ( "25"         , var.GetString() );
    ALIB.Config.Load( var.Define( "",               "concat"            ) );   UT_EQ( 11 , var.Size());
                                                                               UT_EQ( "start =5"   , var.GetString(0) );
                                                                               UT_EQ( "end   =32"  , var.GetString(1) );
    ALIB.Config.Load( var.Define( "Great Section",  "SectionVar"        ) );   UT_EQ( "5"          , var.GetString() );
    ALIB.Config.Load( var.Define( "2nd Section",    "SectionVar"        ) );   UT_EQ( "6"          , var.GetString() );
    ALIB.Config.Load( var.Define( "Great Section",  "SECTION_CONTINUED" ) );   UT_EQ( "yEs"        , var.GetString() );
    ALIB.Config.Load( var.Define( "Great Section",  "Tricky"            ) );   UT_EQ( "backslash\\", var.GetString() );
    ALIB.Config.Load( var.Define( "Great Section",  "SECTION_CONTINUED" ) );   UT_TRUE( var.IsTrue() );


    // check if environment variable "home" overwrites INI file
    AString vIniFile= new AString();   iniFile.Load( var.Define( "", "hOme" ) );               UT_EQ( "overwritten_by_environment", var.GetString() );
    int prio= ALIB.Config.Load( var.Define("", "hOme" ));
    if (prio != Configuration.PrioEnvironment ) // Windows platform?
    {
        prio= ALIB.Config.Load( var.Define("", "hOmePAth") );
        iniFile.Load( var.Define( "", "hOmePAth") );    UT_EQ( "overwritten_by_environment", var.GetString() );
    }
    UT_EQ( Configuration.PrioEnvironment, prio );

    UT_TRUE( var.GetString().Length() > 0 );
    UT_TRUE( !vIniFile.Equals( var.GetString()) );

    // change a value and write a new one
    var.Define( "New Section",  "newvar");
    var.Priority= Configuration.PrioIniFile;
    UT_EQ( Configuration.PrioIniFile, ALIB.Config.Store( var, "new" ) );
    ALIB.Config.Load  ( var.Define("New Section",  "newvar") );  UT_EQ( "new",   var.GetString() );

    var.Define( "",             "newvar");
    var.Priority= Configuration.PrioIniFile;
    UT_EQ( Configuration.PrioIniFile, ALIB.Config.Store( var, "aworx") );
    ALIB.Config.Load  ( var.Define("",             "newvar") );  UT_EQ( "aworx", var.GetString() );


    var.Define( "",   "newvarList", ',');
    var.AddString("val1=5");
    var.AddString("val2=10");
    var.AddString("val3=hello");
    var.Priority= Configuration.PrioIniFile;
    UT_EQ( Configuration.PrioIniFile, ALIB.Config.Store(var) );
    ALIB.Config.Load (  var.Define( "",  "newvarList")   );

    var.Define( "",   "commented", ',', "2lines" );
    var.Priority= Configuration.PrioIniFile;
    UT_EQ( Configuration.PrioIniFile, ALIB.Config.Store(  var,  "this is c-line 1 \nand this line 2" ) );

    // write the file
    iniFile.FileName._(".writeback.txt");
    iniFile.WriteFile();

    // load the written file into another config
    IniFile readBack= new IniFile( iniFile.FileName.ToString() );
    Variable varBack= new Variable();

    // compare all
    UT_TRUE( (IniFile.Status.OK == readBack.LastStatus) );

    {
        AString msg= new AString();
        Substring orig= new Substring();
        Substring back= new Substring();
        foreach ( IniFile.Section section in iniFile.Sections )
        {
            foreach ( IniFile.Entry entry in section.Entries )
            {
                msg.Clear()._( "Reading variable " ).Field()._( section.Name )._( '/' )._( entry.Name );
                UT_PRINT( msg );


                char delim= '\0';
                if(     entry.Name.Equals("concat")
                    ||  entry.Name.Equals("newvarList")       )
                    delim= ',';

                iniFile .Load( var    .Define( section.Name, entry.Name, delim) );
                readBack.Load( varBack.Define( section.Name, entry.Name, delim) );

                UT_EQ( var.Size(), varBack.Size() );
                for ( int i= 0; i< var.Size(); i++ )
                {
                    int idx= var.GetString(i).IndexOf('=');
                    if( idx < 0 )
                    {
                        UT_EQ( var.GetString(i), varBack.GetString(i) );
                    }
                    else
                    {
                        int idxBack= varBack.GetString(i).IndexOf('=');
                        orig.Set( var    .GetString(i), 0, idx     );
                        back.Set( varBack.GetString(i), 0, idxBack );
                        UT_EQ( orig.Trim().ToString(), back.Trim().ToString() );
                        orig.Set( var    .GetString(i), idx     +1 );
                        back.Set( varBack.GetString(i), idxBack +1 );
                        UT_EQ( orig.Trim().ToString(), back.Trim().ToString() );
                    }
                }
            }
        }
    }

    readBack.Load ( var.Define( "New Section",  "newvar" ) );   UT_EQ( "new"  , var.GetString() );
    readBack.Load ( var.Define( "",             "newvar" ) );   UT_EQ( "aworx", var.GetString() );


    ALIB.Config.RemovePlugin( iniFile );


    ALIB.Config.InsertPlugin( readBack, Configuration.PrioIniFile );
    ALIB.Config.Load ( var.Define( "New Section",  "newvar") );   UT_EQ( "new"   , var.GetString() );
    ALIB.Config.Load ( var.Define( "",             "newvar") );   UT_EQ( "aworx" , var.GetString() );

    ALIB.Config.RemovePlugin( readBack );
}
public void ConfigReplacementVariables()
{
    UT_INIT();

    String[] args=
    {
        "COMMANDLINE",
        "--REPL_CMDLINE=ReplCommandLine",
        "--NOCATCMDLINE=NoCatCommandLine",
    };

    Configuration cfg= new Configuration();
    cfg.SetCommandLineArgs( args );

    Variable var= new Variable();

    // replacements from command line plugin
    var.Define( "TEST", "VARIABLE" );
    cfg.ProtectedValues.Store( var, "no replacment"                ); cfg.Load( var );   UT_EQ( "no replacment"                   ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$UKN"                         ); cfg.Load( var );   UT_EQ( ""                                ,var.GetString() );
    cfg.ProtectedValues.Store( var, "-$UKN * $UKN2-"               ); cfg.Load( var );   UT_EQ( "- * -"                           ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$NOCATCMDLINE"                ); cfg.Load( var );   UT_EQ( "NoCatCommandLine"                ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$$NOCATCMDLINE$"              ); cfg.Load( var );   UT_EQ( "$NoCatCommandLine$"              ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$REPL_CMDLINE"                ); cfg.Load( var );   UT_EQ( "ReplCommandLine"                 ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$REPL_ CMDLINE"               ); cfg.Load( var );   UT_EQ( " CMDLINE"                        ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$repL_CmdLine"                ); cfg.Load( var );   UT_EQ( "ReplCommandLine"                 ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$repL_CmdLine$repL_CmdLine"   ); cfg.Load( var );   UT_EQ( "ReplCommandLineReplCommandLine"  ,var.GetString() );
    cfg.ProtectedValues.Store( var, "$repL_CmdLine $repL_CmdLine"  ); cfg.Load( var );   UT_EQ( "ReplCommandLine ReplCommandLine" ,var.GetString() );

    // replacements without category name
    cfg.ProtectedValues.Store( var.Define( ""    , "NOCAT"   ), "NoCat"    );
    cfg.ProtectedValues.Store( var.Define( ""    , "NO_CAT"  ), "No_cat"   );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "$nocat"                       ); cfg.Load( var );   UT_EQ( "NoCat"   ,var.GetString() );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "$_nocat"                      ); cfg.Load( var );   UT_EQ( "NoCat"   ,var.GetString() );

    // need to add an underscore, if no category but name contains underscore!
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "$no_cat"                      ); cfg.Load( var );   UT_EQ( ""        ,var.GetString() );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "$_no_cat"                     ); cfg.Load( var );   UT_EQ( "No_cat"  ,var.GetString() );


    // nested variables
    cfg.ProtectedValues.Store( var.Define( "Rep", "Var1"     ), "$Rep_Var2"                         );
    cfg.ProtectedValues.Store( var.Define( "Rep", "Var2"     ), "nested"                            );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "$rep_var2"                    ); cfg.Load( var );   UT_EQ( "nested"                          ,var.GetString() );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "$rep_var1"                    ); cfg.Load( var );   UT_EQ( "nested"                          ,var.GetString() );

    // illegal recursion
    UT_PRINT( "One warning should follow" );
    cfg.ProtectedValues.Store( var.Define( "Rep", "Var1"     ), "$Rep_Var2"                         );
    cfg.ProtectedValues.Store( var.Define( "Rep", "Var2"     ), "$Rep_Var1"                         );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "$rep_var1"                    ); cfg.Load( var );

    // custom variable definitions
    cfg.ProtectedValues.Store( var.Define( "Rep", "CUST"     ), "cf"                                );

    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), ">>$REP_CUST<<"                ); cfg.Load( var );   UT_EQ( ">>cf<<"                          ,var.GetString() );

    cfg.SubstitutionVariableStart._()._( "${" );
    cfg.SubstitutionVariableEnd  ._()._( "}"  );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), ">>${REP_CUST}<<"              ); cfg.Load( var );   UT_EQ( ">>cf<<"                          ,var.GetString() );

    cfg.SubstitutionVariableStart._()._( "€€€-");
    cfg.SubstitutionVariableEnd  ._()._( "--"  );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), ">>€€€-REP_CUST--<<"           ); cfg.Load( var );   UT_EQ( ">>cf<<"                          ,var.GetString() );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), ">>€€€-REP_CUST--"             ); cfg.Load( var );   UT_EQ( ">>cf"                            ,var.GetString() );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "€€€-REP_CUST--"               ); cfg.Load( var );   UT_EQ( "cf"                              ,var.GetString() );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "€€€-REP_CUST--€€€-REP_CUST--" ); cfg.Load( var );   UT_EQ( "cfcf"                            ,var.GetString() );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "€€-REP_CUST--"                ); cfg.Load( var );   UT_EQ( "€€-REP_CUST--"                   ,var.GetString() );

    UT_PRINT( "One warning should follow" );
    cfg.ProtectedValues.Store( var.Define( "TEST", "VARIABLE"), "€€€-REP_CUST-"                ); cfg.Load( var );   UT_EQ( "€€€-REP_CUST-"                   ,var.GetString() );
    cfg.SubstitutionVariableStart._()._( "$" );
    cfg.SubstitutionVariableEnd._();

    // multi line replacements
    cfg.DefaultValues.Store( var.Define("ML", "REPL1", ';'), "repl1-v1;repl1-v2"   );
    cfg.DefaultValues.Store( var.Define("ML", "REPL2", ';'), "repl2-v1;repl2-v2"   );
    cfg.DefaultValues.Store( var.Define("ML", "VAR"  , ';'), "$ML_REPL1;$ML_REPL2" );
    var.Define("ML", "VAR", ';' );
    cfg.Load( var );
    UT_EQ( 4, var.Size() );
    UT_EQ( "repl1-v1", var.GetString(0) );
    UT_EQ( "repl1-v2", var.GetString(1) );
    UT_EQ( "repl2-v1", var.GetString(2) );
    UT_EQ( "repl2-v2", var.GetString(3) );
}
public void ConfigDefaultAndProtected()
{
    UT_INIT();

    String[] args=
    {
        "COMMANDLINE",
        "--TEST_VARIABLE=fromCommandLine",
    };

    Configuration cfg= new Configuration();
    cfg.SetCommandLineArgs( args );

    Variable var= new Variable();

    // command line
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load  ( var.Define( "TEST",      "VARIABLE" ) ) );   UT_EQ( "fromCommandLine"    ,var.GetString() );

    // set default, does not overwrite
    cfg.DefaultValues.Store( var.Define("TEST", "VARIABLE"), "not overwriting" );
    UT_EQ( Configuration.PrioCmdLine,    cfg.Load  ( var.Define( "TEST",      "VARIABLE" ) ) );   UT_EQ( "fromCommandLine"    ,var.GetString() );

    // set protected, overwrites command line
    cfg.ProtectedValues.Store( var.Define("TEST", "VARIABLE"), "does overwrite" );
    UT_EQ( Configuration.PrioProtected,  cfg.Load  ( var.Define( "TEST",      "VARIABLE" ) ) );   UT_EQ( "does overwrite"     ,var.GetString() );

    // set default, something else
    cfg.DefaultValues.Store( var.Define("TEST", "VAR2"), "this is var 2" );
    UT_EQ( Configuration.PrioDefault,    cfg.Load  ( var.Define( "TEST",      "VAR2"     ) ) );   UT_EQ( "this is var 2"      ,var.GetString() );

    // set and remove an entry using plugin interface
    var.Define( "TEST", "Remove" );     UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg.DefaultValues.Load( var );      UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    var.AddString("To be deleted");     UT_EQ( 1, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg.DefaultValues.Store( var );     UT_EQ( 1, var.Size() );     UT_EQ( -1                           ,var.Priority );
    var.Define( "TEST", "Remove" );     UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg.DefaultValues.Load( var );      UT_EQ( 1, var.Size() );     UT_EQ( -1                           ,var.Priority );
    var.ClearValues();                  UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg.DefaultValues.Store( var );     UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    var.Define( "TEST", "Remove" );     UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg.DefaultValues.Load( var );      UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );

    // set and remove an entry using configuration interface
    cfg              .Load ( var );     UT_EQ( 0, var.Size() );     UT_EQ(  0                           ,var.Priority );
    cfg              .Store( var );     UT_EQ( 0, var.Size() );     UT_EQ(  0                           ,var.Priority );
    var.AddString("To be deleted");     UT_EQ( 1, var.Size() );     UT_EQ(  0                           ,var.Priority );
    cfg              .Store( var );     UT_EQ( 1, var.Size() );     UT_EQ( Configuration.PrioDefault    ,var.Priority );
    var.Define( "TEST", "Remove" );     UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg              .Load ( var );     UT_EQ( 1, var.Size() );     UT_EQ( Configuration.PrioDefault    ,var.Priority );
    var.Define( "TEST", "Remove" );     UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg              .Store( var );     UT_EQ( 0, var.Size() );     UT_EQ( Configuration.PrioDefault    ,var.Priority );
    cfg              .Load ( var );     UT_EQ( 0, var.Size() );     UT_EQ( 0                            ,var.Priority );
    var.Define( "TEST", "Remove" );     UT_EQ( 0, var.Size() );     UT_EQ( -1                           ,var.Priority );
    cfg              .Load ( var );     UT_EQ( 0, var.Size() );     UT_EQ( 0                            ,var.Priority );

    // protected
    var.Define( "TEST", "Protected");   UT_EQ( 0, var.Size() );                 UT_EQ( -1                          ,var.Priority );
    var.DefaultValue._( "Default"  );
    var.StoreDefault( "def par");       UT_EQ( "def par",   var.GetString() );  UT_EQ( Configuration.PrioDefault   ,var.Priority );

    var.ClearValues();
    var.AddString( "def var" );
    var.StoreDefault();                 UT_EQ( "def var",   var.GetString() );  UT_EQ( Configuration.PrioDefault   ,var.Priority );

    var.ClearValues();
    var.StoreDefault();                 UT_EQ( "Default",   var.GetString() );  UT_EQ( Configuration.PrioDefault   ,var.Priority );

    var.ClearValues();
    var.AddString( "def var" );
    var.Protect();                      UT_EQ( "def var",   var.GetString() );  UT_EQ( Configuration.PrioProtected ,var.Priority );
    var.Protect("prot par");            UT_EQ( "prot par",  var.GetString() );  UT_EQ( Configuration.PrioProtected ,var.Priority );
    var.ClearValues();
    var.Protect();                      UT_EQ( "Default",   var.GetString() );  UT_EQ( Configuration.PrioProtected ,var.Priority );
    var.DefaultValue.SetNull();
    var.ClearValues();
    var.Protect();                      UT_EQ( 0, var.Size()                );  UT_EQ( Configuration.PrioProtected ,var.Priority );
    var.Load();                         UT_EQ( "Default",   var.GetString() );  UT_EQ( Configuration.PrioDefault   ,var.Priority );

}
    public void Log_WriteVerbosities()
    {
        UT_INIT();

        Log.AddDebugLogger();
        MemoryLogger memLogger= new MemoryLogger("MYLGGR");
        Log.SetVerbosity( Log.DebugLogger, Verbosity.Verbose, ALox.InternalDomains );

        Variable var= new Variable( ALox.ConfigCategoryName, Log.LOX.GetName() + "_MYLGGR_VERBOSITY",  ';' );
        Variable varBack= new Variable();

        // test writing into other variable with variable name error
        UT_PRINT( "An error message should follow (wrong variable format): " );
        var.Store(  "writeback MY_" );
        Log.SetVerbosity( memLogger, Verbosity.Verbose );
        Log.RemoveLogger( memLogger );

        // test writing into other variable
        var.Store(  "writeback MY_VAR" );
        Log.SetVerbosity( memLogger, Verbosity.Verbose );
        Log.RemoveLogger( memLogger );
        varBack.Define( "MY",  "VAR" ).Load();
        UT_PRINT(  "Variable written: " + varBack.GetString().ToString() );
        UT_TRUE( varBack.GetString().Length() > 0 );

        // test writing into other variable without cat
        var.Store(  "writeback ANON" );
        Log.SetVerbosity( memLogger, Verbosity.Verbose );
        Log.RemoveLogger( memLogger );
        varBack.Define( "",  "ANON" ).Load();
        UT_PRINT(  "Variable written: " + varBack.GetString().ToString() );
        UT_TRUE( varBack.GetString().Length() > 0 );

        // test writing into other variable without cat and with underscores in name
        var.Store(  "writeback _2ND_ANON" );
        Log.SetVerbosity( memLogger, Verbosity.Verbose );
        Log.RemoveLogger( memLogger );
        varBack.Define( "",  "2ND_ANON" ).Load();
        UT_PRINT(  "Variable written: " + varBack.GetString().ToString() );
        UT_TRUE( varBack.GetString().Length() > 0 );

        // test writing into other the variable itself
        var.Store(  "writeback" );
        Log.SetVerbosity( memLogger, Verbosity.Verbose );
        Log.RemoveLogger( memLogger );

        ALIB.Config.Load( var);
        UT_PRINT( "Variable written: " + var.GetString().ToString() );
        UT_TRUE( var.GetString().Length() > 0 );

       Log.RemoveDebugLogger();
    }
    public void Log_SetSourcePathTrimRuleExternal()
    {
        UT_INIT();

        // for the unit tests to reset, we need an extra lox to be able to clear the global rules
        // beforewe initialize our main lox
        Lox clearLox= new Lox("ClearingRules");

        // global rule
        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        {
            // create iniFile
            String iniFileContents=
                 "[ALOX]\n"
                +"TESTML_FORMAT= \"%Sp\"  \n"

                +"GLOBAL_SOURCE_PATH_TRIM_RULES=  *src.cs/   , true  ;     \\   \n"
                             +"    /usr/local/lib/  , false, 9, true, /usr/lib/"
                +"\n"
               ;
/* SNIPPIT FOR Dox
//! [Man_SourcePathTrimming]
[ALOX]
GLOBAL_SOURCE_PATH_TRIM_RULES= *src.cs/                  , true                ; \
                               /usr/local/lib/  , false, 9, true, /usr/lib/
//! [Man_SourcePathTrimming]
*/
            String fileName= Environment.CurrentDirectory + "/Log_ConfigTrimRules.ini";
            StreamWriter file= new StreamWriter( fileName );
            file.Write( iniFileContents );
            file.Close();

            IniFile iniFile= new IniFile( fileName );
            iniFile.ReadFile();
            //iniFile.WriteFile(); // temporarily enable to see what we have written above

            ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );

            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" );  UT_EQ("alox.unittests", ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            ALIB.Config.RemovePlugin( iniFile );
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        // local rule
        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // store default values
            Variable var= new Variable();
            var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ).Store( "%Sp" );
            var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';')
            .Store( "*;**; *alox.u*, include ;*;**" // default values, 0, ignore"
                                                    // the * will be removed
                                                    // two illegal rules before and after
                                 );

            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" ); UT_EQ( "nittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // create iniFile
            IniFile iniFile= new IniFile("*"); // don't read
            Variable var= new Variable();
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ),  "%Sp" );
            iniFile.Store( var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';'),
                           "*alox.u, excl, 2, sens" );

            ALIB.Config.InsertPlugin( iniFile, Configuration.PrioIniFile );


            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" ); UT_EQ( "ox.unittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            // overwrite with source priority
            lox.SetSourcePathTrimRule( "*alox.u", Inclusion.Exclude, 0, Case.Ignore, "REPLACE_1/", Reach.Local );
            lox.Info( "" ); UT_EQ( "ox.unittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();
            lox.SetSourcePathTrimRule( "*alox.u", Inclusion.Exclude, 0, Case.Ignore, "REPLACE_2/", Reach.Local, Configuration.PrioProtected );
            lox.Info( "" ); UT_TRUE( ml.MemoryLog.StartsWith( "REPLACE_2/" ) ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            ALIB.Config.RemovePlugin( iniFile );
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        // ignore case
        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // store default values
            Variable var= new Variable();
            var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ).Store( "%Sp" );
            var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';')
               .Store( "*aLOX.U, exc, 2, ign"   );


            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" ); UT_EQ( "ox.unittests"  , ml.MemoryLog ); ml.MemoryLog._(); ml.AutoSizes.Reset();

            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }

        clearLox.ClearSourcePathTrimRules( Reach.Global, false);
        ALIB.Config.DefaultValues.Reset();
        {
            // store default values
            Variable var= new Variable();
            var.Define( ALox.ConfigCategoryName, "TESTML_FORMAT" ).Store( "%Sp" );
            var.Define( ALox.ConfigCategoryName, "T_LOX_SOURCE_PATH_TRIM_RULES",';')
               .Store( "*aLOX.U, excl, 2, sens"  );



            // test
            Lox lox= new Lox("T_LOX", false );

            lox.SetVerbosity( Lox.CreateConsoleLogger("CONSOLE") , Verbosity.Verbose );
            lox.SetVerbosity( "CONSOLE"                          , Verbosity.Verbose, ALox.InternalDomains );

            MemoryLogger ml= new MemoryLogger("TESTML");

            lox.SetVerbosity(ml, Verbosity.Verbose );

            lox.Info( "" );
            if( Path.DirectorySeparatorChar == '/' )
                UT_EQ( "src.cs/alox.unittests"  , ml.MemoryLog );
            else
                UT_EQ( "src.cs\\alox.unittests"  , ml.MemoryLog );

            ml.MemoryLog._(); ml.AutoSizes.Reset();
            lox.RemoveLogger( ml );
            lox.RemoveLogger( "CONSOLE" );
        }
    }
Exemple #14
0
        /** ****************************************************************************************
         * Invokes \b Find on the given domain and logs internal message when the domain was
         * not known before.
         *
         * @param domainSystem  The domain system. Either the standard or the internal one.
         * @param domainPath    The domain path.
         * @return The resulting \ref cs::aworx::lox::core::Domain "Domain".
         ******************************************************************************************/
        Domain findDomain( Domain domainSystem, AString domainPath )
        {
            AString substPath= domainSystem == domains ? tmpSubstitutionPath
                                                       : tmpSubstitutionPathInternalDomains;

            int maxSubstitutions= 10;
            for(;;)
            {
                // loop for creating domains, one by one
                Domain dom= null;
                for(;;)
                {
                    bool wasCreated= false;
                    dom= domainSystem.Find( domainPath, DomainSensitivity, 1, ref wasCreated );

                    if ( wasCreated )
                    {
                        // get maximum domain path length (for nicer State output only...)
                        if ( maxDomainPathLength < dom.FullPath.Length() )
                            maxDomainPathLength=   dom.FullPath.Length();

                        // log info on new domain
                        intMsg._()._('\'')._NC( dom.FullPath )._NC("' registered.");
                        logInternal( Verbosity.Info, "DMN", intMsg );
                    }

                    // read domain from Config
                    if ( !dom.ConfigurationRead )
                    {
                        dom.ConfigurationRead= true;

                        Variable variable= new Variable();
                        for ( int i= 0; i < dom.CountLoggers(); ++i )
                        {
                            Logger logger= dom.GetLogger(i);
                            if ( 0 != variable.Define( ALox.VERBOSITY, GetName(), logger.GetName() ).Load() )
                                getVerbosityFromConfig( logger, dom, variable );
                        }

                        getDomainPrefixFromConfig( dom );
                    }

                    // log inherited setting for each logger
                    if ( wasCreated )
                    {
                        if ( domainSystem.CountLoggers() == 0 )
                            logInternal( Verbosity.Verbose, "DMN", intMsg._()._NC("No loggers set, yet.") );
                        else
                            for ( int i= 0; i < domainSystem.CountLoggers(); i++ )
                            {
                                intMsg._()._("  \"")._( dom.GetLogger(i).GetName() )._NC("\":");
                                intMsg.InsertChars( ' ', maxLoggerNameLength  + 6 - intMsg.Length() );
                                intMsg._NC( dom.FullPath )
                                      ._NC( " = " ); ALox.ToString( dom.GetVerbosity( i ), dom.GetPriority( i), intMsg );

                                logInternal( Verbosity.Verbose, "DMN", intMsg );
                            }
                    }
                    else
                        break;
                }

                // apply domain substitutions
                if( domainSubstitutions.Count > 0 )
                {
                    substPath.Clear();
                    while( maxSubstitutions-- > 0  )
                    {
                        // loop over rules
                        bool substituted= false;
                        foreach( DomainSubstitutionRule rule in domainSubstitutions )
                        {
                            switch( rule.type )
                            {
                                case DomainSubstitutionRule.Type.StartsWith:
                                    if( substPath.IsEmpty() )
                                    {
                                        if ( dom.FullPath.StartsWith( rule.Search, DomainSensitivity ) )
                                        {
                                            substPath._( rule.Replacement )._( dom.FullPath, rule.Search.Length() );
                                            substituted= true;
                                            continue; //next rule
                                        }
                                    }
                                    else
                                    {
                                        if ( substPath.StartsWith( rule.Search, DomainSensitivity ) )
                                        {
                                            substPath.ReplaceSubstring( rule.Replacement, 0, rule.Search.Length()  );
                                            substituted= true;
                                            continue; //next rule
                                        }
                                    }
                                break;

                                case DomainSubstitutionRule.Type.EndsWith:
                                    if( substPath.IsEmpty() )
                                    {
                                        if ( dom.FullPath.EndsWith( rule.Search, DomainSensitivity ) )
                                        {
                                            substPath._( dom.FullPath, 0, dom.FullPath.Length() - rule.Search.Length() )._( rule.Replacement );
                                            substituted= true;
                                            continue;
                                        }
                                    }
                                    else
                                    {
                                        if ( substPath.EndsWith( rule.Search, DomainSensitivity ) )
                                        {
                                            substPath.DeleteEnd( rule.Search.Length() )._( rule.Replacement );
                                            substituted= true;
                                            continue;
                                        }
                                    }
                                break;


                                case DomainSubstitutionRule.Type.Substring:
                                    if( substPath.IsEmpty() )
                                    {
                                        int idx= dom.FullPath.IndexOf( rule.Search, 0, DomainSensitivity );
                                        if ( idx >= 0 )
                                        {
                                            substPath._( dom.FullPath, 0, idx )._( rule.Replacement)._( dom.FullPath, idx + rule.Search.Length() );
                                            substituted= true;
                                            continue; //next rule
                                        }
                                    }
                                    else
                                    {
                                        int idx= substPath.IndexOf( rule.Search, 0, DomainSensitivity );
                                        if ( idx >= 0 )
                                        {
                                            substPath.ReplaceSubstring( rule.Replacement, idx, rule.Search.Length()  );
                                            substituted= true;
                                            continue; //next rule
                                        }
                                    }
                                break;

                                case DomainSubstitutionRule.Type.Exact:
                                {
                                    if( substPath.IsEmpty() )
                                    {
                                        if ( dom.FullPath.Equals( rule.Search ) )
                                        {
                                            substPath._( rule.Replacement);
                                            substituted= true;
                                            continue; //next rule
                                        }
                                    }
                                    else
                                    {
                                        if ( substPath.Equals( rule.Search) )
                                        {
                                            substPath._()._( rule.Replacement );
                                            substituted= true;
                                            continue; //next rule
                                        }
                                    }
                                }
                                break;

                            } // switch rule type

                        }//rules loop

                        // stop if non was found
                        if( !substituted )
                            break;
                    }

                    // too many substitutions?
                    if ( maxSubstitutions <= 0 && !oneTimeWarningCircularDS )
                    {
                        oneTimeWarningCircularDS= true;
                        intMsg._()._(   "The Limit of 10 domain substitutions was reached. Circular substitution assumed!"
                                      + " (This error is only reported once!)" );

                        logInternal( Verbosity.Error, "DMN", intMsg );
                    }

                    // anything substituted?
                    if( substPath.Length() > 0 )
                    {
                        domainPath= substPath;
                        continue;
                    }
                }

                return dom;
            }
        }