/// /// Copyright (c) 2013-2017 Sensus Metering Systems /// using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Threading; using log4net; using Config.Entities; using TBF.BenchControl; using TBF.Resources; namespace TBF.BenchControl.Output.FileWriters.Basic { public class Writer : ComponentBase, IOperation, GenericDevices.IResultsWriter { private static readonly ILog log = LogManager.GetLogger(typeof(Writer)); public override string ToString() { return string.Format("Output.FileWriters.Basic({0})", Cfg.ToString(1)); } readonly WriterCfg writerCfg; readonly string separatorStr; /// /// Result items to print /// readonly IList rsltItems; Thread thread1; /// Thread where one file is saved Thread thread2; /// Thread where another file is saved bool completed1; /// Set to 'true' by the first thread when writing to the file completed bool completed2; /// Set to 'true' by the second thread when writing to the file completed bool abort; /// Set to 'true' by Stop() operation to abort writing to the file public Writer() {} public Writer(Generic.IComponentCfg cfg) : base(cfg) { writerCfg = cfg as WriterCfg; switch (writerCfg.Separator) { default: case Separator.None: separatorStr = string.Empty; break; case Separator.Space: separatorStr = " "; break; case Separator.Tabulator: separatorStr = "\t"; break; case Separator.Comma: separatorStr = ","; break; case Separator.Semicolon: separatorStr = ";"; break; } rsltItems = Results.WMeterRsltItemSpec.FromStrArray(writerCfg.SelectedItems); log.Debug(this.ToString()); } /// /// Returns a file name derived from a DateTime structure. /// Creates directories on this path as a side effect. /// /// Date and time /// File name string GetFilename(string destinationPath, DateTime time) { string directory = destinationPath; /// Ends with "\\"; switch (writerCfg.YearFolders) { case YearFolders.FourDigit: directory = string.Format("{0}{1}\\", directory, time.Year.ToString("D4")); break; case YearFolders.TwoDigit: directory = string.Format("{0}{1}\\", directory, (time.Year % 100).ToString("D2")); break; } switch (writerCfg.MonthFolders) { case MonthFolders.Name: { string monthStr; switch (time.Month) { default: case 1: monthStr = "January"; break; case 2: monthStr = "February"; break; case 3: monthStr = "March"; break; case 4: monthStr = "April"; break; case 5: monthStr = "May"; break; case 6: monthStr = "June"; break; case 7: monthStr = "July"; break; case 8: monthStr = "August"; break; case 9: monthStr = "September"; break; case 10: monthStr = "October"; break; case 11: monthStr = "November"; break; case 12: monthStr = "December"; break; } directory = string.Format("{0}{1}\\", directory, monthStr); break; } case MonthFolders.Digit: directory = string.Format("{0}{1}\\", directory, time.Month.ToString()); break; case MonthFolders.TwoDigit: directory = string.Format("{0}{1}\\", directory, time.Month.ToString("D2")); break; } switch (writerCfg.DayFolders) { case DayFolders.Digit: directory = string.Format("{0}{1}\\", directory, time.Day.ToString()); break; case DayFolders.TwoDigit: directory = string.Format("{0}{1}\\", directory, time.Day.ToString("D2")); break; } Directory.CreateDirectory(directory); try { if (string.IsNullOrEmpty(writerCfg.FileNameFormat)) throw new Exception(); return directory + string.Format(writerCfg.FileNameFormat, time); } catch { return string.Format("{0}{1:yyMMdd-HHmm}.txt", directory, time); } } /// /// Writes the test cycle results into a file /// Events: /// Event.ResultsWritten /// Event.Busy /// /// Results to write into a file /// Reference to the operation public IOperation WriteResultsOp(Results.Entities.Batch batch) { thread1 = new Thread(() => { WriteRslts(batch, writerCfg.DestinationPath); completed1 = true; }); thread2 = new Thread(() => { WriteRslts(batch, writerCfg.DestinationPath2); completed2 = true; }); if (writerCfg.Culture > Culture.system && writerCfg.Culture < Culture.Count) { thread1.CurrentCulture = new CultureInfo(writerCfg.Culture.ToString()); thread2.CurrentCulture = new CultureInfo(writerCfg.Culture.ToString()); } return this; } /// Start this operation public void Start() { completed1 = false; completed2 = false; abort = false; thread1.Start(); thread2.Start(); } /// Run this operation /// Event.ResultsWritten public Event Run() { if (completed1 && completed2) return Event.ResultsWritten; else return Event.Busy; } /// Stop this operation public void Stop() { if (!completed1 || !completed2) abort = true; } void WriteRslts(Results.Entities.Batch batch, string destination) { if (batch == null || batch.WaterMeters == null || batch.WaterMeters.Count <= 0) return; if (rsltItems == null || rsltItems.Count == 0) return; StreamWriter writer = StreamWriter.Null; if (!string.IsNullOrEmpty(writerCfg.DestinationPath)) { try { writer = File.AppendText(GetFilename(writerCfg.DestinationPath, batch.EndTime)); } catch { } } foreach (var wm in batch.WaterMeters) { if (!writerCfg.SaveGoodOnly || wm.Passed) { WriteWM(writer, wm); if (abort) return; } } writer.Close(); } /// /// Write one water meter results /// /// Water meter number (0-based) void WriteWM(StreamWriter wr, Results.Entities.WaterMeter wm) { for (int i = 0; i < rsltItems.Count; i++) { if (abort) return; wr.Write(rsltItems[i].Print(wm)); if (i < rsltItems.Count - 1) { wr.Write(separatorStr); } else { wr.WriteLine(string.Empty); } } } } }