mirror of
				https://github.com/Theodor-Springmann-Stiftung/hamann-ausgabe-core.git
				synced 2025-10-31 02:05:33 +00:00 
			
		
		
		
	Added collection classes. Will not do extra collection for subcomments rn.
This commit is contained in:
		
							
								
								
									
										24
									
								
								HaWeb/XMLParser/IXMLCollection.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								HaWeb/XMLParser/IXMLCollection.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| namespace HaWeb.XMLParser; | ||||
| using HaWeb.Models; | ||||
| using System.Xml.Linq; | ||||
|  | ||||
| public interface IXMLCollection { | ||||
|     // Collections of Elements to be created a Hamann File Root | ||||
|     // Key: the key under which the element(s) will be filed | ||||
|     // xPath: (absolute, realtive if subelement) XPaths to the element(s) | ||||
|     // GenerateKey: How to extract an identifier for the single element in the collection | ||||
|     // GenerateDataFields: Generate a dict of data associated with each of the collected Elements input: XElement output: Dictonary<string> | ||||
|     // GroupingsGeneration: datafields by which dictorary-like groups should be held in memory input: List<CollectedItem> output: Dictonary<string, Lookup<string, CollectedItem[]>> | ||||
|     // SortingsGeneration: datafields by which a sorting should be held in memory input: List<CollectedItem> output: ordered List<CollectedItem> | ||||
|     // SubCollections to be created in this element | ||||
|     // Searchable: Will the element be indexed for full-text-search? | ||||
|  | ||||
|     abstract string Key { get; } | ||||
|     abstract string[] xPath { get; } | ||||
|     abstract Func<XElement, string?> GenerateKey { get; } | ||||
|     abstract Func<XElement, IDictionary<string, string>?>? GenerateDataFields { get; } | ||||
|     abstract Func<IEnumerable<CollectedItem>, IDictionary<string, ILookup<string, CollectedItem>>?>? GroupingsGeneration { get; } | ||||
|     abstract Func<IEnumerable<CollectedItem>, IDictionary<string, IEnumerable<CollectedItem>>?>? SortingsGeneration { get; } | ||||
|     abstract IXMLCollection[]? SubCollections { get; } | ||||
|     abstract bool Searchable { get; } | ||||
| } | ||||
| @@ -13,24 +13,6 @@ public interface IXMLRoot { | ||||
|     // XPaths to determine if container is present | ||||
|     public abstract string[] XPathContainer { get; } | ||||
|  | ||||
|     // Collections of Elements to be created from this Root | ||||
|     // Key: the key under which the element(s) will be files | ||||
|     // xPath: the (absolute) XPath to the element(s) | ||||
|     // Searchable: Will the element be indexed for full-text-search? | ||||
|     // GenerateKey: How to extrect an identifier for the single element in the collection | ||||
|     // GenerateDataFields: Generate a dict of data associated with each of the collected Elements input: XElement output: Dictonary<string> | ||||
|     // GroupingsGeneration: datafields by which dictorary-like groups should be held in memory input: List<CollectedItem> output: Dictonary<string, Lookup<string, CollectedItem[]>> | ||||
|     // SortingsGeneration: datafields by which a sorting should be held in memory input: List<CollectedItem> output: ordered List<CollectedItem> | ||||
|     public abstract ( | ||||
|         string Key,  | ||||
|         string xPath, | ||||
|         Func<XElement, string?> GenerateKey, | ||||
|         Func<XElement, Dictionary<string, string[]>?>? GenerateDataFields, | ||||
|         Func<List<CollectedItem>, Dictionary<string, Lookup<string, CollectedItem>>?>? GroupingsGeneration, | ||||
|         Func<List<CollectedItem>, Dictionary<string, List<CollectedItem>>?>? SortingsGeneration, | ||||
|         bool Searchable | ||||
|     )[]? Collections { get; } | ||||
|  | ||||
|     // Determines child objects to be collected  | ||||
|     // (deprecated see collections above; only used internally) | ||||
|     public abstract Predicate<XElement> IsCollectedObject { get; } | ||||
|   | ||||
| @@ -12,6 +12,7 @@ using HaXMLReader.Interfaces; | ||||
| public class XMLService : IXMLService { | ||||
|     private Dictionary<string, FileList?>? _Used; | ||||
|     private Dictionary<string, IXMLRoot>? _Roots; | ||||
|     private Dictionary<string, IXMLCollection>? _Collections; | ||||
|  | ||||
|     private Stack<Dictionary<string, FileList?>>? _InProduction; | ||||
|  | ||||
| @@ -20,15 +21,25 @@ public class XMLService : IXMLService { | ||||
|  | ||||
|     public XMLService() { | ||||
|         // Getting all classes which implement IXMLRoot for possible document endpoints | ||||
|         var types = _GetAllTypesThatImplementInterface<IXMLRoot>().ToList(); | ||||
|         types.ForEach( x => { | ||||
|         var roottypes = _GetAllTypesThatImplementInterface<IXMLRoot>().ToList(); | ||||
|         roottypes.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); | ||||
|         }); | ||||
|  | ||||
|         var collectiontypes = _GetAllTypesThatImplementInterface<IXMLCollection>().ToList(); | ||||
|         collectiontypes.ForEach( x => { | ||||
|             if (this._Collections == null) this._Collections = new Dictionary<string, IXMLCollection>(); | ||||
|             var instance = (IXMLCollection)Activator.CreateInstance(x)!; | ||||
|             if (instance != null) this._Collections.Add(instance.Key, instance); | ||||
|         }); | ||||
|  | ||||
|         if (_Roots == null || !_Roots.Any()) | ||||
|             throw new Exception("No classes for upload endpoints were found!"); | ||||
|  | ||||
|         if (_Collections == null || !_Collections.Any()) | ||||
|             throw new Exception("No classes for object collection were found!"); | ||||
|     } | ||||
|  | ||||
|     public IXMLRoot? GetRoot(string name) { | ||||
| @@ -66,33 +77,32 @@ public class XMLService : IXMLService { | ||||
|         int startingSize = 2909; | ||||
|         int startingSizeAllCollections = 23; | ||||
|         var ret = new ConcurrentDictionary<string, ItemsCollection>(concurrencyLevel, startingSizeAllCollections); | ||||
|         foreach (var root in _Roots) { | ||||
|             if (root.Value.Collections != null) | ||||
|                 foreach (var coll in root.Value.Collections) { | ||||
|                     var elem = document.XPathSelectElements(coll.xPath); | ||||
|                     if (elem != null && elem.Any()) { | ||||
|                         var items = new ConcurrentDictionary<string, CollectedItem>(concurrencyLevel, startingSize); | ||||
|                         Parallel.ForEach(elem, (e) => { | ||||
|                             var k = coll.GenerateKey(e); | ||||
|                             if (k != null) { | ||||
|                                 var searchtext = coll.Searchable ?  | ||||
|                                     StringHelpers.NormalizeWhiteSpace(e.ToString(), ' ', false) :  | ||||
|                                     null; | ||||
|                                 var datafileds = coll.GenerateDataFields != null ?  | ||||
|                                     coll.GenerateDataFields(e) : | ||||
|                                     null; | ||||
|                                 items[k] = new CollectedItem(k, e, root.Value, coll.Key, datafileds, searchtext); | ||||
|                             } | ||||
|                         }); | ||||
|                         if (items.Any()) { | ||||
|                             if (!ret.ContainsKey(coll.Key))  | ||||
|                                 ret[coll.Key] = new ItemsCollection(coll.Key, coll.Searchable, root.Value, coll.GroupingsGeneration, coll.SortingsGeneration); | ||||
|                             foreach (var item in items)  | ||||
|                                 ret[coll.Key].Items.Add(item.Key, item.Value); | ||||
|  | ||||
|         if (_Collections != null) | ||||
|             foreach (var coll in _Collections) { | ||||
|                 var elem = coll.Value.xPath.Aggregate(new List<XElement>(), (x, y) =>  { x.AddRange(document.XPathSelectElements(y).ToList()); return x; } ); | ||||
|                 if (elem != null && elem.Any()) { | ||||
|                     var items = new ConcurrentDictionary<string, CollectedItem>(concurrencyLevel, startingSize); | ||||
|                     Parallel.ForEach(elem, (e) => { | ||||
|                         var k = coll.Value.GenerateKey(e); | ||||
|                         if (k != null) { | ||||
|                             var searchtext = coll.Value.Searchable ?  | ||||
|                                 StringHelpers.NormalizeWhiteSpace(e.ToString(), ' ', false) :  | ||||
|                                 null; | ||||
|                             var datafileds = coll.Value.GenerateDataFields != null ?  | ||||
|                                 coll.Value.GenerateDataFields(e) : | ||||
|                                 null; | ||||
|                             items[k] = new CollectedItem(k, e, coll.Value, datafileds, searchtext); | ||||
|                         } | ||||
|                     }); | ||||
|                     if (items.Any()) { | ||||
|                         if (!ret.ContainsKey(coll.Key))  | ||||
|                             ret[coll.Key] = new ItemsCollection(coll.Key, coll.Value); | ||||
|                         foreach (var item in items)  | ||||
|                             ret[coll.Key].Items.Add(item.Key, item.Value); | ||||
|                     } | ||||
|                 } | ||||
|         } | ||||
|             } | ||||
|  | ||||
|         if (ret.Any()) { | ||||
|             Parallel.ForEach(ret, (collection) => { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 schnulller
					schnulller