file-folder-helper/ADO2024/PI1/Helper-2024-01-06.cs
2024-10-19 09:32:22 -07:00

252 lines
10 KiB
C#

using Microsoft.Extensions.Logging;
using System.Collections.ObjectModel;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Folder_Helper.ADO2024.PI1;
internal static partial class Helper20240106
{
private record Host([property: JsonPropertyName("a")] string? Id,
[property: JsonPropertyName("b")] string? Colon,
[property: JsonPropertyName("c")] string? Hyphen,
[property: JsonPropertyName("d")] string? Line,
[property: JsonPropertyName("e")] string? Count,
[property: JsonPropertyName("f")] string? Segments,
[property: JsonPropertyName("g")] string? Type,
[property: JsonPropertyName("h")] string? Device,
[property: JsonPropertyName("i")] string? Name,
[property: JsonPropertyName("j")] string? Location);
[JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
[JsonSerializable(typeof(Host[]))]
private partial class HostCollectionSourceGenerationContext : JsonSerializerContext
{
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Dictionary<string, Dictionary<string, string>>))]
private partial class DictionaryDictionarySourceGenerationContext : JsonSerializerContext
{
}
private record Record(string Key, Dictionary<string, string> KeyValuePairs);
private static Dictionary<string, Dictionary<string, string>> GetKeyValuePairs(List<Record> collection, bool replaceFound)
{
Dictionary<string, Dictionary<string, string>> results = [];
if (replaceFound)
{
foreach ((string key, Dictionary<string, string> keyValuePairs) in collection)
_ = results.TryAdd(key, keyValuePairs);
}
else
{
foreach ((string key, Dictionary<string, string> keyValuePairs) in collection.OrderBy(l => l.Key))
_ = results.TryAdd(key, keyValuePairs);
}
return results;
}
private static Dictionary<int, Host> GetHosts(string jsonl)
{
Dictionary<int, Host> results = [];
int id;
string json = $"[{File.ReadAllText(jsonl).Replace("\r\n", ",")}]";
Host[] hosts = JsonSerializer.Deserialize(json, HostCollectionSourceGenerationContext.Default.HostArray) ?? throw new NullReferenceException(nameof(json));
foreach (Host host in hosts)
{
if (host.Id is null)
continue;
if (host.Hyphen is not null and nameof(host.Hyphen))
continue;
if (!int.TryParse(host.Id, out id))
throw new NotSupportedException($"{host.Id} is not a number");
if (results.ContainsKey(id))
throw new NotSupportedException($"Id {id} is not unique!");
results.Add(id, host);
}
return results;
}
private static int? GetHeaderLine(string[] lines)
{
int? headerLine = null;
for (int i = 0; i < lines.Length - 1; i++)
{
if (!lines[i].Contains('\t'))
continue;
headerLine = i;
}
return headerLine;
}
private static Dictionary<string, Dictionary<string, string>> GetKeyValuePairs(int keyIndex, int keyLength, string replace, string[] headers, string[] lines, int headerLine)
{
Dictionary<string, Dictionary<string, string>> results;
string? key;
Record record;
bool replaceFound = false;
List<Record> collection = [];
Dictionary<string, string> keyValuePairs;
for (int i = headerLine + 1; i < lines.Length; i++)
{
key = null;
keyValuePairs = [];
for (int j = 0; j < headers.Length; j++)
{
if (j > 0)
i++;
if (lines.Length <= i)
{
keyValuePairs.Clear();
break;
}
if (j == keyIndex)
{
key = lines[i];
if (key.Length != keyLength)
{
keyValuePairs.Clear();
break;
}
}
if (lines[i] != replace)
_ = keyValuePairs.TryAdd(headers[j], lines[i]);
else
{
if (!replaceFound)
replaceFound = true;
_ = keyValuePairs.TryAdd(headers[j], lines[i]);
j++;
_ = keyValuePairs.TryAdd(headers[j], lines[i]);
}
}
if (keyValuePairs.Count != headers.Length)
continue;
key ??= "-";
record = new(key, keyValuePairs);
collection.Add(record);
}
results = GetKeyValuePairs(collection, replaceFound);
return results;
}
private static ReadOnlyCollection<string> GetIpAddressAndVerify(ILogger<Worker> logger, string key, Dictionary<string, Dictionary<string, string>> keyValuePairs, Dictionary<int, Host> hosts, string filter)
{
List<string> results = [];
int id;
bool found;
Host? host;
string text;
string? ipAddress;
StringBuilder stringBuilder = new();
foreach (KeyValuePair<string, Dictionary<string, string>> keyValuePair in keyValuePairs)
{
found = false;
if (keyValuePair.Key.StartsWith(filter))
continue;
if (!keyValuePair.Value.TryGetValue(key, out ipAddress))
throw new NotSupportedException($"{key} isn't present!");
if (ipAddress == "0.0.0.0")
continue;
results.Add(ipAddress);
_ = stringBuilder.Clear();
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
_ = stringBuilder.AppendLine(keyValue.Value);
text = stringBuilder.ToString();
if (!int.TryParse(ipAddress.Split('.')[^1], out id))
throw new NotSupportedException($"{ipAddress} isn't valid!");
if (!hosts.TryGetValue(id, out host))
throw new NotSupportedException($"{id} isn't valid!");
foreach (KeyValuePair<string, string> keyValue in keyValuePair.Value)
{
if (keyValue.Value != host.Hyphen)
continue;
found = true;
}
if (!found)
throw new NotSupportedException($"{host}{Environment.NewLine}{text} doesn't match!");
if (text.Contains("Unknown", StringComparison.InvariantCultureIgnoreCase))
logger.LogWarning($"{text} contains Unknown and should be {host.Device}!");
}
return new(results);
}
private static void WriteAppendToHostConfFile(FileInfo fileInfo, string hostConfFile, Dictionary<int, Host> hosts, ReadOnlyCollection<string> ipAddress)
{
int id;
Host host;
string ip;
string line;
List<int> distinct = [];
List<string> lines = [$"# {fileInfo.LastWriteTime.Ticks}"];
string firstSegmentsOfIpAddress = string.Join('.', ipAddress[0].Split('.').Take(3));
foreach (KeyValuePair<int, Host> keyValuePair in hosts)
{
host = keyValuePair.Value;
if (host.Hyphen is not null and nameof(host.Hyphen))
continue;
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Hyphen.Length != 17)
throw new NotSupportedException($"{host.Id} is Null or not 17");
if (!int.TryParse(host.Id, out id))
throw new NotSupportedException($"{host.Id} is not a number");
if (distinct.Contains(id))
throw new NotSupportedException($"{id} is not distinct!");
distinct.Add(id);
ip = ipAddress.Contains($"{firstSegmentsOfIpAddress}.{id}") ? $"{firstSegmentsOfIpAddress}.{id}" : $"# {firstSegmentsOfIpAddress}.{id}";
line = $"{ip} {host.Name} # https://{host.Name} | {host.Colon} | {host.Hyphen} | {host.Device} |";
lines.Add(line);
}
lines.Add($"# {fileInfo.LastWriteTime.Ticks}");
File.AppendAllLines(hostConfFile, lines);
}
internal static void TextToJson(ILogger<Worker> logger, List<string> args)
{
string json;
string[] lines;
int? headerLine;
FileInfo fileInfo;
string key = args[7];
string filter = args[10];
string replace = args[5];
int keyIndex = int.Parse(args[3]);
int keyLength = int.Parse(args[4]);
ReadOnlyCollection<string> ipAddress;
string[] headers = args[6].Split(',');
string jsonl = Path.Combine(args[0], args[8]);
string hostConfFile = Path.Combine(args[0], args[9]);
string[] txtFiles = Directory.GetFiles(args[0], args[2]);
Dictionary<string, Dictionary<string, string>> keyValuePairs;
if (!File.Exists(jsonl))
throw new NotSupportedException($"{args[8]} doesn't exist!");
Dictionary<int, Host> hosts = GetHosts(jsonl);
if (hosts.Count == 0)
throw new NotSupportedException($"{args[8]} isn't valid!");
foreach (string txtFile in txtFiles)
{
lines = File.ReadAllLines(txtFile);
if (lines.Length == 0)
continue;
headerLine = GetHeaderLine(lines);
if (headerLine is null)
continue;
fileInfo = new(txtFile);
keyValuePairs = GetKeyValuePairs(keyIndex, keyLength, replace, headers, lines, headerLine.Value);
if (keyValuePairs.Count == 0)
continue;
ipAddress = GetIpAddressAndVerify(logger, key, keyValuePairs, hosts, filter);
if (ipAddress.Count == 0)
continue;
json = JsonSerializer.Serialize(keyValuePairs, DictionaryDictionarySourceGenerationContext.Default.DictionaryStringDictionaryStringString);
logger.LogInformation("Writing output file...");
File.WriteAllText($"{fileInfo.FullName}-{fileInfo.LastWriteTime.Ticks}.json", json);
WriteAppendToHostConfFile(fileInfo, hostConfFile, hosts, ipAddress);
File.WriteAllLines(txtFile, [string.Empty, string.Empty, lines[^1]]);
}
}
}