diff --git a/HaDocumentV6/Models/Meta.cs b/HaDocumentV6/Models/Meta.cs index a20d8d1..e8131f3 100644 --- a/HaDocumentV6/Models/Meta.cs +++ b/HaDocumentV6/Models/Meta.cs @@ -3,10 +3,34 @@ using System.Collections.Generic; using HaXMLReader.EvArgs; namespace HaDocument.Models { + public class AdditionalDates { + public DateTime? NotBefore { get; } = null; + public DateTime? NotAfter { get; } = null; + public DateTime? From { get; } = null; + public DateTime? To { get; } = null; + public string? Cert { get; } = null; + + + public AdditionalDates( + DateTime? notBefore, + DateTime? notAfter, + DateTime? from, + DateTime? to, + string? cert + ) { + NotBefore = notBefore; + NotAfter = notAfter; + From = from; + To = to; + Cert = cert; + } + } + public class Meta { public string ID { get; } = ""; public string Date { get; } = ""; public DateTime Sort { get; } = new DateTime(1700, 1, 1); + public AdditionalDates? AdditionalDates { get; } = null; public int Order { get; } = -1; public string Location { get; } = ""; public List Senders { get; } = null; @@ -14,12 +38,12 @@ namespace HaDocument.Models { public bool? hasOriginal { get; } public bool? isProofread { get; } public bool? isDraft { get; } - public ZHInfo ZH { get; } = null; + public ZHInfo? ZH { get; } = null; public Meta( - string id, - string date, - DateTime sort, + string id, + string date, + DateTime sort, int order, bool? hasOriginal, bool? isProofread, @@ -27,7 +51,8 @@ namespace HaDocument.Models { string location, List senders, List receivers, - ZHInfo ZH + ZHInfo? ZH, + AdditionalDates? additionalDates = null ) { ID = id; Date = date; @@ -40,7 +65,8 @@ namespace HaDocument.Models { this.isProofread = isProofread; this.isDraft = isDraft; this.ZH = ZH; + this.AdditionalDates = additionalDates; } } -} \ No newline at end of file +} diff --git a/HaDocumentV6/Models/Person.cs b/HaDocumentV6/Models/Person.cs index 8ed0f3b..acff470 100644 --- a/HaDocumentV6/Models/Person.cs +++ b/HaDocumentV6/Models/Person.cs @@ -8,6 +8,7 @@ namespace HaDocument.Models { public string? Surname { get; } public string? Komm { get; } public string? Reference { get; } + public bool IsOrg { get; } = false; public XElement? XElement { get; } public Person( @@ -17,7 +18,8 @@ namespace HaDocument.Models { string? surname, string? komm, string? reference, - XElement? xElement = null + XElement? xElement = null, + bool IsOrg = false ) { Index = index; Name = name; @@ -25,11 +27,14 @@ namespace HaDocument.Models { Surname = surname; Komm = komm; Reference = reference; + this.XElement = xElement; + this.IsOrg = IsOrg; } public static Person? FromXElement(XElement element) { if (!element.HasAttributes || (element.Name != "personDef" && element.Name != "handDef")) return null; if (element.Attribute("index")?.Value == null || element.Attribute("name")?.Value == null) return null; + var org = element.HasAttributes && element.Attribute("org")?.Value == "true"; return new Person( element.Attribute("index")!.Value, element.Attribute("name")!.Value, @@ -37,8 +42,9 @@ namespace HaDocument.Models { element.Attribute("nachname")?.Value, element.Attribute("komm")?.Value, element.Attribute("ref")?.Value, - element + element, + org ); } } -} \ No newline at end of file +} diff --git a/HaDocumentV6/Reactors/MetaReactor.cs b/HaDocumentV6/Reactors/MetaReactor.cs index 08c0499..7d41e74 100644 --- a/HaDocumentV6/Reactors/MetaReactor.cs +++ b/HaDocumentV6/Reactors/MetaReactor.cs @@ -25,7 +25,8 @@ namespace HaDocument.Reactors { private bool? hasOriginal { get; set; } = null; private bool? isProofread { get; set; } = null; private bool? isDraft { get; set; } = null; - private bool dateChanged {get; set; } = false; + private AdditionalDates? AdditionalDates { get; set; } = null; + private bool dateChanged { get; set; } = false; private string Location { get; set; } = ""; private List Senders { get; set; } = null; private List Receivers { get; set; } = null; @@ -42,9 +43,9 @@ namespace HaDocument.Reactors { protected override void Listen(object sender, Tag tag) { if ( - !tag.EndTag && + !tag.EndTag && !tag.IsEmpty && - tag.Name =="letterDesc" && + tag.Name == "letterDesc" && !String.IsNullOrWhiteSpace(tag["letter"]) ) { Activate(_reader, tag); @@ -52,7 +53,7 @@ namespace HaDocument.Reactors { } protected override void Activate(IReader reader, Tag tag) { - if (!_active && reader != null && tag != null) { + if (!_active && reader != null && tag != null) { Reset(); _active = true; ID = tag["letter"]; @@ -76,8 +77,7 @@ namespace HaDocument.Reactors { } private void OnTag(object _, Tag tag) { - switch (tag.Name) - { + switch (tag.Name) { case "begin": Page = tag["page"]; Volume = tag["vol"]; @@ -101,6 +101,14 @@ namespace HaDocument.Reactors { int res2 = 0; Int32.TryParse(tag["order"], out res2); Order = res2; + + AdditionalDates = new AdditionalDates( + GetDateTime(tag["notBefore"]), + GetDateTime(tag["notAfter"]), + GetDateTime(tag["from"]), + GetDateTime(tag["to"]), + tag["cert"] + ); break; case "hasOriginal": var val = tag["value"]; @@ -135,10 +143,10 @@ namespace HaDocument.Reactors { } break; case "dateChanged": - dateChanged = tag["value"].ToLower() == "true" ? true : false; + dateChanged = tag["value"].ToLower() == "true" ? true : false; break; case "alternativeLineNumbering": - AltLineNumbering = tag["value"].ToLower() == "true" ? true : false; + AltLineNumbering = tag["value"].ToLower() == "true" ? true : false; break; case "letterDesc": if (tag.EndTag) Deactivate(); @@ -148,6 +156,11 @@ namespace HaDocument.Reactors { private void Add() { var ZHInfo = !inZH ? null : new ZHInfo(AltLineNumbering, dateChanged, Volume, Page); + if (AdditionalDates != null) { + if (AdditionalDates.NotBefore == null && AdditionalDates.NotAfter == null && AdditionalDates.From == null && AdditionalDates.To == null && AdditionalDates.Cert == null) { + AdditionalDates = null; + } + } var meta = new Meta( ID, Date, @@ -159,7 +172,8 @@ namespace HaDocument.Reactors { Location, Senders, Receivers, - ZHInfo + ZHInfo, + AdditionalDates ); if ( _availableVolumes.Contains(Volume) || @@ -179,6 +193,7 @@ namespace HaDocument.Reactors { isProofread = null; isDraft = null; dateChanged = false; + AdditionalDates = null; ID = ""; Volume = ""; Page = ""; @@ -190,5 +205,12 @@ namespace HaDocument.Reactors { Senders = new List(); Receivers = new List(); } + + private DateTime? GetDateTime(string date) { + DateTime res; + var ret = System.DateTime.TryParse(date, out res); + if (ret) return res; + else return null; + } } -} \ No newline at end of file +} diff --git a/HaDocumentV6/Reactors/PersonDefsReactor.cs b/HaDocumentV6/Reactors/PersonDefsReactor.cs index 7fe08ff..fe7be28 100644 --- a/HaDocumentV6/Reactors/PersonDefsReactor.cs +++ b/HaDocumentV6/Reactors/PersonDefsReactor.cs @@ -17,6 +17,7 @@ namespace HaDocument.Reactors { private string Surname = ""; private string? Reference; private string? Komm; + private bool IsOrg = false; internal PersonDefsReactor(IReader reader, IntermediateLibrary lib) : base(reader, lib) { lib.Persons = new Dictionary(); @@ -25,9 +26,9 @@ namespace HaDocument.Reactors { } protected override void Listen(object sender, Tag tag) { - if (!tag.EndTag && + if (!tag.EndTag && tag.IsEmpty && - tag.Name == "personDef" && + tag.Name == "personDef" && !String.IsNullOrWhiteSpace(tag["index"]) && !String.IsNullOrWhiteSpace(tag["name"]) ) { @@ -44,6 +45,7 @@ namespace HaDocument.Reactors { Prename = tag["vorname"]; Surname = tag["nachname"]; Reference = String.IsNullOrWhiteSpace(tag["ref"]) ? null : tag["ref"]; + IsOrg = tag["org"] == "true"; if (!String.IsNullOrWhiteSpace(tag["komm"])) Komm = tag["komm"]; Add(); _active = false; @@ -57,10 +59,11 @@ namespace HaDocument.Reactors { Surname = ""; Reference = null; Komm = null; + IsOrg = false; } public void Add() { - CreatedInstances.Add(Index, new Person(Index, Name, Prename, Surname, Komm, Reference)); + CreatedInstances.Add(Index, new Person(Index, Name, Prename, Surname, Komm, Reference, null, IsOrg)); } } -} \ No newline at end of file +} diff --git a/HaWeb/CMIF/model.cs b/HaWeb/CMIF/model.cs new file mode 100644 index 0000000..43b96ac --- /dev/null +++ b/HaWeb/CMIF/model.cs @@ -0,0 +1,306 @@ +namespace HaWeb.CMIF; + +using System; +using System.Xml.Serialization; +using System.Collections.Generic; +using HaDocument.Interfaces; + +public class TeiHeader { + [XmlElement("fileDesc")] + public FileDesc? FileDesc { get; set; } = new FileDesc(); + [XmlElement("profileDesc")] + public ProfileDesc? ProfileDesc { get; set; } = new ProfileDesc(); +} + +public class FileDesc { + [XmlElement("titleStmt")] + public TitleStatement? TitleStatement { get; set; } = new TitleStatement(); + [XmlElement("publicationStmt")] + public PublicationStatement? PublicationStatement { get; set; } = new PublicationStatement(); + [XmlElement("sourceDesc")] + public SourceDescription? SourceDescription { get; set; } = new SourceDescription(); +} + +public class TitleStatement { + [XmlElement("title")] + public string? Title { get; set; } = "Johann Georg Hammann: Kommentierte Briefausgabe (HKB)"; + [XmlElement("editor")] + public List? Editor { get; set; } = new List() { + new Editor() { + Email = "keidel@tss-hd.de", + Name = "Leonard Keidel", + }, + new Editor() { + Email = "reibold@tss-hd.de", + Name = "Janina Reibold", + } + }; +} + +public class Editor { + [XmlElement("email")] + public string? Email { get; set; } + [XmlText] + public string? Name { get; set; } +} + +public class PublicationStatement { + [XmlElement("publisher")] + public List? Publishers { get; set; } = new List() { + new Publisher() { + Reference = new PublisherRef() { + Target = "https://theodor-springmann-stiftung.de", + Value = "Theodor-Springmann-Stiftung", + } + }, + new Publisher() { + Reference = new PublisherRef() { + Target = "https://gs.uni-heidelberg.de", + Value = "Germanistisches Seminar der Universität Heidelberg", + } + } + }; + [XmlElement("idno")] + public Identifier? Identifier { get; set; } = new Identifier(); + [XmlElement("date")] + public Date Date { get; set; } = new Date() { + When = DateTime.Now.ToString("yyyy-MM-dd"), + }; + [XmlElement("availability")] + public Availability? Availability { get; set; } = new Availability(); +} + +public class Publisher { + [XmlElement("ref")] + public PublisherRef? Reference { get; set; } +} + +public class PublisherRef { + [XmlAttribute("target")] + public string? Target { get; set; } + [XmlText] + public string? Value { get; set; } + +} + +public class Availability { + [XmlElement("licence")] + public License? License { get; set; } = new License(); +} + +public class License { + [XmlAttribute("target")] + public string? Target { get; set; } = "https://creativecommons.org/licenses/by/4.0/"; + [XmlText] + public string? Value { get; set; } = "CC-BY 4.0"; +} + +public class Identifier { + [XmlAttribute("type")] + public string? Type { get; set; } = "url"; + [XmlText] + public string? Value { get; set; } = "https://hamann-ausgabe.de/HKB/CMIF"; +} + +public class SourceDescription { + [XmlElement("bibl")] + public Bibliography Bibliography { get; set; } = new Bibliography(); +} + +public class Bibliography { + [XmlAttribute("type")] + public string? Type { get; set; } = "online"; + [XmlAttribute("xml:id")] + public string? Id { get; set; } = "x419f1d82-7f42-4f29-ac00-f02e474ce766"; + [XmlText] + public string? Text { get; set; } = "Johann Georg Hamann: Kommentierte Briefausgabe. Hg. von Leonard Keidel und Janina Reibold, auf Grundlage der Vorarbeiten Arthur Henkels, unter Mitarbeit von Gregor Babelotzky, Konrad Bucher, Christian Großmann, Carl Friedrich Haak, Luca Klopfer, Johannes Knüchel, Isabel Langkabel und Simon Martens (Heidelberg 2020 ff.). URL: www.hamann-ausgabe.de [= HKB]"; + [XmlElement("ref")] + public Reference Reference { get; set; } = new Reference(); +} + +public class Reference { + [XmlAttribute("target")] + public string? Target { get; set; } = "https://hamann-ausgabe.de/HKB"; + [XmlText] + public string? Value { get; set; } = "https://hamann-ausgabe.de/HKB"; +} + +public class ProfileDesc { + [XmlElement("correspDesc")] + public List? CorrespondenceDescriptions { get; set; } +} + +public class CorrespondenceDescription { + [XmlAttribute("source")] + public string? Source { get; set; } = "#x419f1d82-7f42-4f29-ac00-f02e474ce766"; + [XmlAttribute("ref")] + public string? Reference { get; set; } + [XmlAttribute("key")] + public string? Key { get; set; } + [XmlElement("correspAction")] + public List? CorrespondenceActions { get; set; } +} + +public class CorrespondenceAction { + [XmlAttribute("type")] + public string? Type { get; set; } + [XmlElement("persName")] + public List? PersonName { get; set; } + [XmlElement("placeName")] + public List? PlaceName { get; set; } + [XmlElement("date")] + public Date? Date { get; set; } +} + +public class Date { + [XmlAttribute("when")] + public string? When { get; set; } + [XmlAttribute("notBefore")] + public string? NotBefore { get; set; } + [XmlAttribute("notAfter")] + public string? NotAfter { get; set; } + [XmlAttribute("from")] + public string? From { get; set; } + [XmlAttribute("to")] + public string? To { get; set; } + [XmlAttribute("cert")] + public string? Cert { get; set; } + [XmlText] + public string? Value { get; set; } + +} + +public class PersonName { + [XmlAttribute("evidence")] + public string? Evidence { get; set; } + [XmlAttribute("ref")] + public string? Reference { get; set; } + [XmlText] + public string? Name { get; set; } +} + +public class PlaceName { + [XmlAttribute("ref")] + public string? Reference { get; set; } + [XmlText] + public string? Name { get; set; } +} + +public class TeiText { + [XmlElement("body")] + public TextBody? Body { get; set; } = new TextBody(); +} + +public class TextBody { + [XmlElement("p")] + public string? Paragraph { get; set; } = ""; +} + +[XmlRoot(ElementName = "TEI", Namespace = "http://www.tei-c.org/ns/1.0")] +public class TeiDocument { + [XmlElement("teiHeader")] + public TeiHeader? TeiHeader { get; set; } = new TeiHeader(); + [XmlElement("text")] + public TeiText? Text { get; set; } = new TeiText(); + + public TeiDocument() { } + + public TeiDocument(ILibrary lib) { + var UNKNOWN_URL = "http://correspSearch.net/unknown"; + var UNKNOWN_TEXT = "Unbekannt"; + var LETTER_URL = "https://hamann-ausgabe.de/HKB/Briefe/"; + var DATE_OUTPUT = "yyyy-MM-dd"; + List cds = new List(); + foreach (var meta in lib.Metas.Values) { + if (lib.Letters.Where(x => x.Key == meta.ID).Count() == 0) continue; + var cd = new CorrespondenceDescription(); + cd.Reference = LETTER_URL + meta.ID; + cd.Key = meta.ID; + var sent = new CorrespondenceAction(); + sent.Type = "sent"; + var d = new Date(); + if (meta.AdditionalDates != null) { + d.NotBefore = meta.AdditionalDates.NotBefore != null ? meta.AdditionalDates.NotBefore.Value.ToString(DATE_OUTPUT) : null; + d.NotAfter = meta.AdditionalDates.NotAfter != null ? meta.AdditionalDates.NotAfter.Value.ToString(DATE_OUTPUT) : null; + d.From = meta.AdditionalDates.From != null ? meta.AdditionalDates.From.Value.ToString(DATE_OUTPUT) : null; + d.To = meta.AdditionalDates.To != null ? meta.AdditionalDates.To.Value.ToString(DATE_OUTPUT) : null; + d.Cert = !string.IsNullOrWhiteSpace(meta.AdditionalDates.Cert) ? meta.AdditionalDates.Cert.ToString() : null; + } + if (d.NotBefore == null && d.NotAfter == null && d.From == null && d.To == null) { + d.When = meta.Sort.ToString(DATE_OUTPUT); + } + if (!string.IsNullOrWhiteSpace(meta.Date)) { + var dta = meta.Date.Split(','); + var ndate = ""; + if (dta.Length > 1) { + ndate = string.Join(',', dta.Skip(1)).Trim(); + } + else { + ndate = dta[0].Trim(); + } + d.Value = ndate; + } + sent.Date = d; + if (!string.IsNullOrWhiteSpace(meta.Location)) { + if (lib.Locations.ContainsKey(meta.Location)) { + var p = new PlaceName(); + p.Name = lib.Locations[meta.Location].Name; + if (lib.Locations[meta.Location].Reference != null && !string.IsNullOrWhiteSpace(lib.Locations[meta.Location].Reference)) { + p.Reference = lib.Locations[meta.Location].Reference; + } + sent.PlaceName = new List() { p }; + } + } + if (meta.Senders != null && meta.Senders.Count() > 0) { + sent.PersonName = new List(); + foreach (var sender in meta.Senders) { + var pn = new PersonName(); + if (sender == "-1") { + pn.Name = UNKNOWN_TEXT; + pn.Reference = UNKNOWN_URL; + } + else if (lib.Persons.ContainsKey(sender)) { + pn.Name = lib.Persons[sender].Name; + if (lib.Persons[sender].Reference != null && !string.IsNullOrWhiteSpace(lib.Persons[sender].Reference)) { + pn.Reference = lib.Persons[sender].Reference; + } + } + else { + pn = null; + } + if (pn != null) sent.PersonName.Add(pn); + } + } + cd.CorrespondenceActions = new List() { sent }; + var recieved = new CorrespondenceAction(); + if (meta.Receivers != null && meta.Receivers.Count() > 0) { + recieved.PersonName = new List(); + foreach (var sender in meta.Receivers) { + var pn = new PersonName(); + if (sender == "-1") { + pn.Name = UNKNOWN_TEXT; + pn.Reference = UNKNOWN_URL; + } + else if (lib.Persons.ContainsKey(sender)) { + pn.Name = lib.Persons[sender].Name; + if (lib.Persons[sender].Reference != null && !string.IsNullOrWhiteSpace(lib.Persons[sender].Reference)) { + pn.Reference = lib.Persons[sender].Reference; + } + } + else { + pn = null; + } + if (pn != null) recieved.PersonName.Add(pn); + } + } + recieved.Type = "received"; + cd.CorrespondenceActions.Add(recieved); + cds.Add(cd); + } + + this.TeiHeader.ProfileDesc = new ProfileDesc() { CorrespondenceDescriptions = cds }; + } + +} + + diff --git a/HaWeb/Controllers/BriefeContoller.cs b/HaWeb/Controllers/BriefeContoller.cs index c2709a3..a65d81b 100644 --- a/HaWeb/Controllers/BriefeContoller.cs +++ b/HaWeb/Controllers/BriefeContoller.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using Microsoft.AspNetCore.Mvc; using HaWeb.Models; using HaWeb.FileHelpers; diff --git a/HaWeb/Controllers/CMIF.cs b/HaWeb/Controllers/CMIF.cs new file mode 100644 index 0000000..444a8d9 --- /dev/null +++ b/HaWeb/Controllers/CMIF.cs @@ -0,0 +1,27 @@ +namespace HaWeb.Controllers; + +using HaWeb.CMIF; +using HaWeb.FileHelpers; +using Microsoft.AspNetCore.Mvc; + +[ApiController] +public class CMIFController : Controller { + + private IHaDocumentWrappper _lib; + + public CMIFController(IHaDocumentWrappper lib) { + _lib = lib; + } + + [Route("HKB/CMIF")] + [HttpGet] + [Produces("application/xml")] + public IActionResult CMIF() { + var lib = _lib.GetLibrary(); + if (lib != null) { + var document = new TeiDocument(lib); + return Ok(document); + } + return NotFound(); + } +} diff --git a/HaWeb/Models/CollectedItem.cs b/HaWeb/Models/CollectedItem.cs index 2721551..9a8385c 100644 --- a/HaWeb/Models/CollectedItem.cs +++ b/HaWeb/Models/CollectedItem.cs @@ -1,5 +1,3 @@ -using System.Reflection.Emit; -using System.Collections; namespace HaWeb.Models; using HaWeb.SearchHelpers; using HaWeb.XMLParser; @@ -14,9 +12,9 @@ public class CollectedItem : ISearchable { public IDictionary? Items { get; set; } public CollectedItem( - string id, - XElement element, - IXMLCollection collection, + string id, + XElement element, + IXMLCollection collection, string? searchtext = null ) { this.ID = id; @@ -27,11 +25,11 @@ public class CollectedItem : ISearchable { public string? this[string v] { get { - if (Fields == null && Collection.GenerateDataFields != null) + if (Fields == null && Collection.GenerateDataFields != null) Fields = Collection.GenerateDataFields(this.Element); if (Fields != null && Fields.ContainsKey(v)) return Fields[v]; return null; } } -} \ No newline at end of file +} diff --git a/HaWeb/Program.cs b/HaWeb/Program.cs index 8cd75b3..9565f77 100644 --- a/HaWeb/Program.cs +++ b/HaWeb/Program.cs @@ -30,6 +30,7 @@ var hdW = new HaDocumentWrapper(XMLIS, builder.Configuration); var XMLFP = new XMLFileProvider(XMLIS, hdW, builder.Configuration); // Add services to the container. +builder.Services.AddControllers().AddXmlSerializerFormatters(); builder.Services.AddControllersWithViews(); builder.Services.AddHttpContextAccessor(); builder.Services.AddSingleton((_) => tS);