} // TestFormatItemCounters private static void ListAllErrors ( List<FormatStringError> plstAllErrors ) { const int ORDINAL_FROM_SUBSCRIPT = ArrayInfo.INDEX_FROM_ORDINAL; const int POS_LABEL = ArrayInfo.ARRAY_FIRST_ELEMENT; const int POS_VALUE = ArrayInfo.ARRAY_SECOND_ELEMENT; const char DELIMITER = FormatStringError.LABEL_VALUE_DELIMITER; ReportDetail.DetailFormat = "{3} {0} = {1}"; int intErrorCount = plstAllErrors.Count; for ( int intI = ArrayInfo.ARRAY_FIRST_ELEMENT ; intI < intErrorCount ; intI++ ) { FormatStringError fse = plstAllErrors [ intI ]; string [ ] astrErrorDetails = fse.Split ( ); int intNDetails = astrErrorDetails.Length; // Save a trip into the collection. ReportDetails rptDtlsColl = new ReportDetails ( intNDetails ); string [ ] astrErrorSummaryFirst = new string [ ] { string.Format ( Properties.Resources.MSG_FORMAT_ERROR_DETAILS , // Format template string FormatItem.XofY ( // Format Item 0 intI + ORDINAL_FROM_SUBSCRIPT , // X = Item Number intErrorCount ) ) // Y = Item Count }; // string [ ] astrErrorSummaryFirst // ------------------------------------------------------------ // Maybe there is a better way to accompish this. Nevertheless, // this method works for generating a completely blank string // of a length that must be determined at runtime. // ------------------------------------------------------------ string [ ] astrErrorSummaryAllOthers = new string [ ] { string.Empty.PadRight ( astrErrorSummaryFirst [ ArrayInfo.ARRAY_FIRST_ELEMENT ].Length ) }; // string [ ] astrErrorSummaryAllOthers for ( int intJ = ArrayInfo.ARRAY_FIRST_ELEMENT ; intJ < intNDetails ; intJ++ ) { string [ ] astrLabelAndValue = astrErrorDetails [ intJ ].Split ( DELIMITER ); rptDtlsColl.Add ( new ReportDetail ( astrLabelAndValue [ POS_LABEL ].Trim ( ) , // Label (Format Item = 0) astrLabelAndValue [ POS_VALUE ].Trim ( ) , // Value (Format Item = 1) as String ( ReportDetail.ItemDisplayOrder ) ArrayInfo.OrdinalFromIndex ( intJ ) , // Item Number (Format Item = 2) - The arithmetic operation casts it to int (signed), so it must be forcibly cast back to unsigned int. null , // Individual Format String (Null = Use Default from static property) ( intJ == ArrayInfo.ARRAY_FIRST_ELEMENT ) // Additional Details - Condition ? astrErrorSummaryFirst // Value if Condition is True : astrErrorSummaryAllOthers ) ); // Value if Condition is False } // for ( uint uintJ = ArrayInfo.ARRAY_FIRST_ELEMENT ; uintJ < intNDetails ; uintJ++ ) rptDtlsColl.ListAllItems ( ); } // for ( int intI = ArrayInfo.ARRAY_FIRST_ELEMENT ; intI < intErrorCount ; intI++ ) } // ListAllErrors
} // MergeOutputFQFN private static void ReportDetailsTests ( bool pfTestSorting ) { const uint OUT_OF_ORDER = 900; string strTaskName = System.Reflection.MethodBase.GetCurrentMethod ( ).Name; Console.WriteLine ( Properties.Resources.IDS_MSG_BATCH , strTaskName , Properties.Resources.IDS_MSG_BEGIN , Environment.NewLine ); if ( pfTestSorting ) FormatStringParsing_Drills.TestFormatItemCounters ( ); ReportDetails rdColl = new ReportDetails ( ); if ( pfTestSorting ) Console.WriteLine ( Properties.Resources.MSG_REPORT_DETAILS_SELECTIVELY_OVERRIDDEN , Environment.NewLine ); else Console.WriteLine ( Properties.Resources.MSG_REPORT_DETAILS_AUTO_ORDERED , Environment.NewLine ); rdColl.Add ( new ReportDetail ( Properties.Resources.IDS_MSG_REPORT_LABEL_1 , Properties.Resources.IDS_MSG_REPORT_LABEL_1.Length , Properties.Resources.IDS_MSG_REPORT_LABEL_1.Length.ToString ( ) ) ); rdColl.Add ( new ReportDetail ( Properties.Resources.IDS_MSG_REPORT_LABEL_2 , Properties.Resources.IDS_MSG_REPORT_LABEL_2.Length , Properties.Resources.IDS_MSG_REPORT_LABEL_2.Length.ToString ( ) ) ); rdColl.Add ( new ReportDetail ( Properties.Resources.IDS_MSG_REPORT_LABEL_3 , Properties.Resources.IDS_MSG_REPORT_LABEL_3.Length , Properties.Resources.IDS_MSG_REPORT_LABEL_3.Length.ToString ( ) , ( ReportDetail.ItemDisplayOrder ) OUT_OF_ORDER ) ); // This one is intentionally out of order. rdColl.Add ( new ReportDetail ( Properties.Resources.IDS_MSG_REPORT_LABEL_4 , Properties.Resources.IDS_REALLY_LONG_STRING.Length ) ); // Leave the display value NULL. Console.WriteLine ( Properties.Resources.IDS_MSG_LONGEST_LABEL , rdColl.WidthOfWidestLabel ); Console.WriteLine ( Properties.Resources.IDS_MSG_LONGEST_VALUE , rdColl.WidthOfWidestValue , Environment.NewLine ); if ( pfTestSorting ) { // The sorting pass shows it twice. Console.WriteLine ( Properties.Resources.MSG_REPORT_DETAILS_UNSORTED , Environment.NewLine ); } // if ( pfTestSorting ) // ---------------------------------------------------------------- // Since the value of this property is computed on demand by // enumerating the collection, it is more efficient to hoist it out // of the loop that also enumerates it. This change improves the // performance of the foreach loop that follows it from an O(n^2) // operation to an O(n) operation. // // Since the typical size of these report item collections is on // tho order of a few hundred items or less, the computational // impact of this change is too small to measure without running // hundreds or thousands of iterations. Nevertheless, when it's so // easy to do so, I believe that any operation should be designed // to scale as well as possible. // ---------------------------------------------------------------- int intWidthOfWidestLabel = rdColl.WidthOfWidestLabel; int intWidthOfWidestValue = rdColl.WidthOfWidestValue; foreach ( ReportDetail rdItem in rdColl ) { Console.WriteLine ( ReportDetail.DEFAULT_FORMAT , intWidthOfWidestLabel , rdItem.GetPaddedValue ( intWidthOfWidestValue , FormatItem.Alignment.Right , NumericFormats.DECIMAL ) ); } // foreach ( ReportDetail rdItem in rdColl ) if ( pfTestSorting ) { // The second pass follows a sort. Console.WriteLine ( Properties.Resources.MSG_REPORT_DETAILS_UNSORTED , Environment.NewLine ); rdColl.Sort ( ); // ReportDetails implements IComparable. Use it. foreach ( ReportDetail rdItem in rdColl ) { Console.WriteLine ( ReportDetail.DEFAULT_FORMAT , rdItem.GetPaddedLabel ( intWidthOfWidestLabel ) , rdItem.GetPaddedValue ( intWidthOfWidestValue , FormatItem.Alignment.Right , NumericFormats.DECIMAL ) ); } // foreach ( ReportDetail rdItem in rdColl ) } // if ( pfTestSorting ) Console.WriteLine ( Properties.Resources.IDS_MSG_BATCH , strTaskName , Properties.Resources.IDS_MSG_DONE , Environment.NewLine ); } // private void ReportDetailsTests
} // private void ReportDetailsTests private static void ReportHelpersTests ( ) { const uint DESIRED_WIDTH_MINIMUM = 1; const uint DESIRED_WIDTH_MAXIMUM = 10; const uint ITEM_NUMBER_MINIMUM = 0; const uint ITEM_NUMBER_MAXIMUM = 4; string strTaskName = System.Reflection.MethodBase.GetCurrentMethod ( ).Name; Console.WriteLine ( Properties.Resources.IDS_MSG_BATCH , strTaskName , Properties.Resources.IDS_MSG_BEGIN , Environment.NewLine ); uint uintTestNumber = MagicNumbers.ZERO; uint uintExceptionCount = MagicNumbers.ZERO; long lngTotalTests = MagicNumbers.ZERO; string strHeadingFormat = null; #if DBG_REPORTHELPERSTESTS uint uintItemIndexCounter = MagicNumbers.ZERO; #endif // DBG_REPORTHELPERSTESTS for ( uint uintItemIndex = ITEM_NUMBER_MINIMUM ; uintItemIndex <= ITEM_NUMBER_MAXIMUM ; uintItemIndex++ ) { #if DBG_REPORTHELPERSTESTS Console.WriteLine ( "LOOP DEBUG: uintItemIndexCounter = {0}, uintItemIndex = {1}" , ++uintItemIndexCounter , uintItemIndex ); uint uintMaximumWidthCounter = MagicNumbers.ZERO; #endif // DBG_REPORTHELPERSTESTS for ( uint uintMaximumWidth = DESIRED_WIDTH_MINIMUM ; uintMaximumWidth < DESIRED_WIDTH_MAXIMUM ; uintMaximumWidth++ ) { #if DBG_REPORTHELPERSTESTS Console.WriteLine ( "LOOP DEBUG: uintMaximumWidthCounter = {0}, uintMaximumWidth = {1}" , ++uintMaximumWidthCounter , uintMaximumWidth ); uint uintAlignmentCounter = MagicNumbers.ZERO; #endif // DBG_REPORTHELPERSTESTS foreach ( FormatItem.Alignment enmAlignment in s_aenmAlignment ) { #if DBG_REPORTHELPERSTESTS Console.WriteLine ( "LOOP DEBUG: uintAlignmentCounter = {0}, enmAlignment = {1}" , ++uintAlignmentCounter , enmAlignment ); uint uintTestFormatCounter = MagicNumbers.ZERO; #endif // DBG_REPORTHELPERSTESTS foreach ( string strTestFormat in s_astrFormats ) { #if DBG_REPORTHELPERSTESTS Console.WriteLine ( "LOOP DEBUG: uintTestFormatCounter = {0}, strTestFormat = {1}" , ++uintTestFormatCounter , strTestFormat ); #endif // DBG_REPORTHELPERSTESTS if ( lngTotalTests == MagicNumbers.ZERO ) { lngTotalTests = ( ( ITEM_NUMBER_MAXIMUM - ITEM_NUMBER_MINIMUM ) + ArrayInfo.ORDINAL_FROM_INDEX ) * ( DESIRED_WIDTH_MAXIMUM - DESIRED_WIDTH_MINIMUM ) * s_aenmAlignment.Length * s_astrFormats.Length; strHeadingFormat = FormatItem.UpgradeFormatItem ( Properties.Resources.MSG_NEW_TEST , ITEM_NUMBER_MINIMUM , FormatItem.AdjustToMaximumWidth ( ITEM_NUMBER_MINIMUM , ( uint ) lngTotalTests.ToString ( NumericFormats.NUMBER_PER_REG_SETTINGS_0D ).Length , FormatItem.Alignment.Right , NumericFormats.NUMBER_PER_REG_SETTINGS_0D ) ); } // if ( lngTotalTests == MagicNumbers.ZERO ) Console.WriteLine ( strHeadingFormat , ++uintTestNumber , lngTotalTests , Environment.NewLine ); string strUpgradedFormat = FormatItem.AdjustToMaximumWidth ( uintItemIndex , uintMaximumWidth , enmAlignment , strTestFormat ); ReportDetails rdColl = new ReportDetails ( ); rdColl.Add ( new ReportDetail ( Properties.Resources.MSG_PENMALIGNMENT , ( object ) uintItemIndex ) ); rdColl.Add ( new ReportDetail ( Properties.Resources.MSG_PUINTMAXIMUMWIDTH , ( object ) uintMaximumWidth ) ); rdColl.Add ( new ReportDetail ( Properties.Resources.MSG_PENMALIGNMENT , enmAlignment ) ); rdColl.Add ( new ReportDetail ( Properties.Resources.MSG_PSTRFORMATSTRING , ( object ) strTestFormat ) ); // Coerce strTestFormat into the object. rdColl.Add ( new ReportDetail ( Properties.Resources.MSG_UPGRADED_FORMAT , ( object ) strUpgradedFormat ) ); int uintRequiredWidth = rdColl.WidthOfWidestLabel; foreach ( ReportDetail rdItem in rdColl ) { Console.WriteLine ( ReportDetail.DEFAULT_FORMAT , rdItem.Label.PadRight ( ( int ) uintRequiredWidth ) , rdItem.Value ); } // foreach ( ReportDetail rdItem in rdColl ) // ------------------------------------------------ // There are intentionally programed exceptions in // this test. // ------------------------------------------------ try { Console.WriteLine ( Properties.Resources.MSG_SHOW_SAMPLE_BEFORE_AND_AFTER , Properties.Resources.MSG_SAMPLE_FORMAT_STRING , FormatItem.UpgradeFormatItem ( Properties.Resources.MSG_SAMPLE_FORMAT_STRING , uintItemIndex , strUpgradedFormat ) , Environment.NewLine ); } catch ( Exception exAllKinds ) { rs_appThis.BaseStateManager.AppExceptionLogger.ReportException ( exAllKinds ); uintExceptionCount++; } if ( uintTestNumber == lngTotalTests ) { // We need just one test of this type of error. try { Console.WriteLine ( Properties.Resources.MSG_SHOW_SAMPLE_BEFORE_AND_AFTER , Properties.Resources.MSG_SAMPLE_FORMAT_STRING , FormatItem.UpgradeFormatItem ( Properties.Resources.MSG_SAMPLE_FORMAT_STRING , uintItemIndex , "(4,9:X8)" ) , // This format item is invalid. Environment.NewLine ); } catch ( Exception exAllKinds ) { rs_appThis.BaseStateManager.AppExceptionLogger.ReportException ( exAllKinds ); uintExceptionCount++; } } // if ( uintTestNumber == lngTotalTests ) } // foreach ( string strTestFormat in s_astrFormats ) } // foreach ( FormatItem.Alignment enmAlignment in s_aenmAlignment ) } // for ( uint uintMaximumWidth = MINIMUM_DESIRED_WIDTH ; uintMaximumWidth <= MAXIMUM_DESIRED_WIDTH ; uintMaximumWidth++ ) } // for ( uint uintItemIndex = MINIMUM_ITEM_NUMBER ; uintItemIndex < FORMAT_ITEM_LIMIT ; uintItemIndex++ ) Console.WriteLine ( Properties.Resources.MSG_EXCETIONS_COUNTED , uintExceptionCount , Environment.NewLine ); Console.WriteLine ( Properties.Resources.IDS_MSG_BATCH , strTaskName , Properties.Resources.IDS_MSG_DONE , Environment.NewLine ); } // ReportHelpersTests
} // private static string [ ] MakePaddedLabels private ReportDetails UseInputFromFile ( ) { ReportDetails rptDetails = new ReportDetails ( s_astrPaddedLbels.Length ); int intItemIndex = ArrayInfo.ARRAY_INVALID_INDEX; string strInputFQFN = Path.Combine ( Program.rs_strDataDirectory , _strTestDataFileName ); FileInfo fiInputFile = new FileInfo ( strInputFQFN ); string [ ] astrLinesFromFile = File.ReadAllLines ( strInputFQFN ); int intLogestLine = WizardWrx.ReportHelpers.MaxStringLength ( new List<string> ( astrLinesFromFile ) ); foreach ( string strLabel in s_astrPaddedLbels ) { switch ( s_enmDetailItem [ ++intItemIndex ] ) { case DetailItem.DataSource: rptDetails.Add ( new ReportDetail ( strLabel , _enmDataSource.ToString ( ) ) ); break; // case DetailItem.DataSource case DetailItem.SourceFQFN: if ( fiInputFile.DirectoryName == Program.rs_strDataDirectory ) rptDetails.Add ( new ReportDetail ( strLabel , fiInputFile.Name ) ); else rptDetails.Add ( new ReportDetail ( strLabel , fiInputFile.FullName ) ); break; // case DetailItem.SourceFQFN case DetailItem.ModDate: rptDetails.Add ( new ReportDetail ( strLabel , SysDateFormatters.ReformatSysDate ( fiInputFile.LastWriteTime , SysDateFormatters.RFD_YYYY_MM_DD_HH_MM_SS ) ) ); break; // case DetailItem.ModDate case DetailItem.FileSize: rptDetails.Add ( new ReportDetail ( strLabel , fiInputFile.Length.ToString ( NumericFormats.NUMBER_PER_REG_SETTINGS_0D ) ) ); break; // case DetailItem.FileSize case DetailItem.LineCount: rptDetails.Add ( new ReportDetail ( strLabel , astrLinesFromFile.LongLength.ToString ( NumericFormats.NUMBER_PER_REG_SETTINGS_0D ) ) ); break; // case DetailItem.LineCount case DetailItem.LongestLine: rptDetails.Add ( new ReportDetail ( strLabel , intLogestLine.ToString ( NumericFormats.NUMBER_PER_REG_SETTINGS_0D ) ) ); break; // case DetailItem.LongestLine } // switch ( s_enmDetailItem [ ++intItemIndex ] ) } // foreach ( string strLabel in s_astrPaddedLbels ) return rptDetails; } // private void UseInputFromFile