796 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			796 lines
		
	
	
		
			37 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using Adaptation.Eaf.Management.ConfigurationData.CellAutomation;
 | |
| using Adaptation.Ifx.Eaf.EquipmentConnector.File.Configuration;
 | |
| using Adaptation.Shared.Methods;
 | |
| using log4net;
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Globalization;
 | |
| using System.IO;
 | |
| using System.Linq;
 | |
| using System.Text;
 | |
| using System.Text.Json;
 | |
| using System.Text.Json.Serialization;
 | |
| using System.Threading;
 | |
| 
 | |
| namespace Adaptation.Shared;
 | |
| 
 | |
| public class FileRead : Properties.IFileRead
 | |
| {
 | |
| 
 | |
|     protected string _NullData;
 | |
|     protected readonly ILog _Log;
 | |
|     protected long _MinFileLength;
 | |
|     protected Logistics _Logistics;
 | |
|     protected readonly ISMTP _SMTP;
 | |
|     protected readonly int _Hyphens;
 | |
|     protected readonly bool _IsEvent;
 | |
|     protected string _ReportFullPath;
 | |
|     protected long _LastTicksDuration;
 | |
|     protected readonly bool _IsEAFHosted;
 | |
|     protected readonly string _EventName;
 | |
|     protected readonly string _MesEntity;
 | |
|     protected readonly string _TracePath;
 | |
|     protected readonly bool _IsDuplicator;
 | |
|     protected readonly Calendar _Calendar;
 | |
|     protected readonly bool _IsSourceTimer;
 | |
|     protected readonly string _EquipmentType;
 | |
|     protected readonly long _BreakAfterSeconds;
 | |
|     protected readonly string _ExceptionSubject;
 | |
|     protected readonly string _CellInstanceName;
 | |
|     protected readonly string _EventNameFileRead;
 | |
|     protected readonly IDescription _Description;
 | |
|     protected readonly bool _UseCyclicalForDescription;
 | |
|     protected readonly string _CellInstanceConnectionName;
 | |
|     protected readonly string _CellInstanceConnectionNameBase;
 | |
|     protected readonly Dictionary<string, List<long>> _DummyRuns;
 | |
|     protected readonly Dictionary<string, string> _FileParameter;
 | |
|     protected readonly string _ParameterizedModelObjectDefinitionType;
 | |
|     protected readonly FileConnectorConfiguration _FileConnectorConfiguration;
 | |
|     protected readonly Dictionary<long, List<Metrology.WS.Results>> _StaticRuns;
 | |
|     protected readonly IList<ModelObjectParameterDefinition> _ModelObjectParameterDefinitions;
 | |
| 
 | |
|     bool Properties.IFileRead.IsEvent => _IsEvent;
 | |
|     string Properties.IFileRead.NullData => _NullData;
 | |
|     string Properties.IFileRead.EventName => _EventName;
 | |
|     string Properties.IFileRead.MesEntity => _MesEntity;
 | |
|     bool Properties.IFileRead.IsEAFHosted => _IsEAFHosted;
 | |
|     bool Properties.IFileRead.IsDuplicator => _IsDuplicator;
 | |
|     string Properties.IFileRead.EquipmentType => _EquipmentType;
 | |
|     string Properties.IFileRead.ReportFullPath => _ReportFullPath;
 | |
|     string Properties.IFileRead.CellInstanceName => _CellInstanceName;
 | |
|     string Properties.IFileRead.ExceptionSubject => _ExceptionSubject;
 | |
|     bool Properties.IFileRead.UseCyclicalForDescription => _UseCyclicalForDescription;
 | |
|     string Properties.IFileRead.CellInstanceConnectionName => _CellInstanceConnectionName;
 | |
|     string Properties.IFileRead.ParameterizedModelObjectDefinitionType => _ParameterizedModelObjectDefinitionType;
 | |
| 
 | |
|     protected static string GetTupleFile<T>(Logistics logistics, List<T> descriptions, Properties.IScopeInfo scopeInfo, string duplicateDirectory, string duplicateFile) where T : Properties.IDescription
 | |
|     {
 | |
|         string result;
 | |
|         string rds;
 | |
|         string fileName;
 | |
|         string dateValue;
 | |
|         string rdsPlaceholder = "%RDS%";
 | |
|         string mesEntityPlaceholder = "%MesEntity%";
 | |
|         if (descriptions.Count == 0 || string.IsNullOrEmpty(descriptions[0].RDS))
 | |
|             rds = logistics.MID;
 | |
|         else
 | |
|             rds = descriptions[0].RDS;
 | |
|         string[] segments = scopeInfo.FileName.Split(new string[] { "DateTime:" }, StringSplitOptions.RemoveEmptyEntries);
 | |
|         if (segments.Length == 0)
 | |
|             result = string.Concat(duplicateDirectory, @"\", scopeInfo.FileNameWithoutExtension.Replace(rdsPlaceholder, rds).Replace(mesEntityPlaceholder, logistics.MesEntity));
 | |
|         else
 | |
|         {
 | |
|             segments = segments[1].Split('%');
 | |
|             string datePlaceholder = "%DateTime%";
 | |
|             dateValue = logistics.DateTimeFromSequence.ToString(segments[0]);
 | |
|             foreach (string segment in scopeInfo.FileName.Split('%'))
 | |
|             {
 | |
|                 if (!segment.Contains(segments[0]))
 | |
|                     continue;
 | |
|                 datePlaceholder = string.Concat('%', segment, '%');
 | |
|             }
 | |
|             fileName = scopeInfo.FileName.Replace(rdsPlaceholder, rds).Replace(mesEntityPlaceholder, logistics.MesEntity).Replace(datePlaceholder, dateValue);
 | |
|             if (!duplicateFile.Contains("Viewer"))
 | |
|                 result = Path.Combine(duplicateDirectory, fileName);
 | |
|             else
 | |
|                 result = Path.Combine(duplicateDirectory, $"Viewer_{fileName}");
 | |
|         }
 | |
|         if (result.Contains('%'))
 | |
|             throw new Exception("Placeholder exists!");
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     protected void WaitForFileConsumption<T>(string sourceDirectoryCloaking, Logistics logistics, DateTime dateTime, List<T> descriptions, string successDirectory, string duplicateDirectory, string duplicateFile, List<(Properties.IScopeInfo, string)> collection) where T : Properties.IDescription
 | |
|     {
 | |
|         bool check;
 | |
|         long preWait;
 | |
|         string tupleFile;
 | |
|         string tupleFileName = string.Empty;
 | |
|         List<string> duplicateFiles = new();
 | |
|         StringBuilder stringBuilder = new();
 | |
|         List<int> consumedFileIndices = new();
 | |
|         bool moreThanAnHour = _BreakAfterSeconds > 3600;
 | |
|         long breakAfter = dateTime.AddSeconds(_BreakAfterSeconds).Ticks;
 | |
|         if (_FileConnectorConfiguration?.FileHandleWaitTime is null)
 | |
|             preWait = dateTime.AddMilliseconds(1234).Ticks;
 | |
|         else
 | |
|             preWait = dateTime.AddMilliseconds(_FileConnectorConfiguration.FileHandleWaitTime.Value).Ticks;
 | |
|         if (collection.Count == 0)
 | |
|             duplicateFiles.Add(duplicateFile);
 | |
|         string fileName = Path.GetFileNameWithoutExtension(logistics.ReportFullPath);
 | |
|         string successFile = string.Concat(successDirectory, @"\", Path.GetFileName(logistics.ReportFullPath));
 | |
|         foreach ((Properties.IScopeInfo scopeInfo, string text) in collection)
 | |
|         {
 | |
|             if (scopeInfo.FileName.StartsWith(@"\"))
 | |
|                 tupleFile = scopeInfo.FileName;
 | |
|             else if (!scopeInfo.FileName.Contains('%'))
 | |
|                 tupleFile = string.Concat(duplicateDirectory, @"\", fileName, "_", scopeInfo.FileNameWithoutExtension, ".pdsfc");
 | |
|             else
 | |
|                 tupleFile = GetTupleFile(logistics, descriptions, scopeInfo, duplicateDirectory, duplicateFile);
 | |
|             tupleFileName = Path.GetFileNameWithoutExtension(tupleFile).Split('.')[0];
 | |
|             duplicateFiles.Add(tupleFile);
 | |
|             if (_IsEAFHosted)
 | |
|                 File.WriteAllText(tupleFile, text);
 | |
|         }
 | |
|         for (short i = 0; i < short.MaxValue; i++)
 | |
|         {
 | |
|             if (DateTime.Now.Ticks > preWait)
 | |
|                 break;
 | |
|             Thread.Sleep(100);
 | |
|         }
 | |
|         if (!moreThanAnHour)
 | |
|         {
 | |
|             for (short z = 0; z < short.MaxValue; z++)
 | |
|             {
 | |
|                 try
 | |
|                 {
 | |
|                     check = string.IsNullOrEmpty(successDirectory) || File.Exists(successFile);
 | |
|                     if (check)
 | |
|                     {
 | |
|                         consumedFileIndices.Clear();
 | |
|                         for (int i = 0; i < duplicateFiles.Count; i++)
 | |
|                         {
 | |
|                             if (!File.Exists(duplicateFiles[i]))
 | |
|                             {
 | |
|                                 if (string.IsNullOrEmpty(tupleFileName))
 | |
|                                     consumedFileIndices.Add(i);
 | |
|                                 else if (duplicateFiles.All(l => Path.GetFileNameWithoutExtension(l).Split('.')[0] == tupleFileName))
 | |
|                                 {
 | |
|                                     for (int j = 0; j < duplicateFiles.Count; j++)
 | |
|                                         consumedFileIndices.Add(j);
 | |
|                                 }
 | |
|                                 else
 | |
|                                     consumedFileIndices.Add(i);
 | |
|                             }
 | |
|                         }
 | |
|                         if (consumedFileIndices.Count == duplicateFiles.Count)
 | |
|                             break;
 | |
|                     }
 | |
|                 }
 | |
|                 catch (Exception) { }
 | |
|                 if (DateTime.Now.Ticks > breakAfter)
 | |
|                 {
 | |
|                     for (int i = 0; i < duplicateFiles.Count; i++)
 | |
|                     {
 | |
|                         if (File.Exists(duplicateFiles[i]))
 | |
|                         {
 | |
|                             try
 | |
|                             { File.Delete(duplicateFiles[i]); }
 | |
|                             catch (Exception) { }
 | |
|                             _ = stringBuilder.Append('<').Append(duplicateFiles[i]).Append("> ");
 | |
|                         }
 | |
|                     }
 | |
|                     throw new Exception(string.Concat("After {", _BreakAfterSeconds, "} seconds, right side of {", sourceDirectoryCloaking, "} didn't consume file(s) ", stringBuilder));
 | |
|                 }
 | |
|                 Thread.Sleep(250);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected void WaitForFileConsumption<T>(DateTime dateTime, List<T> descriptions, bool isDummyRun, string successDirectory, string duplicateDirectory, List<(Properties.IScopeInfo, string)> collection, string duplicateFile) where T : Properties.IDescription
 | |
|     {
 | |
|         if (!isDummyRun && _IsEAFHosted)
 | |
|             WaitForFileConsumption(_FileConnectorConfiguration.SourceDirectoryCloaking, _Logistics, dateTime, descriptions, successDirectory, duplicateDirectory, duplicateFile, collection);
 | |
|         else
 | |
|         {
 | |
|             long breakAfter = DateTime.Now.AddSeconds(_FileConnectorConfiguration.FileHandleWaitTime.Value).Ticks;
 | |
|             for (short i = 0; i < short.MaxValue; i++)
 | |
|             {
 | |
|                 if (!_IsEAFHosted || DateTime.Now.Ticks > breakAfter)
 | |
|                     break;
 | |
|                 Thread.Sleep(500);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     public FileRead(IDescription description, bool isEvent, ISMTP smtp, Dictionary<string, string> fileParameter, string cellInstanceName, int? connectionCount, string cellInstanceConnectionName, FileConnectorConfiguration fileConnectorConfiguration, string equipmentTypeName, string parameterizedModelObjectDefinitionType, IList<ModelObjectParameterDefinition> modelObjectParameters, string equipmentDictionaryName, Dictionary<string, List<long>> dummyRuns, Dictionary<long, List<Metrology.WS.Results>> staticRuns, bool useCyclicalForDescription, bool isEAFHosted)
 | |
|     {
 | |
|         _SMTP = smtp;
 | |
|         _IsEvent = isEvent;
 | |
|         _DummyRuns = dummyRuns;
 | |
|         _LastTicksDuration = 0;
 | |
|         _StaticRuns = staticRuns;
 | |
|         _IsEAFHosted = isEAFHosted;
 | |
|         _Description = description;
 | |
|         _FileParameter = fileParameter;
 | |
|         _ReportFullPath = string.Empty;
 | |
|         _CellInstanceName = cellInstanceName;
 | |
|         _Calendar = new CultureInfo("en-US").Calendar;
 | |
|         _Log = LogManager.GetLogger(typeof(FileRead));
 | |
|         _UseCyclicalForDescription = useCyclicalForDescription;
 | |
|         _CellInstanceConnectionName = cellInstanceConnectionName;
 | |
|         _ModelObjectParameterDefinitions = modelObjectParameters;
 | |
|         _FileConnectorConfiguration = fileConnectorConfiguration;
 | |
|         _ParameterizedModelObjectDefinitionType = parameterizedModelObjectDefinitionType;
 | |
|         _IsSourceTimer = fileConnectorConfiguration.SourceFileFilter.StartsWith("*Timer.txt");
 | |
|         string cellInstanceConnectionNameBase = cellInstanceConnectionName.Replace("-", string.Empty);
 | |
|         _Hyphens = cellInstanceConnectionName.Length - cellInstanceConnectionNameBase.Length;
 | |
|         _TracePath = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, "Path.Trace");
 | |
|         _ExceptionSubject = string.Concat("Exception:", _CellInstanceConnectionName, _FileConnectorConfiguration?.SourceDirectoryCloaking);
 | |
|         string suffix;
 | |
|         string[] segments = _ParameterizedModelObjectDefinitionType.Split('.');
 | |
|         string @namespace = segments[0];
 | |
|         string eventNameFileRead = "FileRead";
 | |
|         string eventName = segments[segments.Length - 1];
 | |
|         bool isDuplicator = segments[0] == cellInstanceName;
 | |
|         _IsDuplicator = isDuplicator;
 | |
|         _CellInstanceConnectionNameBase = cellInstanceConnectionNameBase;
 | |
|         if (eventName == eventNameFileRead)
 | |
|             suffix = string.Empty;
 | |
|         else
 | |
|             suffix = string.Concat('_', eventName.Split(new string[] { eventNameFileRead }, StringSplitOptions.RemoveEmptyEntries)[1]);
 | |
|         string parameterizedModelObjectDefinitionTypeAppended = string.Concat(@namespace, suffix);
 | |
|         if (!isEAFHosted)
 | |
|         {
 | |
|             if (string.IsNullOrEmpty(equipmentTypeName) || equipmentTypeName != parameterizedModelObjectDefinitionTypeAppended)
 | |
|                 throw new Exception(cellInstanceConnectionName);
 | |
|             if (string.IsNullOrEmpty(equipmentDictionaryName) && isEvent)
 | |
|                 throw new Exception(cellInstanceConnectionName);
 | |
|             if (!string.IsNullOrEmpty(equipmentDictionaryName) && !isEvent && connectionCount > 1)
 | |
|                 throw new Exception(cellInstanceConnectionName);
 | |
|             // if (string.IsNullOrEmpty(equipmentDictionaryName) && !isEvent)
 | |
|             //     throw new Exception(cellInstanceConnectionName);
 | |
|             // if (!string.IsNullOrEmpty(equipmentDictionaryName) && isEvent)
 | |
|             //     throw new Exception(cellInstanceConnectionName);
 | |
|         }
 | |
|         if (isDuplicator)
 | |
|             _MesEntity = string.Empty;
 | |
|         else
 | |
|             _MesEntity = GetPropertyValue(cellInstanceConnectionName, modelObjectParameters, string.Concat("CellInstance.", cellInstanceName, ".Alias"));
 | |
|         _EventName = eventName;
 | |
|         _EventNameFileRead = eventNameFileRead;
 | |
|         _EquipmentType = parameterizedModelObjectDefinitionTypeAppended;
 | |
|         long breakAfterSeconds;
 | |
|         if (_FileConnectorConfiguration is null)
 | |
|             breakAfterSeconds = 360;
 | |
|         else
 | |
|         {
 | |
|             if (_FileConnectorConfiguration.FileScanningOption == FileConnectorConfiguration.FileScanningOptionEnum.TimeBased)
 | |
|                 breakAfterSeconds = Math.Abs(_FileConnectorConfiguration.FileHandleTimeout.Value);
 | |
|             else if (_FileConnectorConfiguration.FileScanningOption == FileConnectorConfiguration.FileScanningOptionEnum.FileWatcher)
 | |
|                 breakAfterSeconds = Math.Abs(_FileConnectorConfiguration.FileScanningIntervalInSeconds.Value);
 | |
|             else
 | |
|                 throw new Exception();
 | |
|         }
 | |
|         _BreakAfterSeconds = breakAfterSeconds;
 | |
|         UpdateLastTicksDuration(breakAfterSeconds * 10000000);
 | |
|         if (_IsDuplicator)
 | |
|         {
 | |
|             if (string.IsNullOrEmpty(_FileConnectorConfiguration.TargetFileLocation) || string.IsNullOrEmpty(_FileConnectorConfiguration.ErrorTargetFileLocation))
 | |
|                 throw new Exception("_Configuration is empty?");
 | |
|             if (_FileConnectorConfiguration.TargetFileLocation.Contains('%') || _FileConnectorConfiguration.ErrorTargetFileLocation.Contains('%'))
 | |
|                 throw new Exception("_Configuration is incorrect for a duplicator!");
 | |
|             // if (_FileConnectorConfiguration is not null)
 | |
|             // {
 | |
|             //     if (string.IsNullOrEmpty(_FileConnectorConfiguration.SourceDirectoryCloaking))
 | |
|             //         throw new Exception("SourceDirectoryCloaking is empty?");
 | |
|             //     if (!_FileConnectorConfiguration.SourceDirectoryCloaking.StartsWith("~"))
 | |
|             //         throw new Exception("SourceDirectoryCloaking is incorrect for a duplicator!");
 | |
|             // }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected static string GetPropertyValue(string cellInstanceConnectionName, IList<ModelObjectParameterDefinition> modelObjectParameters, string propertyName)
 | |
|     {
 | |
|         string result;
 | |
|         List<string> results = (from l in modelObjectParameters where l.Name == propertyName select l.Value).ToList();
 | |
|         if (results.Count != 1)
 | |
|             throw new Exception(cellInstanceConnectionName);
 | |
|         result = results[0];
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     protected void UpdateLastTicksDuration(long ticksDuration)
 | |
|     {
 | |
|         if (ticksDuration < 50000000)
 | |
|             ticksDuration = 50000000;
 | |
|         _LastTicksDuration = (long)Math.Ceiling(ticksDuration * .667);
 | |
|         _Log.Info($"{new TimeSpan(ticksDuration).TotalMilliseconds} TotalMillisecond(s) to process{Environment.NewLine}{_CellInstanceConnectionName}{Environment.NewLine}<{_ReportFullPath}>");
 | |
|     }
 | |
| 
 | |
|     internal static string GetParentParent(string value)
 | |
|     {
 | |
|         string result = Path.GetDirectoryName(Path.GetDirectoryName(value));
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal static List<string> GetDirectoryNames(string directory)
 | |
|     {
 | |
| #nullable enable
 | |
|         List<string> results = new();
 | |
|         string? fileName;
 | |
|         string? checkDirectory = directory;
 | |
|         string? pathRoot = Path.GetPathRoot(directory);
 | |
|         string extension = Path.GetExtension(directory);
 | |
|         if (string.IsNullOrEmpty(pathRoot))
 | |
|             throw new NullReferenceException(nameof(pathRoot));
 | |
|         if (Directory.Exists(directory))
 | |
|         {
 | |
|             fileName = Path.GetFileName(directory);
 | |
|             if (!string.IsNullOrEmpty(fileName))
 | |
|                 results.Add(fileName);
 | |
|         }
 | |
|         else if ((string.IsNullOrEmpty(extension) || extension.Length > 3) && !File.Exists(directory))
 | |
|         {
 | |
|             fileName = Path.GetFileName(directory);
 | |
|             if (!string.IsNullOrEmpty(fileName))
 | |
|                 results.Add(fileName);
 | |
|         }
 | |
|         for (int i = 0; i < int.MaxValue; i++)
 | |
|         {
 | |
|             checkDirectory = Path.GetDirectoryName(checkDirectory);
 | |
|             if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
 | |
|                 break;
 | |
|             fileName = Path.GetFileName(checkDirectory);
 | |
|             if (string.IsNullOrEmpty(fileName))
 | |
|                 continue;
 | |
|             results.Add(fileName);
 | |
|         }
 | |
|         results.Add(pathRoot);
 | |
|         results.Reverse();
 | |
|         return results;
 | |
| #nullable disable
 | |
|     }
 | |
| 
 | |
|     internal static string GetJobIdParentDirectory(string directory)
 | |
|     {
 | |
|         string result;
 | |
|         if (!string.IsNullOrEmpty(Path.GetFileName(directory)))
 | |
|             result = Path.GetFullPath(GetParentParent(directory));
 | |
|         else
 | |
|             result = Path.GetFullPath(GetParentParent(Path.GetDirectoryName(directory)));
 | |
|         if (!Directory.Exists(result))
 | |
|             _ = Directory.CreateDirectory(result);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal static string GetFileNameAfterUnderscoreSplit(string reportFullPath)
 | |
|     {
 | |
|         string result;
 | |
|         string[] segments = Path.GetFileNameWithoutExtension(reportFullPath).Split('_');
 | |
|         if (segments.Length <= 2)
 | |
|             result = segments[0];
 | |
|         else
 | |
|             result = string.Concat(segments[0], segments[2]);
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     internal string[] GetInProcessDirectory(string jobIdDirectory)
 | |
|     {
 | |
|         List<string> results = new();
 | |
|         if (!_IsEAFHosted)
 | |
|             results = new string[] { jobIdDirectory }.ToList();
 | |
|         else
 | |
|         {
 | |
|             string[] files;
 | |
|             string logisticsSequence = _Logistics.Sequence.ToString();
 | |
|             string[] directories = Directory.GetDirectories(jobIdDirectory, $"*{logisticsSequence}*", SearchOption.TopDirectoryOnly);
 | |
|             foreach (string directory in directories)
 | |
|             {
 | |
|                 files = Directory.GetFiles(directory, "*", SearchOption.TopDirectoryOnly);
 | |
|                 if (files.Length == 0)
 | |
|                     continue;
 | |
|                 results.Add(directory);
 | |
|             }
 | |
|         }
 | |
|         if ((results is null) || results.Count != 1)
 | |
|             throw new Exception("Didn't find directory by logistics sequence");
 | |
|         return results.ToArray();
 | |
|     }
 | |
| 
 | |
|     protected static string[] GetMatches(FileConnectorConfiguration fileConnectorConfiguration)
 | |
|     {
 | |
|         string[] segments;
 | |
|         string[] results = null;
 | |
|         foreach (string subSourceFileFilter in fileConnectorConfiguration.SourceFileFilters)
 | |
|         {
 | |
|             segments = subSourceFileFilter.Split('\\');
 | |
|             if (fileConnectorConfiguration.IncludeSubDirectories.Value)
 | |
|                 results = Directory.GetFiles(fileConnectorConfiguration.SourceFileLocation, segments.Last(), SearchOption.AllDirectories);
 | |
|             else
 | |
|                 results = Directory.GetFiles(fileConnectorConfiguration.SourceFileLocation, segments.Last(), SearchOption.TopDirectoryOnly);
 | |
|             if (results.Length != 0)
 | |
|                 break;
 | |
|         }
 | |
|         return results;
 | |
|     }
 | |
| 
 | |
|     protected static void NestExistingFiles(FileConnectorConfiguration fileConnectorConfiguration)
 | |
|     {
 | |
|         // if (!fileConnectorConfiguration.IncludeSubDirectories.Value && fileConnectorConfiguration.TriggerOnCreated is not null && fileConnectorConfiguration.TriggerOnCreated.Value)
 | |
|         if (!fileConnectorConfiguration.IncludeSubDirectories.Value)
 | |
|         {
 | |
|             string[] matches = GetMatches(fileConnectorConfiguration);
 | |
|             if (matches is not null && matches.Length > 0)
 | |
|             {
 | |
|                 string fileName;
 | |
|                 string nestedDirectory = Path.Combine(fileConnectorConfiguration.SourceFileLocation, DateTime.Now.Ticks.ToString());
 | |
|                 if (!Directory.Exists(nestedDirectory))
 | |
|                     _ = Directory.CreateDirectory(nestedDirectory);
 | |
|                 foreach (string match in matches)
 | |
|                 {
 | |
|                     fileName = Path.GetFileName(match);
 | |
|                     File.Move(match, Path.Combine(nestedDirectory, fileName));
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected static List<Properties.IDescription> GetDuplicatorDescriptions(JsonElement[] jsonElements)
 | |
|     {
 | |
|         List<Properties.IDescription> results = new();
 | |
|         Duplicator.Description description;
 | |
|         JsonSerializerOptions jsonSerializerOptions = new() { NumberHandling = JsonNumberHandling.AllowReadingFromString | JsonNumberHandling.WriteAsString };
 | |
|         foreach (JsonElement jsonElement in jsonElements)
 | |
|         {
 | |
|             if (jsonElement.ValueKind != JsonValueKind.Object)
 | |
|                 throw new Exception();
 | |
|             description = JsonSerializer.Deserialize<Duplicator.Description>(jsonElement.ToString(), jsonSerializerOptions);
 | |
|             results.Add(description);
 | |
|         }
 | |
|         return results;
 | |
|     }
 | |
| 
 | |
|     protected static ModelObjectParameterDefinition[] GetProperties(string cellInstanceConnectionName, IList<ModelObjectParameterDefinition> modelObjectParameters, string propertyNamePrefix)
 | |
|     {
 | |
|         ModelObjectParameterDefinition[] results = (from l in modelObjectParameters where l.Name.StartsWith(propertyNamePrefix) select l).ToArray();
 | |
|         if (results.Length == 0)
 | |
|             throw new Exception(cellInstanceConnectionName);
 | |
|         return results;
 | |
|     }
 | |
| 
 | |
|     protected static ModelObjectParameterDefinition[] GetProperties(string cellInstanceConnectionName, IList<ModelObjectParameterDefinition> modelObjectParameters, string propertyNamePrefix, string propertyNameSuffix)
 | |
|     {
 | |
|         ModelObjectParameterDefinition[] results = (from l in modelObjectParameters where l.Name.StartsWith(propertyNamePrefix) && l.Name.EndsWith(propertyNameSuffix) select l).ToArray();
 | |
|         if (results.Length == 0)
 | |
|             throw new Exception(cellInstanceConnectionName);
 | |
|         return results;
 | |
|     }
 | |
| 
 | |
|     protected void SetFileParameter(string key, string value)
 | |
|     {
 | |
|         if (_FileConnectorConfiguration is null || _FileConnectorConfiguration.TargetFileLocation.Contains(string.Concat("%", key, "%")) || _FileConnectorConfiguration.ErrorTargetFileLocation.Contains(string.Concat("%", key, "%")) || _FileConnectorConfiguration.TargetFileName.Contains(string.Concat("%", key, "%")) || _FileConnectorConfiguration.ErrorTargetFileName.Contains(string.Concat("%", key, "%")))
 | |
|         {
 | |
|             if (_FileParameter.ContainsKey(key))
 | |
|                 _FileParameter[key] = value;
 | |
|             else
 | |
|                 _FileParameter.Add(key, value);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected static void WritePDSF(IFileRead fileRead, JsonElement[] jsonElements)
 | |
|     {
 | |
| #pragma warning disable CA1510
 | |
|         if (fileRead is null)
 | |
|             throw new ArgumentNullException(nameof(fileRead));
 | |
|         if (jsonElements is null)
 | |
|             throw new ArgumentNullException(nameof(jsonElements));
 | |
| #pragma warning restore CA1510
 | |
|     }
 | |
| 
 | |
|     protected void WaitForThread(Thread thread, List<Exception> threadExceptions)
 | |
|     {
 | |
|         if (thread is not null)
 | |
|         {
 | |
|             ThreadState threadState;
 | |
|             for (short i = 0; i < short.MaxValue; i++)
 | |
|             {
 | |
|                 if (thread is null)
 | |
|                     break;
 | |
|                 else
 | |
|                 {
 | |
|                     threadState = thread.ThreadState;
 | |
|                     if (threadState is not ThreadState.Running and not ThreadState.WaitSleepJoin)
 | |
|                         break;
 | |
|                 }
 | |
|                 Thread.Sleep(500);
 | |
|             }
 | |
|             lock (threadExceptions)
 | |
|             {
 | |
|                 if (threadExceptions.Count != 0)
 | |
|                 {
 | |
|                     foreach (Exception item in threadExceptions)
 | |
|                         _Log.Error(string.Concat(item.Message, Environment.NewLine, Environment.NewLine, item.StackTrace));
 | |
|                     Exception exception = threadExceptions[0];
 | |
|                     threadExceptions.Clear();
 | |
|                     throw exception;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected void Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults)
 | |
|     {
 | |
|         if (!_IsEAFHosted)
 | |
|         {
 | |
|             string to;
 | |
|             if (!_FileConnectorConfiguration.TargetFileLocation.EndsWith(Path.DirectorySeparatorChar.ToString()))
 | |
|                 to = _FileConnectorConfiguration.TargetFileLocation;
 | |
|             else
 | |
|                 to = Path.GetDirectoryName(_FileConnectorConfiguration.TargetFileLocation);
 | |
|             foreach (KeyValuePair<string, string> keyValuePair in _FileParameter)
 | |
|                 to = to.Replace(string.Concat('%', keyValuePair.Key, '%'), keyValuePair.Value);
 | |
|             if (to.Contains('%'))
 | |
|                 _Log.Debug("Can't debug without EAF Hosting");
 | |
|             else
 | |
|                 _ = Move(extractResults, to, _FileConnectorConfiguration.SourceFileLocation, resolvedFileLocation: string.Empty, exception: null);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected string[] Move(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, string to, string from, string resolvedFileLocation, Exception exception)
 | |
|     {
 | |
|         string[] results;
 | |
|         bool isErrorFile = exception is not null;
 | |
|         if (!to.EndsWith(@"\"))
 | |
|             _ = string.Concat(to, @"\");
 | |
|         if (!isErrorFile)
 | |
|             results = Array.Empty<string>();
 | |
|         else
 | |
|         {
 | |
|             results = new string[] { _Logistics.Sequence.ToString(), _Logistics.ReportFullPath, from, resolvedFileLocation, to, string.Empty, string.Empty, exception.Message, string.Empty, string.Empty, exception.StackTrace };
 | |
|             if (!_IsDuplicator)
 | |
|                 WriteAllLines(to, results);
 | |
|         }
 | |
|         if (extractResults is not null && extractResults.Item4 is not null && extractResults.Item4.Count != 0)
 | |
|         {
 | |
|             string itemFile;
 | |
|             List<string> directories = new();
 | |
|             foreach (FileInfo sourceFile in extractResults.Item4)
 | |
|             {
 | |
|                 if (sourceFile.FullName != _Logistics.ReportFullPath)
 | |
|                 {
 | |
|                     itemFile = sourceFile.FullName.Replace(from, to);
 | |
|                     Shared1880(itemFile, directories, sourceFile, isErrorFile);
 | |
|                 }
 | |
|                 else if (!isErrorFile && _Logistics is not null)
 | |
|                     Shared1811(to, sourceFile);
 | |
|             }
 | |
|             Shared0231(directories);
 | |
|         }
 | |
|         return results;
 | |
|     }
 | |
| 
 | |
|     private void WriteAllLines(string to, string[] exceptionLines)
 | |
|     {
 | |
|         string fileName = string.Concat(to, @"\readme.txt");
 | |
|         try
 | |
|         {
 | |
|             if (!Directory.Exists(to))
 | |
|                 _ = Directory.CreateDirectory(to);
 | |
|             File.WriteAllLines(fileName, exceptionLines);
 | |
|         }
 | |
|         catch (Exception ex) { _Log.Error(ex.Message); }
 | |
|     }
 | |
| 
 | |
|     private void Shared1880(string itemFile, List<string> directories, FileInfo sourceFile, bool isErrorFile)
 | |
|     {
 | |
|         string itemDirectory;
 | |
|         directories.Add(Path.GetDirectoryName(sourceFile.FullName));
 | |
|         itemDirectory = Path.GetDirectoryName(itemFile);
 | |
|         FileConnectorConfiguration.PostProcessingModeEnum processingModeEnum;
 | |
|         if (!isErrorFile)
 | |
|             processingModeEnum = _FileConnectorConfiguration.PostProcessingMode.Value;
 | |
|         else
 | |
|             processingModeEnum = _FileConnectorConfiguration.ErrorPostProcessingMode.Value;
 | |
|         if (processingModeEnum != FileConnectorConfiguration.PostProcessingModeEnum.Delete && !Directory.Exists(itemDirectory))
 | |
|         {
 | |
|             _ = Directory.CreateDirectory(itemDirectory);
 | |
|             FileInfo fileInfo = new(_Logistics.ReportFullPath);
 | |
|             Directory.SetCreationTime(itemDirectory, fileInfo.LastWriteTime);
 | |
|         }
 | |
|         if (_IsEAFHosted)
 | |
|         {
 | |
|             switch (processingModeEnum)
 | |
|             {
 | |
|                 case FileConnectorConfiguration.PostProcessingModeEnum.Move:
 | |
|                     File.Move(sourceFile.FullName, itemFile);
 | |
|                     break;
 | |
|                 case FileConnectorConfiguration.PostProcessingModeEnum.Copy:
 | |
|                     File.Copy(sourceFile.FullName, itemFile);
 | |
|                     break;
 | |
|                 case FileConnectorConfiguration.PostProcessingModeEnum.Delete:
 | |
|                     File.Delete(sourceFile.FullName);
 | |
|                     break;
 | |
|                 case FileConnectorConfiguration.PostProcessingModeEnum.None:
 | |
|                     File.Move(sourceFile.FullName, itemFile);
 | |
|                     break;
 | |
|                 default:
 | |
|                     throw new Exception();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void Shared1811(string to, FileInfo sourceFile)
 | |
|     {
 | |
|         if (!_IsDuplicator && _FileConnectorConfiguration.SourceFileFilter != "*" && sourceFile.Exists && sourceFile.Length < _MinFileLength)
 | |
|         {
 | |
|             string directoryName = Path.GetFileName(to);
 | |
|             string jobIdDirectory = GetJobIdDirectory(to);
 | |
|             DateTime dateTime = DateTime.Now.AddMinutes(-15);
 | |
|             string day = $"{_Logistics.DateTimeFromSequence:yyyy-MM-dd}";
 | |
|             string weekOfYear = _Calendar.GetWeekOfYear(_Logistics.DateTimeFromSequence, CalendarWeekRule.FirstDay, DayOfWeek.Sunday).ToString("00");
 | |
|             string weekDirectory = $"{_Logistics.DateTimeFromSequence:yyyy}_Week_{weekOfYear}";
 | |
|             string destinationDirectory = Path.Combine(jobIdDirectory, "_ Ignore 100 bytes", weekDirectory, day, directoryName);
 | |
|             if (!Directory.Exists(destinationDirectory))
 | |
|                 _ = Directory.CreateDirectory(destinationDirectory);
 | |
|             File.Move(sourceFile.FullName, string.Concat(destinationDirectory, @"\", sourceFile.Name));
 | |
|             try
 | |
|             {
 | |
|                 string[] checkDirectories = Directory.GetDirectories(jobIdDirectory, "*", SearchOption.TopDirectoryOnly);
 | |
|                 foreach (string checkDirectory in checkDirectories)
 | |
|                 {
 | |
|                     if (!checkDirectory.Contains('_'))
 | |
|                         continue;
 | |
|                     if (Directory.GetDirectories(checkDirectory, "*", SearchOption.TopDirectoryOnly).Length != 0)
 | |
|                         continue;
 | |
|                     if (Directory.GetFiles(checkDirectory, "*", SearchOption.TopDirectoryOnly).Length != 0)
 | |
|                         continue;
 | |
|                     if (Directory.GetDirectories(checkDirectory, "*", SearchOption.AllDirectories).Length != 0)
 | |
|                         continue;
 | |
|                     if (Directory.GetFiles(checkDirectory, "*", SearchOption.AllDirectories).Length != 0)
 | |
|                         continue;
 | |
|                     if (new DirectoryInfo(checkDirectory).CreationTime > dateTime)
 | |
|                         continue;
 | |
|                     Directory.Delete(checkDirectory, recursive: false);
 | |
|                 }
 | |
|             }
 | |
|             catch (Exception) { throw; }
 | |
|             DeleteEmptyTopDirectories(jobIdDirectory);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private string GetJobIdDirectory(string path)
 | |
|     {
 | |
|         string result;
 | |
|         List<string> directoryNames = GetDirectoryNames(path);
 | |
|         if (!directoryNames.Contains(_Logistics.JobID))
 | |
|             result = Path.GetDirectoryName(path);
 | |
|         else
 | |
|         {
 | |
|             result = string.Empty;
 | |
|             foreach (string directoryName in directoryNames)
 | |
|             {
 | |
|                 result = Path.Combine(result, directoryName);
 | |
|                 if (directoryName == _Logistics.JobID)
 | |
|                     break;
 | |
|             }
 | |
|         }
 | |
|         return result;
 | |
|     }
 | |
| 
 | |
|     private static void DeleteEmptyTopDirectories(string rootDirectory)
 | |
|     {
 | |
|         if (Directory.Exists(rootDirectory))
 | |
|         {
 | |
|             string[] files;
 | |
|             string[] directories;
 | |
|             string[] subDirectories = Directory.GetDirectories(rootDirectory, "*", SearchOption.TopDirectoryOnly);
 | |
|             foreach (string subDirectory in subDirectories)
 | |
|             {
 | |
|                 files = Directory.GetFiles(subDirectory, "*", SearchOption.AllDirectories);
 | |
|                 if (files.Length > 0)
 | |
|                     continue;
 | |
|                 directories = Directory.GetDirectories(subDirectory, "*", SearchOption.TopDirectoryOnly);
 | |
|                 if (directories.Length > 0)
 | |
|                     continue;
 | |
|                 try
 | |
|                 { Directory.Delete(subDirectory); }
 | |
|                 catch (UnauthorizedAccessException)
 | |
|                 {
 | |
|                     new DirectoryInfo(subDirectory).Attributes = FileAttributes.Normal;
 | |
|                     Directory.Delete(subDirectory);
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     private void Shared0231(List<string> directories)
 | |
|     {
 | |
|         if (_FileConnectorConfiguration.PostProcessingMode != FileConnectorConfiguration.PostProcessingModeEnum.Copy)
 | |
|         {
 | |
|             foreach (string directory in (from l in directories orderby l.Split('\\').Length descending select l).Distinct())
 | |
|             {
 | |
|                 if (Directory.Exists(directory) && Directory.GetFiles(directory).Length == 0)
 | |
|                     Directory.Delete(directory);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     protected void SetFileParameterLotID(string value, bool includeLogisticsSequence = true)
 | |
|     {
 | |
|         string key;
 | |
|         if (!includeLogisticsSequence)
 | |
|             key = "LotID";
 | |
|         else
 | |
|         {
 | |
|             key = "LotIDWithLogisticsSequence";
 | |
|             value = string.Concat(value, "_", _Logistics.Sequence, "_", DateTime.Now.Ticks - _Logistics.Sequence);
 | |
|         }
 | |
|         SetFileParameter(key, value);
 | |
|     }
 | |
| 
 | |
|     protected void SetFileParameterLotIDToLogisticsMID(bool includeLogisticsSequence = true)
 | |
|     {
 | |
|         string key;
 | |
|         if (!includeLogisticsSequence)
 | |
|             key = "LotID";
 | |
|         else
 | |
|             key = "LotIDWithLogisticsSequence";
 | |
|         string value = string.Concat(_Logistics.MID, "_", _Logistics.Sequence, "_", DateTime.Now.Ticks - _Logistics.Sequence);
 | |
|         SetFileParameter(key, value);
 | |
|     }
 | |
| 
 | |
|     protected Tuple<string, Test[], JsonElement[], List<FileInfo>> ReExtract(IFileRead fileRead, List<string> headerNames, Dictionary<string, string> keyValuePairs)
 | |
|     {
 | |
|         Tuple<string, Test[], JsonElement[], List<FileInfo>> results;
 | |
|         if (!Directory.Exists(_FileConnectorConfiguration.SourceFileLocation))
 | |
|             results = null;
 | |
|         else
 | |
|         {
 | |
|             string[] matches = GetMatches(_FileConnectorConfiguration);
 | |
|             if (matches is null || matches.Length == 0)
 | |
|                 results = null;
 | |
|             else
 | |
|             {
 | |
|                 _ReportFullPath = matches[0];
 | |
|                 results = fileRead.GetExtractResult(_ReportFullPath, _EventName);
 | |
|                 if (!_IsEAFHosted)
 | |
|                     TriggerEvents(results, headerNames, keyValuePairs);
 | |
|             }
 | |
|         }
 | |
|         return results;
 | |
|     }
 | |
| 
 | |
|     protected void TriggerEvents(Tuple<string, Test[], JsonElement[], List<FileInfo>> extractResults, List<string> headerNames, Dictionary<string, string> keyValuePairs)
 | |
|     {
 | |
|         object value;
 | |
|         string segments;
 | |
|         string description;
 | |
|         List<object[]> list;
 | |
|         for (int i = 0; i < extractResults.Item3.Length; i++)
 | |
|         {
 | |
|             _Log.Debug(string.Concat("TriggerEvent - {", _Logistics.ReportFullPath, "} ", i, " of ", extractResults.Item3.Length));
 | |
|             foreach (JsonProperty jsonProperty in extractResults.Item3[i].EnumerateObject())
 | |
|             {
 | |
|                 if (jsonProperty.Value.ValueKind != JsonValueKind.String || !keyValuePairs.TryGetValue(jsonProperty.Name, out segments))
 | |
|                     description = string.Empty;
 | |
|                 else
 | |
|                     description = segments.Split('|')[0];
 | |
|                 if (!_UseCyclicalForDescription || headerNames.Contains(jsonProperty.Name))
 | |
|                     value = jsonProperty.Value.ToString();
 | |
|                 else
 | |
|                 {
 | |
|                     list = new List<object[]>();
 | |
|                     for (int z = 0; z < extractResults.Item3.Length; z++)
 | |
|                         list.Add(new object[] { z, extractResults.Item3[z].GetProperty(jsonProperty.Name).ToString() });
 | |
|                     value = list;
 | |
|                 }
 | |
|             }
 | |
|             if (_UseCyclicalForDescription)
 | |
|                 break;
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| // 2025-03-25 -> Shared - FileRead |