using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using Deltares.Standard.IO; using Deltares.Standard.Language; using LumenWorks.Framework.IO.Csv; namespace Deltares.Dam.Data.CsvImporters { public class CsvImporterSurfaceLinesException : Exception { public CsvImporterSurfaceLinesException(string message) : base(message) { } } public class CsvImporterSurfaceLines { private readonly List surfaceLineRecords = new List(); private List errorMessages = new List(); public class SurfaceLineRecord { private IList xcoors = new List(); private IList ycoors = new List(); private IList zcoors = new List(); public string SurfaceLineId { get; set; } public int SurfaceLineRecordId { get; set; } public IList Xcoors { get { return xcoors; } set { xcoors = value; } } public IList Ycoors { get { return ycoors; } set { ycoors = value; } } public IList Zcoors { get { return zcoors; } set { zcoors = value; } } } private void CheckColumn(int index, string fileName, string fieldName) { if (index < 0) { var csvHeaderFieldError = LocalizationManager.GetTranslatedText(GetType(), "csvHeaderFieldError"); throw new CsvImporterSurfaceLinesException(String.Format("{0} : {1} {2}", fileName, csvHeaderFieldError, fieldName)); } } /// /// Copies to temporary file. /// /// Name of the file. /// the name of the temporary file private string CopyToTemporaryFile(string fileName) { string newFilename = Path.GetTempFileName(); File.Delete(newFilename); File.Copy(fileName, newFilename); return newFilename; } public CsvImporterSurfaceLines(string filename) { errorMessages.Clear(); ThrowHelper.ThrowIfStringArgumentNullOrEmpty(filename, StringResourceNames.CsvFileNotValid); ThrowHelper.ThrowIfFileNotExist(filename, StringResourceNames.CsvFileNotFound); // This is a 'dynamic' csv file, i.e. the number of columns is not known and can vary per row. So make sure of a // proper header (i.e. a header with the maximum number of fields // because the file will be changed we copy it to a temporary file and perform the action on the temporary file string tempFilename = CopyToTemporaryFile(filename); CsvReaderUtilities.EnsureProperHeaderForDynamicRecordLengthInCsvFile(tempFilename); var oldcur = Thread.CurrentThread.CurrentCulture; try { Thread.CurrentThread.CurrentCulture = CsvReaderUtilities.DetermineCultureForFile(tempFilename); using (CsvReader csv = new CsvReader(new StreamReader(tempFilename), true, ';'){ MissingFieldAction = MissingFieldAction.ReplaceByNull }) { string[] headers = CsvImporterHelper.GetFieldHeaders(this, csv); int colIndexSurfaceLineId = CsvReaderUtilities.GetHeaderIndexByString(headers, SurfaceLineCsvColumnNames.LocationColumnName); if (colIndexSurfaceLineId < 0) { // colIndexSurfaceLineId can be defined with 2 identifiers (ProfileNameColumnName is deprecated, LocationColumnName is the new one) colIndexSurfaceLineId = CsvReaderUtilities.GetHeaderIndexByString(headers, SurfaceLineCsvColumnNames.LocationColumnName); if (colIndexSurfaceLineId < 0) { colIndexSurfaceLineId = CsvReaderUtilities.GetHeaderIndexByString(headers, SurfaceLineCsvColumnNames.ProfileNameColumnName); } } CheckColumn(colIndexSurfaceLineId, tempFilename, SurfaceLineCsvColumnNames.LocationColumnName); int colIndexFirstX = CsvReaderUtilities.GetHeaderIndexByString(headers, SurfaceLineCsvColumnNames.FirstXColumnName); CheckColumn(colIndexFirstX, tempFilename, SurfaceLineCsvColumnNames.FirstXColumnName); int maxColumns = headers.Count(); var end = Math.Floor((maxColumns - colIndexFirstX + 1) / 3.0); var surflineIndex = 1; while (csv.ReadNextRecord()) { var recordReadError = false; SurfaceLineRecord surfaceLine = new SurfaceLineRecord { SurfaceLineRecordId = surflineIndex }; surflineIndex++; surfaceLine.SurfaceLineId = csv[colIndexSurfaceLineId]; var colIndex = colIndexFirstX; for (int i = 0; i < end; i++) { // if the first value = null the end of this surfaceline is reached, so break and it. Checking on null can only be done this way, // a csv[index] == null does not work as that throws an exception itself. try { var dum = csv[colIndex]; if (String.IsNullOrEmpty(dum)) break; } catch (Exception) { break; } // other "errors" are real errors so trap them. try { surfaceLine.Xcoors.Add(Convert.ToDouble(csv[colIndex])); colIndex++; surfaceLine.Ycoors.Add(Convert.ToDouble(csv[colIndex])); colIndex++; surfaceLine.Zcoors.Add(Convert.ToDouble(csv[colIndex])); colIndex++; } catch (Exception e) { var csvSurfaceLineError = String.Format(LocalizationManager.GetTranslatedText(GetType(), "csvSurfaceLineError"), surfaceLine.SurfaceLineRecordId, colIndex + 1); errorMessages.Add(csvSurfaceLineError + e.Message); recordReadError = true; break; } } if (!recordReadError) { surfaceLineRecords.Add(surfaceLine); } } } } finally { File.Delete(tempFilename); Thread.CurrentThread.CurrentCulture = oldcur; } } public List ImportedItems { get { return surfaceLineRecords; } } public List ErrorMessages { get { return errorMessages; } set { errorMessages = value; } } } }