mirror of
https://github.com/Theodor-Springmann-Stiftung/hamann-ausgabe-core.git
synced 2025-10-29 09:15:33 +00:00
201 lines
7.6 KiB
C#
201 lines
7.6 KiB
C#
namespace HaWeb.XMLParser;
|
|
using HaWeb.Settings.XMLRoots;
|
|
using System.Xml.Linq;
|
|
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
|
using Microsoft.Extensions.FileProviders;
|
|
using Microsoft.FeatureManagement;
|
|
|
|
public class XMLService : IXMLService {
|
|
private Dictionary<string, List<XMLRootDocument>?>? _availableFilesObj;
|
|
private Dictionary<string, List<XMLRootDocument>?>? _availableFiles {
|
|
get {
|
|
if (_availableFilesObj == null) {
|
|
_availableFilesObj = _GetAvailableFiles();
|
|
AutoDetermineUsed();
|
|
}
|
|
return _availableFilesObj;
|
|
} }
|
|
|
|
private IFileProvider _fileProvider;
|
|
private IFeatureManager _featureManager;
|
|
private Dictionary<string, IXMLRoot>? _Roots;
|
|
|
|
public bool UploadEnabled = false;
|
|
public bool UpdateEnabled = false;
|
|
|
|
public XMLService(IFileProvider provider, IFeatureManager featureManager) {
|
|
_fileProvider = provider;
|
|
_featureManager = featureManager;
|
|
if (provider == null)
|
|
throw new Exception("To Upload Files you need a FileProvider");
|
|
|
|
// Getting all classes which implement IXMLRoot for possible upload endpoints
|
|
var types = _GetAllTypesThatImplementInterface<IXMLRoot>().ToList();
|
|
types.ForEach( x => {
|
|
if (this._Roots == null) this._Roots = new Dictionary<string, IXMLRoot>();
|
|
var instance = (IXMLRoot)Activator.CreateInstance(x)!;
|
|
if (instance != null) this._Roots.Add(instance.Prefix, instance);
|
|
});
|
|
|
|
if (_Roots == null || !_Roots.Any())
|
|
throw new Exception("No classes for upload endpoints were found!");
|
|
}
|
|
|
|
public IXMLRoot? GetRoot(string name) {
|
|
_Roots.TryGetValue(name, out var root);
|
|
return root;
|
|
}
|
|
|
|
public List<IXMLRoot>? GetRoots() => this._Roots == null ? null : this._Roots.Values.ToList();
|
|
|
|
public async Task<List<XMLRootDocument>?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) {
|
|
if (document.Root!.Name != "opus") {
|
|
ModelState.AddModelError("Error", "A valid Hamann-Docuemnt must begin with <opus>");
|
|
return null;
|
|
}
|
|
|
|
List<XMLRootDocument>? res = null;
|
|
if (document.Root != null && _Roots != null) {
|
|
foreach (var (_, root) in _Roots) {
|
|
var elements = root.IsTypeOf(document.Root);
|
|
if (elements != null && elements.Any())
|
|
foreach (var elem in elements) {
|
|
if (res == null) res = new List<XMLRootDocument>();
|
|
res.Add(_createXMLRootDocument(root, elem));
|
|
}
|
|
}
|
|
}
|
|
if (res == null) ModelState.AddModelError("Error", "Kein zum Hamann-Briefe-Projekt passendes XML gefunden.");
|
|
return res;
|
|
}
|
|
|
|
public void UpdateAvailableFiles() {
|
|
_availableFilesObj = _GetAvailableFiles();
|
|
}
|
|
|
|
public void UpdateAvailableFiles(string prefix) {
|
|
if (_availableFilesObj == null) {
|
|
UpdateAvailableFiles();
|
|
return;
|
|
}
|
|
if (_availableFilesObj.ContainsKey(prefix))
|
|
_availableFilesObj.Remove(prefix);
|
|
if (_fileProvider.GetDirectoryContents(prefix).Exists) {
|
|
_availableFilesObj.Add(prefix, _GetAvailableFiles(prefix));
|
|
}
|
|
|
|
AutoDetermineUsed(prefix);
|
|
}
|
|
|
|
public async Task UpdateAvailableFiles(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState) {
|
|
await _setEnabled();
|
|
if (!UploadEnabled) {
|
|
ModelState.AddModelError("Error", "The uploading of files is deactivated");
|
|
return;
|
|
}
|
|
|
|
await _Save(doc, basefilepath, ModelState);
|
|
if (!ModelState.IsValid) return;
|
|
|
|
UpdateAvailableFiles(doc.Prefix);
|
|
}
|
|
|
|
private async Task _Save(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState) {
|
|
var type = doc.Prefix;
|
|
var directory = Path.Combine(basefilepath, type);
|
|
if (!Directory.Exists(directory))
|
|
Directory.CreateDirectory(directory);
|
|
var path = Path.Combine(directory, doc.FileName);
|
|
try {
|
|
using (var targetStream = System.IO.File.Create(path))
|
|
await doc.Save(targetStream, ModelState);
|
|
}
|
|
catch (Exception ex) {
|
|
ModelState.AddModelError("Error", "Speichern der Datei fehlgeschlagen: " + ex.Message);
|
|
return;
|
|
}
|
|
|
|
var info = _fileProvider.GetFileInfo(Path.Combine(doc.Prefix, doc.FileName));
|
|
if (info == null) {
|
|
ModelState.AddModelError("Error", "Auf die neu erstellte Dtaei konnte nicht zugegriffen werden");
|
|
return;
|
|
}
|
|
doc.SetFile(info);
|
|
|
|
UpdateAvailableFiles(type);
|
|
}
|
|
|
|
|
|
private XMLRootDocument _createXMLRootDocument(IXMLRoot Root, XElement element) {
|
|
var doc = new XMLRootDocument(this, Root.Prefix, Root.GenerateIdentificationString(element), element);
|
|
doc.Fields = Root.GenerateFields(doc);
|
|
return doc;
|
|
}
|
|
|
|
private IEnumerable<Type> _GetAllTypesThatImplementInterface<T>()
|
|
{
|
|
return System.Reflection.Assembly.GetExecutingAssembly()
|
|
.GetTypes()
|
|
.Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface);
|
|
}
|
|
|
|
private async Task _setEnabled() {
|
|
if (await _featureManager.IsEnabledAsync(HaWeb.Features.UploadService))
|
|
UploadEnabled = true;
|
|
if (await _featureManager.IsEnabledAsync(HaWeb.Features.UpdateService))
|
|
UpdateEnabled = true;
|
|
}
|
|
|
|
private Dictionary<string, List<XMLRootDocument>?>? _GetAvailableFiles() {
|
|
if (_Roots == null) return null;
|
|
Dictionary<string, List<XMLRootDocument>?>? res = null;
|
|
var dirs = _fileProvider.GetDirectoryContents(string.Empty).Where(x => x.IsDirectory);
|
|
foreach(var dir in dirs) {
|
|
if(_Roots.ContainsKey(dir.Name)) {
|
|
if (res == null) res = new Dictionary<string, List<XMLRootDocument>?>();
|
|
res.Add(dir.Name, _GetAvailableFiles(dir.Name));
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
private List<XMLRootDocument>? _GetAvailableFiles(string prefix) {
|
|
List<XMLRootDocument>? res = null;
|
|
var files = _fileProvider.GetDirectoryContents(prefix).Where(x => !x.IsDirectory && x.Name.StartsWith(prefix) && x.Name.EndsWith(".xml"));
|
|
foreach (var file in files) {
|
|
if (res == null) res = new List<XMLRootDocument>();
|
|
res.Add(new XMLRootDocument(this, file));
|
|
}
|
|
return res;
|
|
}
|
|
|
|
public void AutoDetermineUsed() {
|
|
if (_availableFilesObj == null) return;
|
|
foreach (var (prefix, _) in _availableFilesObj)
|
|
AutoDetermineUsed(prefix);
|
|
}
|
|
|
|
public void AutoDetermineUsed(string prefix) {
|
|
if (_Roots == null || _availableFilesObj == null) return;
|
|
_Roots.TryGetValue(prefix, out var root);
|
|
_availableFilesObj.TryGetValue(prefix, out var files);
|
|
if (files == null || root == null) return;
|
|
|
|
//TODO: Item1
|
|
var lookup = files.ToLookup(x => x.IdentificationString.Item2);
|
|
foreach (var idstring in lookup) {
|
|
var ordered = idstring.OrderBy(x => x.Date);
|
|
ordered.Last().SetUsed(true);
|
|
ordered.Take(ordered.Count() - 1).ToList().ForEach(x => x.SetUsed(false));
|
|
}
|
|
}
|
|
|
|
public Dictionary<string, List<XMLRootDocument>>? GetUsed() {
|
|
if (_availableFiles == null) return null;
|
|
return _availableFiles
|
|
.Where(x => x.Value != null)
|
|
.Select(x => x.Value!.Where(x => x.Used).ToList())
|
|
.Where(x => x.Any())
|
|
.ToDictionary(x => x.First().Prefix);
|
|
}
|
|
} |