// Copyright 2024 Matthew Rich . All rights reserved. package resource import ( "context" "fmt" "net/url" "path/filepath" "decl/internal/data" "decl/internal/folio" "log/slog" ) type UriSchemeValidator func(scheme string) bool type Common struct { SchemeCheck UriSchemeValidator `json:"-" yaml:"-"` includeQueryParamsInURI bool `json:"-" yaml:"-"` resourceType TypeName `json:"-" yaml:"-"` Uri folio.URI `json:"uri,omitempty" yaml:"uri,omitempty"` parsedURI *url.URL `json:"-" yaml:"-"` Path string `json:"path,omitempty" yaml:"path,omitempty"` exttype string `json:"-" yaml:"-"` fileext string `json:"-" yaml:"-"` normalizePath bool `json:"-" yaml:"-"` State string `json:"state,omitempty" yaml:"state,omitempty"` config data.ConfigurationValueGetter Resources data.ResourceMapper `json:"-" yaml:"-"` } func NewCommon(resourceType TypeName, includeQueryParams bool) *Common { c := &Common{ includeQueryParamsInURI: includeQueryParams, resourceType: resourceType } c.SchemeCheck = c.IsValidResourceScheme return c } func (c *Common) IsValidResourceScheme(scheme string) bool { return c.Type() == scheme } func (c *Common) ContentType() string { if c.parsedURI.Scheme != "file" { return c.parsedURI.Scheme } return c.exttype } func (c *Common) SetResourceMapper(resources data.ResourceMapper) { c.Resources = resources } func (c *Common) Clone() *Common { return &Common { Uri: c.Uri, parsedURI: c.parsedURI, Path: c.Path, exttype: c.exttype, fileext: c.fileext, normalizePath: c.normalizePath, State: c.State, config: c.config, Resources: c.Resources, } } func (c *Common) PathNormalization(flag bool) { c.normalizePath = flag } func (c *Common) URIPath() string { return c.Path } func (c *Common) URI() string { return string(c.Uri) } func (c *Common) SetURI(uri string) (err error) { c.SetURIFromString(uri) err = c.SetParsedURI(c.Uri.Parse()) return } func (c *Common) SetURIFromString(uri string) { c.Uri = folio.URI(uri) c.exttype, c.fileext = c.Uri.Extension() } func (c *Common) SetParsedURI(u *url.URL) (err error) { if u != nil { slog.Info("Common.SetParsedURI()", "parsed", u, "uri", c.Uri) if c.Uri.IsEmpty() { c.SetURIFromString(u.String()) } c.parsedURI = u if c.SchemeCheck(c.parsedURI.Scheme) { if c.includeQueryParamsInURI { c.Path = filepath.Join(c.parsedURI.Hostname(), c.parsedURI.RequestURI()) } else { c.Path = filepath.Join(c.parsedURI.Hostname(), c.parsedURI.Path) } if err = c.NormalizePath(); err != nil { return } return } } err = fmt.Errorf("%w: %s is not a %s resource, parsed: %t", ErrInvalidResourceURI, c.Uri, c.Type(), (u != nil)) return } func (c *Common) UseConfig(config data.ConfigurationValueGetter) { c.config = config } func (c *Common) ResolveId(ctx context.Context) string { if e := c.NormalizePath(); e != nil { panic(e) } return c.Path } func (c *Common) NormalizePath() error { if c.config != nil { if prefixPath, configErr := c.config.GetValue("prefix"); configErr == nil { c.Path = filepath.Join(prefixPath.(string), c.Path) } } if c.normalizePath { filePath, fileAbsErr := filepath.Abs(c.Path) if fileAbsErr == nil { c.Path = filePath } return fileAbsErr } return nil } func (c *Common) Type() string { return string(c.resourceType) }