Seperation of concerns: Seperated used File Management form Overall FIle Management

This commit is contained in:
schnulller
2022-06-05 15:18:32 +02:00
parent abc27c6d04
commit c95059b2e8
22 changed files with 211 additions and 186 deletions

View File

@@ -21,6 +21,7 @@ namespace HaDocument
private static ILibrary _library; private static ILibrary _library;
public static ILibrary Create(IHaDocumentOptions Settings) { public static ILibrary Create(IHaDocumentOptions Settings) {
Console.WriteLine("PARSING");
SettingsValidator.Validate(Settings); SettingsValidator.Validate(Settings);
_settings = Settings; _settings = Settings;
_createReader(); _createReader();

View File

@@ -8,6 +8,7 @@ using Microsoft.Net.Http.Headers;
using HaWeb.Filters; using HaWeb.Filters;
using HaWeb.FileHelpers; using HaWeb.FileHelpers;
using HaWeb.XMLParser; using HaWeb.XMLParser;
using HaWeb.Models;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Text.Json; using System.Text.Json;
using HaDocument.Interfaces; using HaDocument.Interfaces;
@@ -25,14 +26,16 @@ public class APIController : Controller {
private readonly long _fileSizeLimit; private readonly long _fileSizeLimit;
private readonly string _targetFilePath; private readonly string _targetFilePath;
private readonly IXMLService _xmlService; private readonly IXMLService _xmlService;
private readonly IXMLProvider _xmlProvider;
// Options // Options
private static readonly string[] _permittedExtensions = { ".xml" }; private static readonly string[] _permittedExtensions = { ".xml" };
private static readonly FormOptions _defaultFormOptions = new FormOptions(); private static readonly FormOptions _defaultFormOptions = new FormOptions();
public APIController(IHaDocumentWrappper lib, IReaderService readerService, IXMLService xmlService, IConfiguration config) { public APIController(IHaDocumentWrappper lib, IReaderService readerService, IXMLService xmlService, IXMLProvider xmlProvider, IConfiguration config) {
_lib = lib; _lib = lib;
_xmlProvider = xmlProvider;
_readerService = readerService; _readerService = readerService;
_xmlService = xmlService; _xmlService = xmlService;
_fileSizeLimit = config.GetValue<long>("FileSizeLimit"); _fileSizeLimit = config.GetValue<long>("FileSizeLimit");
@@ -117,7 +120,13 @@ public class APIController : Controller {
//// 5. Stage: Saving the File(s) //// 5. Stage: Saving the File(s)
foreach (var doc in retdocs) { foreach (var doc in retdocs) {
await _xmlService.UpdateAvailableFiles(doc, _targetFilePath, ModelState); // Physical saving
var task = _xmlProvider.Save(doc, _targetFilePath, ModelState);
// Setting the new docuemnt as used
_xmlService.Use(doc);
// Unsetting all old docuemnts as ununsed
_xmlService.AutoUse(doc.Prefix);
await task;
if (!ModelState.IsValid) return StatusCode(500, ModelState); if (!ModelState.IsValid) return StatusCode(500, ModelState);
if (docs == null) docs = new List<XMLRootDocument>(); if (docs == null) docs = new List<XMLRootDocument>();
docs.Add(doc); docs.Add(doc);

View File

@@ -18,16 +18,18 @@ public class UploadController : Controller {
private readonly long _fileSizeLimit; private readonly long _fileSizeLimit;
private readonly string _targetFilePath; private readonly string _targetFilePath;
private readonly IXMLService _xmlService; private readonly IXMLService _xmlService;
private readonly IXMLProvider _xmlProvider;
// Options // Options
private static readonly string[] _permittedExtensions = { ".xml" }; private static readonly string[] _permittedExtensions = { ".xml" };
private static readonly FormOptions _defaultFormOptions = new FormOptions(); private static readonly FormOptions _defaultFormOptions = new FormOptions();
public UploadController(IHaDocumentWrappper lib, IReaderService readerService, IXMLService xmlService, IConfiguration config) { public UploadController(IHaDocumentWrappper lib, IReaderService readerService, IXMLService xmlService, IXMLProvider xmlProvider, IConfiguration config) {
_lib = lib; _lib = lib;
_readerService = readerService; _readerService = readerService;
_xmlService = xmlService; _xmlService = xmlService;
_xmlProvider = xmlProvider;
_fileSizeLimit = config.GetValue<long>("FileSizeLimit"); _fileSizeLimit = config.GetValue<long>("FileSizeLimit");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
_targetFilePath = config.GetValue<string>("StoredFilePathWindows"); _targetFilePath = config.GetValue<string>("StoredFilePathWindows");
@@ -42,23 +44,25 @@ public class UploadController : Controller {
[GenerateAntiforgeryTokenCookie] [GenerateAntiforgeryTokenCookie]
public IActionResult Index(string? id) { public IActionResult Index(string? id) {
if (id != null) { if (id != null) {
id = id.ToLower();
var root = _xmlService.GetRoot(id); var root = _xmlService.GetRoot(id);
if (root == null) return error404(); if (root == null) return error404();
var roots = _xmlService.GetRoots(); var roots = _xmlService.GetRootsList();
if (roots == null) return error404(); if (roots == null) return error404();
var usedFiles = _xmlService.GetUsed(); var usedFiles = _xmlService.GetUsedDictionary();
var availableFiles = _xmlService.GetAvailableFiles(id); var availableFiles = _xmlProvider.GetFiles(id);
var model = new UploadViewModel(root.Type, id, roots, availableFiles, usedFiles); var model = new UploadViewModel(root.Type, id, roots, availableFiles, usedFiles);
return View("../Admin/Upload/Index", model); return View("../Admin/Upload/Index", model);
} }
else { else {
var roots = _xmlService.GetRoots(); var roots = _xmlService.GetRootsList();
if (roots == null) return error404(); if (roots == null) return error404();
var usedFiles = _xmlService.GetUsed(); var usedFiles = _xmlService.GetUsedDictionary();
var model = new UploadViewModel("Upload", id, roots, null, usedFiles); var model = new UploadViewModel("Upload", id, roots, null, usedFiles);
return View("../Admin/Upload/Index", model); return View("../Admin/Upload/Index", model);

View File

@@ -0,0 +1,8 @@
namespace HaWeb.FileHelpers;
using HaWeb.Models;
using Microsoft.AspNetCore.Mvc.ModelBinding;
public interface IXMLProvider {
public FileList? GetFiles(string prefix);
public Task Save(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState);
}

View File

@@ -0,0 +1,77 @@
namespace HaWeb.FileHelpers;
using Microsoft.Extensions.FileProviders;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using HaWeb.Models;
using HaWeb.XMLParser;
public class XMLProvider : IXMLProvider {
private IFileProvider _fileProvider;
private Dictionary<string, FileList?>? _Files;
private Dictionary<string, IXMLRoot>? _Roots;
public XMLProvider(IFileProvider provider, IXMLService xmlservice) {
_fileProvider = provider;
_Roots = xmlservice.GetRootsDictionary();
_Files = _ScanFiles();
}
public FileList? GetFiles(string prefix)
=> _Files != null && _Files.ContainsKey(prefix) ? _Files[prefix] : null;
// Saves a Document as file and adds it to the collection
public async Task Save(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState) {
var type = doc.Prefix;
var directory = Path.Combine(basefilepath, type);
var path = Path.Combine(directory, doc.FileName);
try {
if (!Directory.Exists(directory))
Directory.CreateDirectory(directory);
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);
if (_Files == null) _Files = new Dictionary<string, FileList?>();
if (!_Files.ContainsKey(doc.Prefix)) _Files.Add(doc.Prefix, new FileList(doc.XMLRoot));
_Files[doc.Prefix]!.Add(doc);
}
private Dictionary<string, FileList?>? _ScanFiles() {
if (_Roots == null) return null;
Dictionary<string, FileList?>? res = null;
var dirs = _fileProvider.GetDirectoryContents(string.Empty).Where(x => x.IsDirectory);
foreach (var dir in dirs) {
if (_Roots.ContainsKey(dir.Name)) {
if (_Files == null) _Files = new Dictionary<string, FileList?>();
if (res == null) res = new Dictionary<string, FileList?>();
res.Add(dir.Name, _ScanFiles(dir.Name));
}
}
return res;
}
private FileList? _ScanFiles(string prefix) {
if (_Roots == null) return null;
FileList? 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 (_Roots == null || !_Roots.ContainsKey(prefix))
throw new Exception("Attempting to read a File from an unrecognized Prefix: " + prefix);
if (res == null) res = new FileList(_Roots[prefix]);
res.Add(new XMLRootDocument(_Roots[prefix], file));
}
return res;
}
}

25
HaWeb/Models/FileList.cs Normal file
View File

@@ -0,0 +1,25 @@
namespace HaWeb.Models;
using HaWeb.XMLParser;
using System.Text.Json.Serialization;
public class FileList {
private HashSet<XMLRootDocument>? _Files;
[JsonIgnore]
public IXMLRoot XMLRoot { get; private set; }
public FileList(IXMLRoot xmlRoot) {
XMLRoot = xmlRoot;
}
public void Add(XMLRootDocument document) {
if (document.Prefix != XMLRoot.Prefix)
throw new Exception("Diese Liste kann nur Elemente des Typs " + XMLRoot.Prefix + " enthalten");
if (_Files == null) _Files = new HashSet<XMLRootDocument>();
if (!_Files.Contains(document)) _Files.Add(document);
}
public List<XMLRootDocument>? GetFileList()
=> this._Files != null ? this._Files.ToList() : null;
}

View File

@@ -5,11 +5,11 @@ public class UploadViewModel {
public string ActiveTitle { get; private set; } public string ActiveTitle { get; private set; }
public string? Prefix { get; private set; } public string? Prefix { get; private set; }
public List<IXMLRoot>? AvailableRoots { get; private set; } public List<IXMLRoot>? AvailableRoots { get; private set; }
public List<XMLRootDocument>? AvailableFiles { get; private set; } public FileList? AvailableFiles { get; private set; }
public Dictionary<string, List<XMLRootDocument>>? UsedFiles { get; private set; } public Dictionary<string, FileList>? UsedFiles { get; private set; }
public UploadViewModel(string title, string? prefix, List<IXMLRoot>? roots, List<XMLRootDocument>? availableFiles, Dictionary<string, List<XMLRootDocument>>? usedFiles) { public UploadViewModel(string title, string? prefix, List<IXMLRoot>? roots, FileList? availableFiles, Dictionary<string, FileList>? usedFiles) {
Prefix = prefix; Prefix = prefix;
ActiveTitle = title; ActiveTitle = title;
AvailableRoots = roots; AvailableRoots = roots;

View File

@@ -1,13 +1,14 @@
namespace HaWeb.XMLParser; namespace HaWeb.Models;
using System.Xml.Linq; using System.Xml.Linq;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
using HaWeb.XMLParser;
public class XMLRootDocument { public class XMLRootDocument {
private XElement? _Element; private XElement? _Element;
private string? _filename; private string? _filename;
private IXMLService _xmlService; public IXMLRoot XMLRoot { get; private set; }
[JsonIgnore] [JsonIgnore]
public XElement Root { public XElement Root {
@@ -31,21 +32,20 @@ public class XMLRootDocument {
public IFileInfo? File { get; private set; } public IFileInfo? File { get; private set; }
public string Prefix { get; private set; } public string Prefix { get; private set; }
public DateTime Date { get; private set; } public DateTime Date { get; private set; }
public bool Used { get; private set; } = false;
public (string?, string?) IdentificationString { get; private set; } public (string?, string?) IdentificationString { get; private set; }
[JsonIgnore] public List<(string, string?)>? Fields { get; set; }
public List<(string, string)>? Fields { get; set; }
// Entry point for file reading // Entry point for file reading
public XMLRootDocument(IXMLService xmlService, IFileInfo file) { public XMLRootDocument(IXMLRoot xmlRoot, IFileInfo file) {
_xmlService = xmlService; XMLRoot = xmlRoot;
Prefix = xmlRoot.Prefix;
SetFile(file); SetFile(file);
} }
// Entry point for XML upload reading // Entry point for XML upload reading
public XMLRootDocument(IXMLService xmlService, string prefix, (string?, string?) idString, XElement element) { public XMLRootDocument(IXMLRoot xmlRoot, string prefix, (string?, string?) idString, XElement element) {
_xmlService = xmlService; XMLRoot = xmlRoot;
Prefix = prefix; Prefix = prefix;
IdentificationString = idString; IdentificationString = idString;
Date = DateTime.Today; Date = DateTime.Today;
@@ -58,13 +58,6 @@ public class XMLRootDocument {
_GenerateFieldsFromFilename(file.Name); _GenerateFieldsFromFilename(file.Name);
} }
public void SetUsed(bool used) {
Used = used;
if (used && _Element == null) {
_GetElement();
}
}
private string _CreateFilename() { private string _CreateFilename() {
var filename = _removeInvalidChars(Prefix) + "_"; var filename = _removeInvalidChars(Prefix) + "_";
if (!String.IsNullOrWhiteSpace(IdentificationString.Item1)) { if (!String.IsNullOrWhiteSpace(IdentificationString.Item1)) {
@@ -101,7 +94,7 @@ public class XMLRootDocument {
if (File == null || String.IsNullOrWhiteSpace(File.PhysicalPath) || !File.Exists) if (File == null || String.IsNullOrWhiteSpace(File.PhysicalPath) || !File.Exists)
throw new Exception("Es ist kein Pfad für die XML-Datei vorhanden."); throw new Exception("Es ist kein Pfad für die XML-Datei vorhanden.");
var root = _xmlService.GetRoot(Prefix); var root = XMLRoot;
if (root == null) if (root == null)
throw new Exception("Kein gültiges Hamann-Dokument: " + File.PhysicalPath + "Vom Prefix: " + Prefix); throw new Exception("Kein gültiges Hamann-Dokument: " + File.PhysicalPath + "Vom Prefix: " + Prefix);
@@ -123,7 +116,7 @@ public class XMLRootDocument {
} }
public async Task Save(Stream stream, ModelStateDictionary state) { public async Task Save(Stream stream, ModelStateDictionary state) {
var root = _xmlService.GetRoot(Prefix); var root = XMLRoot;
if (root == null) { if (root == null) {
state.AddModelError("Error", "No corresponding Root Element found."); state.AddModelError("Error", "No corresponding Root Element found.");
return; return;

View File

@@ -2,6 +2,7 @@ using HaXMLReader;
using HaXMLReader.Interfaces; using HaXMLReader.Interfaces;
using HaDocument.Interfaces; using HaDocument.Interfaces;
using HaWeb.XMLParser; using HaWeb.XMLParser;
using HaWeb.FileHelpers;
using Microsoft.FeatureManagement; using Microsoft.FeatureManagement;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.FileProviders;
@@ -13,6 +14,7 @@ builder.Services.AddControllersWithViews();
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
// // To get files from a path provided by configuration: // // To get files from a path provided by configuration:
// TODO: Test Read / Write Access
string? filepath = null; string? filepath = null;
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
filepath = builder.Configuration.GetValue<string>("StoredFilePathWindows"); filepath = builder.Configuration.GetValue<string>("StoredFilePathWindows");
@@ -27,10 +29,10 @@ if (filepath == null) {
var physicalProvider = new PhysicalFileProvider(filepath); var physicalProvider = new PhysicalFileProvider(filepath);
builder.Services.AddSingleton<IFileProvider>(physicalProvider); builder.Services.AddSingleton<IFileProvider>(physicalProvider);
builder.Services.AddSingleton<HaWeb.FileHelpers.IHaDocumentWrappper, HaWeb.FileHelpers.HaDocumentWrapper>(); builder.Services.AddSingleton<HaWeb.FileHelpers.IHaDocumentWrappper, HaWeb.FileHelpers.HaDocumentWrapper>();
builder.Services.AddTransient<IReaderService, ReaderService>(); builder.Services.AddTransient<IReaderService, ReaderService>();
builder.Services.AddSingleton<IXMLProvider, XMLProvider>();
builder.Services.AddSingleton<IXMLService, XMLService>(); builder.Services.AddSingleton<IXMLService, XMLService>();
builder.Services.AddFeatureManagement(); builder.Services.AddFeatureManagement();
@@ -45,7 +47,6 @@ if (!app.Environment.IsDevelopment())
app.UseHttpsRedirection(); app.UseHttpsRedirection();
} }
// app.UseWebOptimizer();
app.UseAuthorization(); app.UseAuthorization();
app.UseStaticFiles(); app.UseStaticFiles();
app.MapControllers(); app.MapControllers();

View File

@@ -43,4 +43,7 @@ TODO Word-wrap before align, tabs
TODO pills are not mobile friendly (hover / click) TODO pills are not mobile friendly (hover / click)
TODO Evtl alignment von center / right an der letzten oder nächsten zeile TODO Evtl alignment von center / right an der letzten oder nächsten zeile
TODO Abhärten des Konstruktors von XMLRootDokument für von außerhalb platzierte Dokumente TODO Abhärten des Konstruktors von XMLRootDokument für von außerhalb platzierte Dokumente
TODO XML-Check im Client TODO XML-Check im Client
TODO Lock für die Liste
TODO Up-Button
TODO Neue Forschungsliteratur einsenden

View File

@@ -1,5 +1,6 @@
namespace HaWeb.Settings.XMLRoots; namespace HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using HaWeb.Models;
using HaWeb.XMLParser; using HaWeb.XMLParser;
public class CommentRoot : HaWeb.XMLParser.IXMLRoot { public class CommentRoot : HaWeb.XMLParser.IXMLRoot {

View File

@@ -1,5 +1,6 @@
namespace HaWeb.Settings.XMLRoots; namespace HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using HaWeb.Models;
using HaWeb.XMLParser; using HaWeb.XMLParser;
public class DescriptionsRoot : HaWeb.XMLParser.IXMLRoot { public class DescriptionsRoot : HaWeb.XMLParser.IXMLRoot {

View File

@@ -1,5 +1,6 @@
namespace HaWeb.Settings.XMLRoots; namespace HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using HaWeb.Models;
using HaWeb.XMLParser; using HaWeb.XMLParser;
public class DocumentRoot : HaWeb.XMLParser.IXMLRoot { public class DocumentRoot : HaWeb.XMLParser.IXMLRoot {

View File

@@ -1,5 +1,6 @@
namespace HaWeb.Settings.XMLRoots; namespace HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using HaWeb.Models;
using HaWeb.XMLParser; using HaWeb.XMLParser;
public class EditsRoot : HaWeb.XMLParser.IXMLRoot { public class EditsRoot : HaWeb.XMLParser.IXMLRoot {

View File

@@ -1,5 +1,6 @@
namespace HaWeb.Settings.XMLRoots; namespace HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using HaWeb.Models;
using HaWeb.XMLParser; using HaWeb.XMLParser;
public class MarginalsRoot : HaWeb.XMLParser.IXMLRoot { public class MarginalsRoot : HaWeb.XMLParser.IXMLRoot {

View File

@@ -1,5 +1,6 @@
namespace HaWeb.Settings.XMLRoots; namespace HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using HaWeb.Models;
using HaWeb.XMLParser; using HaWeb.XMLParser;
public class ReferencesRoot : HaWeb.XMLParser.IXMLRoot { public class ReferencesRoot : HaWeb.XMLParser.IXMLRoot {

View File

@@ -1,5 +1,6 @@
namespace HaWeb.Settings.XMLRoots; namespace HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using HaWeb.Models;
using HaWeb.XMLParser; using HaWeb.XMLParser;
public class TraditionsRoot : HaWeb.XMLParser.IXMLRoot { public class TraditionsRoot : HaWeb.XMLParser.IXMLRoot {

View File

@@ -6,14 +6,14 @@
<div class="ha-uploadfieldname">@item.Type</div> <div class="ha-uploadfieldname">@item.Type</div>
@if (Model.UsedFiles != null && Model.UsedFiles.ContainsKey(item.Prefix)) { @if (Model.UsedFiles != null && Model.UsedFiles.ContainsKey(item.Prefix)) {
<div class="ha-uploadusedfiles"> <div class="ha-uploadusedfiles">
@foreach(var file in Model.UsedFiles[item.Prefix]) { @foreach(var file in Model.UsedFiles[item.Prefix].GetFileList()!) {
@if (file == Model.UsedFiles[item.Prefix].Last()) @if (file == Model.UsedFiles[item.Prefix].GetFileList()!.Last())
{ {
<span class="ha-uploadusedfile">@file.File.Name</span> <span class="ha-uploadusedfile">@file.FileName</span>
} }
else else
{ {
<span class="ha-uploadusedfile">@file.File.Name;</span> <span class="ha-uploadusedfile">@file.FileName;</span>
} }
} }
</div> </div>
@@ -56,7 +56,7 @@
<div class="ha-usedfilesheader"> <div class="ha-usedfilesheader">
<div class="ha-usedfilesheaderlist"> <div class="ha-usedfilesheaderlist">
@if(Model.UsedFiles != null && Model.UsedFiles.ContainsKey(Model.Prefix)) { @if(Model.UsedFiles != null && Model.UsedFiles.ContainsKey(Model.Prefix)) {
@foreach (var item in Model.UsedFiles[Model.Prefix]) @foreach (var item in Model.UsedFiles[Model.Prefix].GetFileList())
{ {
<div class="ha-usedfilesheaderfile">@item.File.Name</div> <div class="ha-usedfilesheaderfile">@item.File.Name</div>
} }

View File

@@ -1,6 +1,7 @@
namespace HaWeb.XMLParser; namespace HaWeb.XMLParser;
using System.Xml.Linq; using System.Xml.Linq;
using System.Xml.XPath; using System.Xml.XPath;
using HaWeb.Models;
public interface IXMLRoot { public interface IXMLRoot {
// Name of the IXMLRoot // Name of the IXMLRoot

View File

@@ -1,12 +1,15 @@
namespace HaWeb.XMLParser; namespace HaWeb.XMLParser;
using System.Xml.Linq; using System.Xml.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding;
using HaWeb.Models;
public interface IXMLService { public interface IXMLService {
public IXMLRoot? GetRoot(string name); public IXMLRoot? GetRoot(string name);
public List<IXMLRoot>? GetRoots(); public List<IXMLRoot>? GetRootsList();
public Dictionary<string, IXMLRoot>? GetRootsDictionary();
public Task<List<XMLRootDocument>?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState); public Task<List<XMLRootDocument>?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState);
public Task UpdateAvailableFiles(XMLRootDocument doc, string basefilepath, ModelStateDictionary ModelState); public Dictionary<string, FileList?>? GetUsedDictionary();
public Dictionary<string, List<XMLRootDocument>> GetUsed(); public void Use(XMLRootDocument doc);
public List<XMLRootDocument>? GetAvailableFiles(string prefix); public void AutoUse(string prefix);
public void AutoUse(FileList filelist);
} }

View File

@@ -1,35 +1,14 @@
namespace HaWeb.XMLParser; namespace HaWeb.XMLParser;
using HaWeb.Settings.XMLRoots;
using System.Xml.Linq; using System.Xml.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.FileProviders; using HaWeb.Models;
using Microsoft.FeatureManagement;
public class XMLService : IXMLService { public class XMLService : IXMLService {
private Dictionary<string, List<XMLRootDocument>?>? _availableFilesObj; private Dictionary<string, FileList?>? _Used;
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; private Dictionary<string, IXMLRoot>? _Roots;
public bool UploadEnabled = false; public XMLService() {
public bool UpdateEnabled = false; // Getting all classes which implement IXMLRoot for possible document endpoints
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(); var types = _GetAllTypesThatImplementInterface<IXMLRoot>().ToList();
types.ForEach( x => { types.ForEach( x => {
if (this._Roots == null) this._Roots = new Dictionary<string, IXMLRoot>(); if (this._Roots == null) this._Roots = new Dictionary<string, IXMLRoot>();
@@ -42,11 +21,14 @@ public class XMLService : IXMLService {
} }
public IXMLRoot? GetRoot(string name) { public IXMLRoot? GetRoot(string name) {
if (_Roots == null) return null;
_Roots.TryGetValue(name, out var root); _Roots.TryGetValue(name, out var root);
return root; return root;
} }
public List<IXMLRoot>? GetRoots() => this._Roots == null ? null : this._Roots.Values.ToList(); public List<IXMLRoot>? GetRootsList() => this._Roots == null ? null : this._Roots.Values.ToList();
public Dictionary<string, IXMLRoot>? GetRootsDictionary() => this._Roots == null ? null : this._Roots;
public async Task<List<XMLRootDocument>?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) { public async Task<List<XMLRootDocument>?> ProbeHamannFile(XDocument document, ModelStateDictionary ModelState) {
if (document.Root!.Name != "opus") { if (document.Root!.Name != "opus") {
@@ -69,72 +51,43 @@ public class XMLService : IXMLService {
return res; return res;
} }
public void UpdateAvailableFiles() { public Dictionary<string, FileList?>? GetUsedDictionary()
_availableFilesObj = _GetAvailableFiles(); => this._Used;
// Adds a document and sets it to used
public void Use(XMLRootDocument doc) {
if (_Used == null) _Used = new Dictionary<string, FileList?>();
if (!_Used.ContainsKey(doc.Prefix)) _Used.Add(doc.Prefix, new FileList(doc.XMLRoot));
_Used[doc.Prefix]!.Add(doc);
} }
public void UpdateAvailableFiles(string prefix) { // Performs detection of using on the specified document type
if (_availableFilesObj == null) { public void AutoUse(string prefix) {
UpdateAvailableFiles(); if (_Used == null || !_Used.ContainsKey(prefix)) return;
return; AutoUse(_Used[prefix]!);
}
if (_availableFilesObj.ContainsKey(prefix))
_availableFilesObj.Remove(prefix);
if (_fileProvider.GetDirectoryContents(prefix).Exists) {
_availableFilesObj.Add(prefix, _GetAvailableFiles(prefix));
}
AutoDetermineUsed(prefix);
} }
public List<XMLRootDocument>? GetAvailableFiles(string prefix) { // Performs detection of using given a list of files
if (_Roots == null || _availableFiles == null) return null; public void AutoUse(FileList filelist) {
if(!_Roots.ContainsKey(prefix) || !_availableFiles.ContainsKey(prefix)) return null; FileList? res = null;
var list = filelist.GetFileList();
var prefix = filelist.XMLRoot.Prefix;
return _availableFiles[prefix]; if (list == null) return;
if (_Used != null && _Used.ContainsKey(prefix)) _Used.Remove(prefix);
// TODO: Item1
var lookup = list.ToLookup(x => x.IdentificationString.Item2);
foreach (var idstring in lookup) {
var ordered = idstring.OrderBy(x => x.Date);
if (res == null) res = new FileList(filelist.XMLRoot);
Use(ordered.Last());
}
} }
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) { private XMLRootDocument _createXMLRootDocument(IXMLRoot Root, XElement element) {
var doc = new XMLRootDocument(this, Root.Prefix, Root.GenerateIdentificationString(element), element); var doc = new XMLRootDocument(Root, Root.Prefix, Root.GenerateIdentificationString(element), element);
doc.Fields = Root.GenerateFields(doc); doc.Fields = Root.GenerateFields(doc);
return doc; return doc;
} }
@@ -145,64 +98,4 @@ public class XMLService : IXMLService {
.GetTypes() .GetTypes()
.Where(type => typeof(T).IsAssignableFrom(type) && !type.IsInterface); .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);
}
} }

View File

@@ -30,7 +30,7 @@ namespace HamannPrinter
EndYearTextBox.Text = "1762"; // DEV EndYearTextBox.Text = "1762"; // DEV
XmlFileBox.Text = @"D:\dev\source\hamann-ausgabe-core\XML\XML"; // DEV XmlFileBox.Text = @"D:\dev\source\hamann-ausgabe-core\XML\XML"; // DEV
OutputDirBox.Text = @"D:\dev\source\hamann-ausgabe-core\XML\Ausg"; // DEV OutputDirBox.Text = @"D:\dev\source\hamann-ausgabe-core\XML\Ausg"; // DEV
Act(); // DEV //Act(); // DEV
} }
private void SingleDocChanged(object sender, RoutedEventArgs e) private void SingleDocChanged(object sender, RoutedEventArgs e)