jx/internal/types/types.go

108 lines
2.4 KiB
Go
Raw Normal View History

2024-05-31 16:11:35 +00:00
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package types
import (
"errors"
"fmt"
"net/url"
"strings"
"path/filepath"
)
2024-07-01 07:16:55 +00:00
/*
The `types` package provides a generic method of registering a type factory.
*/
2024-05-31 16:11:35 +00:00
var (
ErrUnknownType = errors.New("Unknown type")
ErrInvalidProduct = errors.New("Invalid product")
2024-05-31 16:11:35 +00:00
)
2024-07-01 07:16:55 +00:00
//type Name[Registry any] string //`json:"type"`
2024-05-31 16:11:35 +00:00
type Factory[Product comparable] func(*url.URL) Product
type RegistryTypeMap[Product comparable] map[string]Factory[Product]
2024-05-31 16:11:35 +00:00
type Types[Product comparable] struct {
2024-05-31 16:11:35 +00:00
registry RegistryTypeMap[Product]
}
func New[Product comparable]() *Types[Product] {
2024-05-31 16:11:35 +00:00
return &Types[Product]{registry: make(map[string]Factory[Product])}
}
func (t *Types[Product]) Register(names []string, factory Factory[Product]) {
for _,name := range names {
t.registry[name] = factory
}
}
func (t *Types[Product]) FromExtension(path string) (Factory[Product], error) {
elements := strings.Split(path, ".")
numberOfElements := len(elements)
if numberOfElements > 2 {
if src := t.Get(strings.Join(elements[numberOfElements - 2: numberOfElements - 1], ".")); src != nil {
return src, nil
}
}
if src := t.Get(elements[numberOfElements - 1]); src != nil {
return src, nil
}
return nil, fmt.Errorf("%w: %s", ErrUnknownType, path)
}
func (t *Types[Product]) New(uri string) (result Product, err error) {
u, e := url.Parse(uri)
if u == nil || e != nil {
err = fmt.Errorf("%w: %s", ErrUnknownType, e)
return
}
if u.Scheme == "" {
u.Scheme = "file"
}
path := filepath.Join(u.Hostname(), u.Path)
if d, lookupErr := t.FromExtension(path); d != nil {
return d(u), lookupErr
}
if r, ok := t.registry[u.Scheme]; ok {
if result = r(u); result != any(nil) {
return result, nil
} else {
return result, fmt.Errorf("%w: factory failed creating %s", ErrInvalidProduct, uri)
}
2024-05-31 16:11:35 +00:00
}
err = fmt.Errorf("%w: %s", ErrUnknownType, u.Scheme)
return
}
func (t *Types[Product]) Has(typename string) bool {
if _, ok := t.registry[typename]; ok {
return true
}
return false
}
func (t *Types[Product]) Get(typename string) Factory[Product] {
if d, ok := t.registry[typename]; ok {
return d
}
return nil
}
/*
2024-07-01 07:16:55 +00:00
func (n *Name[Registry]) UnmarshalJSON(b []byte) error {
ProductTypeName := strings.Trim(string(b), "\"")
if Registry.Has(ProductTypeName) {
*n = Name[Registry](ProductTypeName)
2024-05-31 16:11:35 +00:00
return nil
}
2024-07-01 07:16:55 +00:00
return fmt.Errorf("%w: %s", ErrUnknownType, ProductTypeName)
2024-05-31 16:11:35 +00:00
}
*/