mirror of
https://github.com/Theodor-Springmann-Stiftung/kgpz_web.git
synced 2025-10-29 09:05:30 +00:00
restructured viewmodels, better serialization
This commit is contained in:
48
providers/xmlprovider/agents.go
Normal file
48
providers/xmlprovider/agents.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package xmlprovider
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type AgentProvider struct {
|
||||
XMLProvider[Agents]
|
||||
}
|
||||
|
||||
type Agent struct {
|
||||
XMLName xml.Name `xml:"akteur"`
|
||||
Names []string `xml:"name"`
|
||||
SortName string `xml:"sortiername"`
|
||||
Life string `xml:"lebensdaten"`
|
||||
GND string `xml:"gnd"`
|
||||
Org bool `xml:"org,attr"`
|
||||
Identifier
|
||||
AnnotationNote
|
||||
}
|
||||
|
||||
type Agents struct {
|
||||
XMLName xml.Name `xml:"akteure"`
|
||||
Agents []Agent `xml:"akteur"`
|
||||
}
|
||||
|
||||
func (a Agents) String() string {
|
||||
var res []string
|
||||
for _, agent := range a.Agents {
|
||||
res = append(res, agent.String())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Agents: %v", res)
|
||||
}
|
||||
|
||||
func (a Agents) Append(data Agents) Agents {
|
||||
a.Agents = append(a.Agents, data.Agents...)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Agent) String() string {
|
||||
return fmt.Sprintf("ID: %s\nNames: %v\nSortName: %s\nLife: %s\nGND: %s\nAnnotations: %v\nNotes: %v\n", a.ID, a.Names, a.SortName, a.Life, a.GND, a.Annotations, a.Notes)
|
||||
}
|
||||
|
||||
func NewAgentProvider(paths []string) *AgentProvider {
|
||||
return &AgentProvider{XMLProvider: XMLProvider[Agents]{paths: paths}}
|
||||
}
|
||||
45
providers/xmlprovider/categories.go
Normal file
45
providers/xmlprovider/categories.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package xmlprovider
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type CategoryProvider struct {
|
||||
XMLProvider[Categories]
|
||||
}
|
||||
|
||||
type Categories struct {
|
||||
XMLName xml.Name `xml:"kategorien"`
|
||||
Category []Category `xml:"kategorie"`
|
||||
}
|
||||
|
||||
type Category struct {
|
||||
XMLName xml.Name `xml:"kategorie"`
|
||||
Names []string `xml:"name"`
|
||||
SortName string `xml:"sortiername"`
|
||||
Identifier
|
||||
AnnotationNote
|
||||
}
|
||||
|
||||
func (c Categories) Append(data Categories) Categories {
|
||||
c.Category = append(c.Category, data.Category...)
|
||||
return c
|
||||
}
|
||||
|
||||
func (c Categories) String() string {
|
||||
var res []string
|
||||
for _, category := range c.Category {
|
||||
res = append(res, category.String())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Categories: %v", res)
|
||||
}
|
||||
|
||||
func (c *Category) String() string {
|
||||
return fmt.Sprintf("ID: %s\nNames: %v\nSortName: %s\nAnnotations: %v\nNotes: %v\n", c.ID, c.Names, c.SortName, c.Annotations, c.Notes)
|
||||
}
|
||||
|
||||
func NewCategoryProvider(paths []string) *CategoryProvider {
|
||||
return &CategoryProvider{XMLProvider: XMLProvider[Categories]{paths: paths}}
|
||||
}
|
||||
60
providers/xmlprovider/issues.go
Normal file
60
providers/xmlprovider/issues.go
Normal file
@@ -0,0 +1,60 @@
|
||||
package xmlprovider
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type IssueProvider struct {
|
||||
XMLProvider[Issues]
|
||||
}
|
||||
|
||||
type Issues struct {
|
||||
XMLName xml.Name `xml:"stuecke"`
|
||||
Issues []Issue `xml:"stueck"`
|
||||
}
|
||||
|
||||
type Issue struct {
|
||||
XMLName xml.Name `xml:"stueck"`
|
||||
Number Nummer `xml:"nummer"`
|
||||
Datum KGPZDate `xml:"datum"`
|
||||
Von int `xml:"von"`
|
||||
Bis int `xml:"bis"`
|
||||
Additionals []Additional `xml:"beilage"`
|
||||
Identifier
|
||||
AnnotationNote
|
||||
}
|
||||
|
||||
type Nummer struct {
|
||||
No int `xml:",chardata"`
|
||||
Corrected string `xml:"korrigiert,attr"`
|
||||
}
|
||||
|
||||
type Additional struct {
|
||||
XMLName xml.Name `xml:"beilage"`
|
||||
Nummer string `xml:"nummer,attr"`
|
||||
Von string `xml:"von"`
|
||||
Bis string `xml:"bis"`
|
||||
}
|
||||
|
||||
func (i Issues) Append(data Issues) Issues {
|
||||
i.Issues = append(i.Issues, data.Issues...)
|
||||
return i
|
||||
}
|
||||
|
||||
func (i Issues) String() string {
|
||||
var res []string
|
||||
for _, issue := range i.Issues {
|
||||
res = append(res, issue.String())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Issues: %v", res)
|
||||
}
|
||||
|
||||
func (i Issue) String() string {
|
||||
return fmt.Sprintf("Number: %v, Datum: %v, Von: %d, Bis: %d, Additionals: %v, Identifier: %v, AnnotationNote: %v\n", i.Number, i.Datum, i.Von, i.Bis, i.Additionals, i.Identifier, i.AnnotationNote)
|
||||
}
|
||||
|
||||
func NewIssueProvider(paths []string) *IssueProvider {
|
||||
return &IssueProvider{XMLProvider: XMLProvider[Issues]{paths: paths}}
|
||||
}
|
||||
53
providers/xmlprovider/pieces.go
Normal file
53
providers/xmlprovider/pieces.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package xmlprovider
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type PieceProvider struct {
|
||||
XMLProvider[Pieces]
|
||||
}
|
||||
|
||||
type Pieces struct {
|
||||
XMLName xml.Name `xml:"beitraege"`
|
||||
Piece []Piece `xml:"beitrag"`
|
||||
}
|
||||
|
||||
type Piece struct {
|
||||
XMLName xml.Name `xml:"beitrag"`
|
||||
IssueRefs []IssueRef `xml:"stueck"`
|
||||
PlaceRefs []PlaceRef `xml:"ort"`
|
||||
CategoryRefs []CategoryRef `xml:"kategorie"`
|
||||
AgentRefs []AgentRef `xml:"akteur"`
|
||||
WorkRefs []WorkRef `xml:"werk"`
|
||||
PieceRefs []PieceRef `xml:"beitrag"`
|
||||
AdditionalRef []AdditionalRef `xml:"beilage"`
|
||||
Datum []KGPZDate `xml:"datum"`
|
||||
Incipit []string `xml:"incipit"`
|
||||
Title []string `xml:"titel"`
|
||||
Identifier
|
||||
AnnotationNote
|
||||
}
|
||||
|
||||
func (p Pieces) Append(data Pieces) Pieces {
|
||||
p.Piece = append(p.Piece, data.Piece...)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p Pieces) String() string {
|
||||
var res []string
|
||||
for _, piece := range p.Piece {
|
||||
res = append(res, piece.String())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Pieces: %v", res)
|
||||
}
|
||||
|
||||
func (p Piece) String() string {
|
||||
return fmt.Sprintf("ID: %s\nIssueRefs: %v\nPlaceRefs: %v\nCategoryRefs: %v\nAgentRefs: %v\nWorkRefs: %v\nPieceRefs: %v\nAdditionalRef: %v\nIncipit: %v\nTitle: %v\nAnnotations: %v\nNotes: %v\n", p.ID, p.IssueRefs, p.PlaceRefs, p.CategoryRefs, p.AgentRefs, p.WorkRefs, p.PieceRefs, p.AdditionalRef, p.Incipit, p.Title, p.Annotations, p.Notes)
|
||||
}
|
||||
|
||||
func NewPieceProvider(paths []string) *PieceProvider {
|
||||
return &PieceProvider{XMLProvider: XMLProvider[Pieces]{paths: paths}}
|
||||
}
|
||||
46
providers/xmlprovider/places.go
Normal file
46
providers/xmlprovider/places.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package xmlprovider
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type PlaceProvider struct {
|
||||
XMLProvider[Places]
|
||||
}
|
||||
|
||||
type Places struct {
|
||||
XMLName xml.Name `xml:"orte"`
|
||||
Place []Place `xml:"ort"`
|
||||
}
|
||||
|
||||
type Place struct {
|
||||
XMLName xml.Name `xml:"ort"`
|
||||
Names []string `xml:"name"`
|
||||
SortName string `xml:"sortiername"`
|
||||
Geo string `xml:"geonames"`
|
||||
Identifier
|
||||
AnnotationNote
|
||||
}
|
||||
|
||||
func (p Places) Append(data Places) Places {
|
||||
p.Place = append(p.Place, data.Place...)
|
||||
return p
|
||||
}
|
||||
|
||||
func (p Places) String() string {
|
||||
var res []string
|
||||
for _, place := range p.Place {
|
||||
res = append(res, place.String())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Places: %v", res)
|
||||
}
|
||||
|
||||
func (p *Place) String() string {
|
||||
return fmt.Sprintf("ID: %s\nNames: %v\nSortName: %s\nGeo: %s\nAnnotations: %v\nNotes: %v\n", p.ID, p.Names, p.SortName, p.Geo, p.Annotations, p.Notes)
|
||||
}
|
||||
|
||||
func NewPlaceProvider(paths []string) *PlaceProvider {
|
||||
return &PlaceProvider{XMLProvider: XMLProvider[Places]{paths: paths}}
|
||||
}
|
||||
55
providers/xmlprovider/works.go
Normal file
55
providers/xmlprovider/works.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package xmlprovider
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type WorkProvider struct {
|
||||
XMLProvider[Works]
|
||||
}
|
||||
|
||||
type Works struct {
|
||||
XMLName xml.Name `xml:"werke"`
|
||||
Work []Work `xml:"werk"`
|
||||
}
|
||||
|
||||
type Work struct {
|
||||
XMLName xml.Name `xml:"werk"`
|
||||
URLs []URL `xml:"url"`
|
||||
Citation Citation `xml:"zitation"`
|
||||
PreferredTitle string `xml:"preferred"`
|
||||
Akteur []AgentRef `xml:"akteur"`
|
||||
Identifier
|
||||
AnnotationNote
|
||||
}
|
||||
|
||||
type Citation struct {
|
||||
XMLName xml.Name `xml:"zitation"`
|
||||
Title string `xml:"title"`
|
||||
Year []string `xml:"year"`
|
||||
Value
|
||||
Inner
|
||||
}
|
||||
|
||||
func (w Works) Append(data Works) Works {
|
||||
w.Work = append(w.Work, data.Work...)
|
||||
return w
|
||||
}
|
||||
|
||||
func (w Works) String() string {
|
||||
var res []string
|
||||
for _, work := range w.Work {
|
||||
res = append(res, work.String())
|
||||
}
|
||||
|
||||
return fmt.Sprintf("Works: %v", res)
|
||||
}
|
||||
|
||||
func (w *Work) String() string {
|
||||
return fmt.Sprintf("URLs: %v, Citation: %v, PreferredTitle: %s, Akteur: %v, Identifier: %v, AnnotationNote: %v\n", w.URLs, w.Citation, w.PreferredTitle, w.Akteur, w.Identifier, w.AnnotationNote)
|
||||
}
|
||||
|
||||
func NewWorkProvider(paths []string) *WorkProvider {
|
||||
return &WorkProvider{XMLProvider: XMLProvider[Works]{paths: paths}}
|
||||
}
|
||||
55
providers/xmlprovider/xmlcommon.go
Normal file
55
providers/xmlprovider/xmlcommon.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package xmlprovider
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
type KGPZDate struct {
|
||||
XMLName xml.Name `xml:"datum"`
|
||||
When string `xml:"when,attr"`
|
||||
NotBefore string `xml:"notBefore,attr"`
|
||||
NotAfter string `xml:"notAfter,attr"`
|
||||
From string `xml:"from,attr"`
|
||||
To string `xml:"to,attr"`
|
||||
Value
|
||||
}
|
||||
|
||||
type URL struct {
|
||||
XMLName xml.Name `xml:"url"`
|
||||
Address string `xml:"address,attr"`
|
||||
Value
|
||||
}
|
||||
|
||||
type AnnotationNote struct {
|
||||
Annotations []Annotation `xml:"anmerkung"`
|
||||
Notes []Note `xml:"vermerk"`
|
||||
}
|
||||
|
||||
type Annotation struct {
|
||||
XMLName xml.Name `xml:"anmerkung"`
|
||||
Value
|
||||
Inner
|
||||
}
|
||||
|
||||
type Note struct {
|
||||
XMLName xml.Name `xml:"vermerk"`
|
||||
Value
|
||||
Inner
|
||||
}
|
||||
|
||||
type Identifier struct {
|
||||
ID string `xml:"id,attr"`
|
||||
}
|
||||
|
||||
type Reference struct {
|
||||
Ref string `xml:"ref,attr"`
|
||||
Category string `xml:"kat,attr"`
|
||||
Unsicher bool `xml:"unsicher,attr"`
|
||||
Value
|
||||
}
|
||||
|
||||
type Value struct {
|
||||
Chardata string `xml:",chardata"`
|
||||
}
|
||||
|
||||
type Inner struct {
|
||||
InnerXML string `xml:",innerxml"`
|
||||
}
|
||||
139
providers/xmlprovider/xmlprovider.go
Normal file
139
providers/xmlprovider/xmlprovider.go
Normal file
@@ -0,0 +1,139 @@
|
||||
package xmlprovider
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/Theodor-Springmann-Stiftung/kgpz_web/helpers/logging"
|
||||
)
|
||||
|
||||
type KGPZXML[T any] interface {
|
||||
Append(data T) T
|
||||
fmt.Stringer
|
||||
}
|
||||
|
||||
type XMLProvider[T KGPZXML[T]] struct {
|
||||
mu sync.Mutex
|
||||
paths []string
|
||||
Items T
|
||||
}
|
||||
|
||||
type Library struct {
|
||||
Agents *AgentProvider
|
||||
Places *PlaceProvider
|
||||
Works *WorkProvider
|
||||
Categories *CategoryProvider
|
||||
Issues *IssueProvider
|
||||
Pieces *PieceProvider
|
||||
}
|
||||
|
||||
func NewLibrary(agentpaths, placepaths, workpaths, categorypaths, issuepaths, piecepaths []string) *Library {
|
||||
return &Library{
|
||||
Agents: NewAgentProvider(agentpaths),
|
||||
Places: NewPlaceProvider(placepaths),
|
||||
Works: NewWorkProvider(workpaths),
|
||||
Categories: NewCategoryProvider(categorypaths),
|
||||
Issues: NewIssueProvider(issuepaths),
|
||||
Pieces: NewPieceProvider(piecepaths),
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Library) Serialize() {
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(6)
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := l.Agents.Serialize()
|
||||
if err != nil {
|
||||
l.Agents = nil
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := l.Places.Serialize()
|
||||
if err != nil {
|
||||
l.Places = nil
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := l.Works.Serialize()
|
||||
if err != nil {
|
||||
l.Works = nil
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := l.Categories.Serialize()
|
||||
if err != nil {
|
||||
l.Categories = nil
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := l.Issues.Serialize()
|
||||
if err != nil {
|
||||
l.Issues = nil
|
||||
}
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
err := l.Pieces.Serialize()
|
||||
if err != nil {
|
||||
l.Pieces = nil
|
||||
}
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (p *XMLProvider[T]) Serialize() error {
|
||||
// Introduce goroutine for every path, locking on append:
|
||||
var wg sync.WaitGroup
|
||||
for _, path := range p.paths {
|
||||
wg.Add(1)
|
||||
go func(path string) {
|
||||
defer wg.Done()
|
||||
var data T
|
||||
if err := UnmarshalFile(path, &data); err != nil {
|
||||
return
|
||||
}
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
p.Items = p.Items.Append(data)
|
||||
}(path)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
fmt.Println(p.Items)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *XMLProvider[T]) String() string {
|
||||
a.mu.Lock()
|
||||
defer a.mu.Unlock()
|
||||
return fmt.Sprintf("Items: %s", a.Items)
|
||||
}
|
||||
|
||||
func UnmarshalFile[T any](filename string, data *T) error {
|
||||
xmlFile, err := os.Open(filename)
|
||||
if err != nil {
|
||||
logging.Error(err, "Could not deserialize file: "+filename)
|
||||
return err
|
||||
}
|
||||
defer xmlFile.Close()
|
||||
logging.Info("Deserialization: " + filename)
|
||||
byteValue, _ := io.ReadAll(xmlFile)
|
||||
xml.Unmarshal(byteValue, data)
|
||||
|
||||
return nil
|
||||
}
|
||||
49
providers/xmlprovider/xmlrefs.go
Normal file
49
providers/xmlprovider/xmlrefs.go
Normal file
@@ -0,0 +1,49 @@
|
||||
package xmlprovider
|
||||
|
||||
import "encoding/xml"
|
||||
|
||||
type AgentRef struct {
|
||||
XMLName xml.Name `xml:"akteur"`
|
||||
Reference
|
||||
}
|
||||
|
||||
type AdditionalRef struct {
|
||||
XMLName xml.Name `xml:"beilage"`
|
||||
Reference
|
||||
Datum string `xml:"datum,attr"`
|
||||
Nr string `xml:"nr,attr"`
|
||||
AdditionalNo string `xml:"beilage,attr"`
|
||||
Von string `xml:"von,attr"`
|
||||
Bis string `xml:"bis,attr"`
|
||||
}
|
||||
|
||||
type IssueRef struct {
|
||||
XMLName xml.Name `xml:"stueck"`
|
||||
Reference
|
||||
Datum string `xml:"datum,attr"`
|
||||
Nr string `xml:"nr,attr"`
|
||||
Von string `xml:"von,attr"`
|
||||
Bis string `xml:"bis,attr"`
|
||||
}
|
||||
|
||||
type PlaceRef struct {
|
||||
XMLName xml.Name `xml:"ort"`
|
||||
Reference
|
||||
}
|
||||
|
||||
type CategoryRef struct {
|
||||
XMLName xml.Name `xml:"kategorie"`
|
||||
Reference
|
||||
}
|
||||
|
||||
type WorkRef struct {
|
||||
XMLName xml.Name `xml:"werk"`
|
||||
Reference
|
||||
Page string `xml:"s,attr"`
|
||||
}
|
||||
|
||||
type PieceRef struct {
|
||||
XMLName xml.Name `xml:"beitrag"`
|
||||
Page string `xml:"s,attr"`
|
||||
Reference
|
||||
}
|
||||
Reference in New Issue
Block a user