mirror of
https://github.com/Theodor-Springmann-Stiftung/hamann-ausgabe-core.git
synced 2025-10-30 01:35:32 +00:00
Setup Git Repository Parsing
This commit is contained in:
138
HaWeb/XMLTests/BackgroundServices.cs
Normal file
138
HaWeb/XMLTests/BackgroundServices.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
namespace HaWeb.BackgroundTask;
|
||||
|
||||
using System.Threading.Channels;
|
||||
|
||||
public interface IBackgroundTaskQueue {
|
||||
ValueTask QueueBackgroundWorkItemAsync(Func<CancellationToken, ValueTask> workItem);
|
||||
ValueTask<Func<CancellationToken, ValueTask>> DequeueAsync(CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
public interface IMonitorLoop {
|
||||
public void StartMonitorLoop();
|
||||
}
|
||||
|
||||
public class BackgroundTaskQueue : IBackgroundTaskQueue {
|
||||
private readonly Channel<Func<CancellationToken, ValueTask>> _queue;
|
||||
|
||||
public BackgroundTaskQueue(int capacity) {
|
||||
var options = new BoundedChannelOptions(capacity) {
|
||||
FullMode = BoundedChannelFullMode.Wait
|
||||
};
|
||||
_queue = Channel.CreateBounded<Func<CancellationToken, ValueTask>>(options);
|
||||
}
|
||||
|
||||
public async ValueTask QueueBackgroundWorkItemAsync(Func<CancellationToken, ValueTask> workItem) {
|
||||
if (workItem == null) {
|
||||
throw new ArgumentNullException(nameof(workItem));
|
||||
}
|
||||
await _queue.Writer.WriteAsync(workItem);
|
||||
}
|
||||
|
||||
public async ValueTask<Func<CancellationToken, ValueTask>> DequeueAsync(
|
||||
CancellationToken cancellationToken
|
||||
) {
|
||||
var workItem = await _queue.Reader.ReadAsync(cancellationToken);
|
||||
return workItem;
|
||||
}
|
||||
}
|
||||
|
||||
public class QueuedHostedService : BackgroundService {
|
||||
private readonly ILogger<QueuedHostedService> _logger;
|
||||
public IBackgroundTaskQueue TaskQueue { get; }
|
||||
|
||||
public QueuedHostedService(IBackgroundTaskQueue taskQueue, ILogger<QueuedHostedService> logger) {
|
||||
TaskQueue = taskQueue;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
|
||||
await BackgroundProcessing(stoppingToken);
|
||||
}
|
||||
|
||||
private async Task BackgroundProcessing(CancellationToken stoppingToken) {
|
||||
while (!stoppingToken.IsCancellationRequested) {
|
||||
var workItem = await TaskQueue.DequeueAsync(stoppingToken);
|
||||
|
||||
try {
|
||||
await workItem(stoppingToken);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
_logger.LogError(ex, "Error occurred executing {WorkItem}.", nameof(workItem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task StopAsync(CancellationToken stoppingToken) {
|
||||
_logger.LogInformation("Queued Hosted Service is stopping.");
|
||||
|
||||
await base.StopAsync(stoppingToken);
|
||||
}
|
||||
}
|
||||
|
||||
public class MonitorLoop : IMonitorLoop {
|
||||
private readonly IBackgroundTaskQueue _taskQueue;
|
||||
private readonly ILogger _logger;
|
||||
private readonly CancellationToken _cancellationToken;
|
||||
|
||||
public MonitorLoop(
|
||||
IBackgroundTaskQueue taskQueue,
|
||||
ILogger<MonitorLoop> logger,
|
||||
IHostApplicationLifetime applicationLifetime
|
||||
) {
|
||||
_taskQueue = taskQueue;
|
||||
_logger = logger;
|
||||
_cancellationToken = applicationLifetime.ApplicationStopping;
|
||||
}
|
||||
|
||||
public void StartMonitorLoop() {
|
||||
_logger.LogInformation("MonitorAsync Loop is starting.");
|
||||
|
||||
// Run a console user input loop in a background thread
|
||||
Task.Run(async () => await MonitorAsync());
|
||||
}
|
||||
|
||||
private async ValueTask MonitorAsync() {
|
||||
while (!_cancellationToken.IsCancellationRequested) {
|
||||
var keyStroke = Console.ReadKey();
|
||||
|
||||
if (keyStroke.Key == ConsoleKey.W) {
|
||||
// Enqueue a background work item
|
||||
await _taskQueue.QueueBackgroundWorkItemAsync(BuildWorkItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask BuildWorkItem(CancellationToken token) {
|
||||
// Simulate three 5-second tasks to complete
|
||||
// for each enqueued work item
|
||||
|
||||
int delayLoop = 0;
|
||||
var guid = Guid.NewGuid().ToString();
|
||||
|
||||
_logger.LogInformation("Queued Background Task {Guid} is starting.", guid);
|
||||
|
||||
while (!token.IsCancellationRequested && delayLoop < 3) {
|
||||
try {
|
||||
await Task.Delay(TimeSpan.FromSeconds(5), token);
|
||||
}
|
||||
catch (OperationCanceledException) {
|
||||
// Prevent throwing if the Delay is cancelled
|
||||
}
|
||||
|
||||
delayLoop++;
|
||||
|
||||
_logger.LogInformation(
|
||||
"Queued Background Task {Guid} is running. " + "{DelayLoop}/3",
|
||||
guid,
|
||||
delayLoop
|
||||
);
|
||||
}
|
||||
|
||||
if (delayLoop == 3) {
|
||||
_logger.LogInformation("Queued Background Task {Guid} is complete.", guid);
|
||||
}
|
||||
else {
|
||||
_logger.LogInformation("Queued Background Task {Guid} was cancelled.", guid);
|
||||
}
|
||||
}
|
||||
}
|
||||
6
HaWeb/XMLTests/HamannXPath.cs
Normal file
6
HaWeb/XMLTests/HamannXPath.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace HaWeb.XMLTests;
|
||||
|
||||
public class HamannXPath {
|
||||
public string[]? Documents { get; set; }
|
||||
public string? XPath { get; set; }
|
||||
}
|
||||
@@ -4,8 +4,8 @@ using System.Xml.Linq;
|
||||
|
||||
public interface ICollectionRule {
|
||||
public string Name { get; }
|
||||
public string[] Bases { get; }
|
||||
public string[] Backlinks { get; }
|
||||
public HamannXPath[] Bases { get; }
|
||||
public HamannXPath[] Backlinks { get; }
|
||||
public IEnumerable<(string, XElement, XMLRootDocument)> GenerateIdentificationStrings(IEnumerable<(XElement, XMLRootDocument)> List);
|
||||
public IEnumerable<(string, XElement, XMLRootDocument, bool)> GenerateBacklinkString(IEnumerable<(XElement, XMLRootDocument)> List);
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using HaWeb.XMLParser;
|
||||
|
||||
namespace HaWeb.XMLTests;
|
||||
|
||||
public interface IXMLTestService {
|
||||
@@ -5,5 +7,5 @@ public interface IXMLTestService {
|
||||
public Dictionary<string, INodeRule>? Ruleset { get; }
|
||||
public Dictionary<string, ICollectionRule>? CollectionRuleset { get; }
|
||||
|
||||
public void Test();
|
||||
public void Test(IXMLInteractionService _XMLService);
|
||||
}
|
||||
@@ -2,8 +2,8 @@ namespace HaWeb.XMLTests;
|
||||
|
||||
public interface INodeRule {
|
||||
public string Name { get; }
|
||||
public string XPath { get; }
|
||||
public HamannXPath XPath { get; }
|
||||
public string? uniquenessAttribute { get; }
|
||||
public List<(string LinkAttribute, string RemoteElement, string RemoteAttribute)>? References { get; }
|
||||
public List<(string LinkAttribute, HamannXPath RemoteElement, string RemoteAttribute)>? References { get; }
|
||||
public string[]? Attributes { get; }
|
||||
}
|
||||
@@ -2,12 +2,9 @@ namespace HaWeb.XMLTests;
|
||||
using HaWeb.XMLParser;
|
||||
|
||||
public class XMLTestService : IXMLTestService {
|
||||
private IXMLService _XMLService;
|
||||
public Dictionary<string, INodeRule>? Ruleset { get; private set; }
|
||||
public Dictionary<string, ICollectionRule>? CollectionRuleset { get; private set; }
|
||||
public XMLTestService(IXMLService xmlService) {
|
||||
_XMLService = xmlService;
|
||||
|
||||
public XMLTestService() {
|
||||
var roottypes = _GetAllTypesThatImplementInterface<INodeRule>().ToList();
|
||||
roottypes.ForEach( x => {
|
||||
if (this.Ruleset == null) this.Ruleset = new Dictionary<string, INodeRule>();
|
||||
@@ -23,17 +20,10 @@ public class XMLTestService : IXMLTestService {
|
||||
});
|
||||
}
|
||||
|
||||
public void Test() {
|
||||
var docs = _XMLService.GetUsedDictionary();
|
||||
public void Test(IXMLInteractionService _XMLService) {
|
||||
var docs = _XMLService.GetLoaded();
|
||||
if (docs == null) return;
|
||||
foreach (var d in docs.Values) {
|
||||
var fl = d.GetFileList();
|
||||
if (fl == null) continue;
|
||||
foreach (var v in fl) {
|
||||
v.ResetLog();
|
||||
}
|
||||
}
|
||||
var tester = new XMLTester(this, _XMLService.GetUsedDictionary());
|
||||
var tester = new XMLTester(this, docs);
|
||||
tester.Test();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ public class XMLTester {
|
||||
|
||||
public void Test() {
|
||||
if (_Ruleset == null) return;
|
||||
_IDs = new System.Collections.Generic.Dictionary<string, HashSet<string>>();
|
||||
_IDs = new Dictionary<string, HashSet<string>>();
|
||||
foreach (var rule in _Ruleset) {
|
||||
buildIDs(rule.Value);
|
||||
checkRequiredAttributes(rule.Value);
|
||||
@@ -42,6 +42,7 @@ public class XMLTester {
|
||||
checkReferences(collectionrule.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkReferences(INodeRule rule) {
|
||||
if (rule.References == null || !rule.References.Any()) return;
|
||||
var elements = GetEvaluateXPath(rule.XPath);
|
||||
@@ -49,11 +50,11 @@ public class XMLTester {
|
||||
foreach (var e in elements) {
|
||||
foreach (var r in rule.References) {
|
||||
var hasattr = checkAttribute(e.Item1, r.LinkAttribute, e.Item2, false);
|
||||
var keyname = r.RemoteElement + "-" + r.RemoteAttribute;
|
||||
var keyname = r.RemoteElement.XPath + "-" + r.RemoteAttribute;
|
||||
if (_IDs != null && _IDs.ContainsKey(keyname) && hasattr) {
|
||||
var val = e.Item1.Attribute(r.LinkAttribute)!.Value;
|
||||
if (!_IDs[keyname].Contains(val)) {
|
||||
e.Item2.Log(generateLogMessage(e.Item1) + "Verlinktes Element " + val + " nicht gefunden.");
|
||||
e.Item2.File.Log(generateLogMessage(e.Item1) + "Verlinktes Element " + val + " nicht gefunden.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +69,7 @@ public class XMLTester {
|
||||
if (elemens != null && elemens.Any()) {
|
||||
foreach(var r in rule.GenerateBacklinkString(elemens)) {
|
||||
if (!r.Item4 && !_CollectionIDs[rule.Name].Contains(r.Item1)) {
|
||||
r.Item3.Log(generateLogMessage(r.Item2) + "Verlinktes Element " + r.Item1 + " nicht gefunden.");
|
||||
r.Item3.File.Log(generateLogMessage(r.Item2) + "Verlinktes Element " + r.Item1 + " nicht gefunden.");
|
||||
}
|
||||
if (r.Item4) {
|
||||
var coll = _CollectionIDs[rule.Name];
|
||||
@@ -76,7 +77,7 @@ public class XMLTester {
|
||||
var searchterm = items[0];
|
||||
var found = coll.Where(x => x.StartsWith(searchterm));
|
||||
if (items[0] == "NA" || found == null || !found.Any()) {
|
||||
r.Item3.Log(generateLogMessage(r.Item2) + "Verlinktes Element " + r.Item1 + " nicht gefunden.");
|
||||
r.Item3.File.Log(generateLogMessage(r.Item2) + "Verlinktes Element " + r.Item1 + " nicht gefunden.");
|
||||
} else {
|
||||
for (var i = 1; i < items.Length; i++) {
|
||||
if (items[i] == "NA") break;
|
||||
@@ -84,7 +85,7 @@ public class XMLTester {
|
||||
searchterm = searchterm + "-" + items[i];
|
||||
found = found.Where(x => x.StartsWith(searchterm));
|
||||
if (found == null || !found.Any())
|
||||
r.Item3.Log(generateLogMessage(r.Item2) + "Verlinktes Element " + r.Item1 + " nicht gefunden.");
|
||||
r.Item3.File.Log(generateLogMessage(r.Item2) + "Verlinktes Element " + r.Item1 + " nicht gefunden.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -125,7 +126,7 @@ public class XMLTester {
|
||||
if (elemens != null && elemens.Any()) {
|
||||
foreach (var r in rule.GenerateIdentificationStrings(elemens)) {
|
||||
if (!hs.Add(r.Item1)) {
|
||||
r.Item3.Log(generateLogMessage(r.Item2) + "Brief-Seite-Zeile " + r.Item1 + " mehrdeutig.");
|
||||
r.Item3.File.Log(generateLogMessage(r.Item2) + "Brief-Seite-Zeile " + r.Item1 + " mehrdeutig.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,24 +135,24 @@ public class XMLTester {
|
||||
}
|
||||
}
|
||||
|
||||
private void checkUniqueness(string xpathelement, string attribute) {
|
||||
if (_Documents == null || _IDs == null || _IDs.ContainsKey(xpathelement + "-" + attribute)) return;
|
||||
private void checkUniqueness(HamannXPath xpathelement, string attribute) {
|
||||
if (_Documents == null || _IDs == null || _IDs.ContainsKey(xpathelement.XPath + "-" + attribute)) return;
|
||||
var hs = new HashSet<string>();
|
||||
var elements = GetEvaluateXPath(xpathelement);
|
||||
if (elements != null)
|
||||
foreach (var e in elements) {
|
||||
if (checkAttribute(e.Item1, attribute, e.Item2)) {
|
||||
if (!hs.Add(e.Item1.Attribute(attribute)!.Value)) {
|
||||
e.Item2.Log(generateLogMessage(e.Item1) + "Attributwert " + e.Item1.Attribute(attribute)!.Value + " doppelt.");
|
||||
e.Item2.File.Log(generateLogMessage(e.Item1) + "Attributwert " + e.Item1.Attribute(attribute)!.Value + " doppelt.");
|
||||
}
|
||||
}
|
||||
}
|
||||
_IDs.TryAdd(xpathelement + "-" + attribute, hs);
|
||||
_IDs.TryAdd(xpathelement.XPath + "-" + attribute, hs);
|
||||
}
|
||||
|
||||
private bool checkAttribute(XElement element, string attributename, XMLRootDocument doc, bool log = true) {
|
||||
if (!element.HasAttributes || element.Attribute(attributename) == null) {
|
||||
if (log) doc.Log(generateLogMessage(element) + "Attribut " + attributename + " fehlt.");
|
||||
if (log) doc.File.Log(generateLogMessage(element) + "Attribut " + attributename + " fehlt.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -165,19 +166,21 @@ public class XMLTester {
|
||||
": ";
|
||||
}
|
||||
|
||||
private List<(XElement, XMLRootDocument)>? GetEvaluateXPath(string xpath) {
|
||||
if (_XPathEvaluated.ContainsKey(xpath)) return _XPathEvaluated[xpath];
|
||||
if (!_XPathEvaluated.ContainsKey(xpath)) _XPathEvaluated.Add(xpath, null);
|
||||
if (_Documents == null) return null;
|
||||
// Cache for XPATH evaluation
|
||||
private List<(XElement, XMLRootDocument)>? GetEvaluateXPath(HamannXPath xpath) {
|
||||
if (_Documents == null || xpath == null) return null;
|
||||
if (_XPathEvaluated.ContainsKey(xpath.XPath)) return _XPathEvaluated[xpath.XPath];
|
||||
if (!_XPathEvaluated.ContainsKey(xpath.XPath)) _XPathEvaluated.Add(xpath.XPath, null);
|
||||
foreach (var d in _Documents) {
|
||||
var elements = d.GetElement().XPathSelectElements(xpath).ToList();
|
||||
if (xpath.Documents != null && !xpath.Documents.Contains(d.Prefix)) continue;
|
||||
var elements = d.Element.XPathSelectElements("." + xpath.XPath).ToList();
|
||||
if (elements != null && elements.Any()) {
|
||||
if (_XPathEvaluated[xpath] == null) _XPathEvaluated[xpath] = new List<(XElement, XMLRootDocument)>();
|
||||
if (_XPathEvaluated[xpath.XPath] == null) _XPathEvaluated[xpath.XPath] = new List<(XElement, XMLRootDocument)>();
|
||||
foreach (var res in elements) {
|
||||
_XPathEvaluated[xpath]!.Add((res, d));
|
||||
_XPathEvaluated[xpath.XPath]!.Add((res, d));
|
||||
}
|
||||
}
|
||||
}
|
||||
return _XPathEvaluated[xpath];
|
||||
return _XPathEvaluated[xpath.XPath];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user