// Copyright 2024 Matthew Rich . 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]() }