jx/internal/folio/referrer.go
2025-08-25 03:56:56 +00:00

134 lines
3.3 KiB
Go

// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package folio
import (
"encoding/json"
"gopkg.in/yaml.v3"
"net/url"
"decl/internal/data"
"decl/internal/mapper"
"errors"
)
var (
// ErrInvalidURI error = errors.New("Invalid URI")
ErrInvalidReferenceType error = errors.New("invalid ReferenceType value")
)
type ReferenceTypes interface {
*Document | *Declaration
}
type RefMap[T ReferenceTypes] mapper.Store[string, T]
type ReferenceMapper[T ReferenceTypes] interface {
mapper.Map[URI, T]
}
type ResourceMapper ReferenceMapper[*Declaration]
type DocumentMapper ReferenceMapper[*Document]
type ReferenceType string
type RefType[T ReferenceTypes, TypedReferenceMapper ReferenceMapper[T]] ReferenceType
type ReferenceURI[T ReferenceTypes] URI
type DocumentURI ReferenceURI[*Document]
type ResourceURI ReferenceURI[*Declaration]
const (
ReferenceTypeResource ReferenceType = "resource"
RefTypeResource RefType[*Declaration, mapper.Store[URI, *Declaration]] = RefType[*Declaration, mapper.Store[URI, *Declaration]](ReferenceTypeResource)
ReferenceTypeDocument ReferenceType = "document"
RefTypeDocument RefType[*Document, mapper.Store[URI, *Document]] = RefType[*Document, mapper.Store[URI, *Document]](ReferenceTypeDocument)
)
type CommonReferrer interface {
ReferenceType() ReferenceType
Parse() *url.URL
Exists() bool
data.ContentReadWriter
IsEmpty() bool
}
// interface for a reference
type Referrer[T ReferenceTypes, TypedReferenceMapper ReferenceMapper[T]] interface {
CommonReferrer
Lookup(TypedReferenceMapper) ContentReadWriter
GetContentReadWriter(TypedReferenceMapper) ContentReadWriter
Dereference(TypedReferenceMapper) T
}
/*
func (r ReferenceType) URIType() any {
switch r {
case ReferenceTypeDocument:
return ReferenceURI[*Document]
case ReferenceTypeResource:
return ReferenceURI[*Declaration]
}
}
*/
func (r *RefType[T, TypedReferenceMapper]) UnmarshalValue(value string) error {
switch value {
case string(ReferenceTypeResource), string(ReferenceTypeDocument):
*r = RefType[T, TypedReferenceMapper](value)
return nil
default:
return ErrInvalidReferenceType
}
}
func (r *RefType[T, TypedReferenceMapper]) UnmarshalJSON(data []byte) error {
var s string
if unmarshalReferenceTypeErr := json.Unmarshal(data, &s); unmarshalReferenceTypeErr != nil {
return unmarshalReferenceTypeErr
}
return r.UnmarshalValue(s)
}
func (r *RefType[T, TypedReferenceMapper]) UnmarshalYAML(value *yaml.Node) error {
var s string
if err := value.Decode(&s); err != nil {
return err
}
return r.UnmarshalValue(s)
}
func (r *RefType[T, TypedReferenceMapper]) Dereference(uri URI, look TypedReferenceMapper) (result T) {
result = nil
if uri != "" {
if v,ok := look.Get(uri); ok {
result = v
}
}
return
}
func RefURI[T ReferenceTypes, RT RefType[T, ReferenceMapper[T]], RU ReferenceURI[T]](uri URI, reftype RT) (refuri RU) {
refuri = RU(uri)
return
}
/*
func (r *ReferenceURI[T]) GetContentReadWriter(mapper TypedReferenceMapper) ContentReadWriter {
if URI(r).String() == "" {
return nil
}
if mapper != nil {
if v,ok := mapper.Get(string(r)); ok {
return v.(data.Originator).GetContentReadWriter()
}
}
return r
}
*/
type ResourceMapSetter interface {
SetResourceMapper(ResourceMapper)
}
func NewResourceMapper() ResourceMapper {
return mapper.New[URI, *Declaration]()
}