// Copyright 2024 Matthew Rich . All rights reserved. package resource import ( "context" "encoding/json" "fmt" "io" "gopkg.in/yaml.v3" "log/slog" "gitea.rosskeen.house/rosskeen.house/machine" ) type DeclarationType struct { Type TypeName `json:"type" yaml:"type"` Transition string `json:"transition,omitempty" yaml:"transition,omitempty"` } type Declaration struct { StateMatchine machine.Stater `json:"-" yaml:"-"` Type TypeName `json:"type" yaml:"type"` Transition string `json:"transition,omitempty" yaml:"transition,omitempty"` Attributes Resource `json:"attributes" yaml:"attributes"` } type ResourceLoader interface { LoadDecl(string) error } type StateTransformer interface { Apply() error } func NewDeclaration() *Declaration { return &Declaration{} } func (d *Declaration) Clone() *Declaration { return &Declaration { Type: d.Type, Attributes: d.Attributes.Clone(), } } func (d *Declaration) Load(r io.Reader) error { c := NewYAMLDecoder(r) return c.Decode(d) } func (d *Declaration) LoadDecl(yamlResourceDeclaration string) error { c := NewYAMLStringDecoder(yamlResourceDeclaration) return c.Decode(d) } func (d *Declaration) NewResource() error { uri := fmt.Sprintf("%s://", d.Type) newResource, err := ResourceTypes.New(uri) d.Attributes = newResource return err } func (d *Declaration) Resource() Resource { return d.Attributes } func (d *Declaration) Apply() error { stater := d.Attributes.StateMachine() return stater.Trigger(d.Transition) } func (d *Declaration) SetURI(uri string) error { slog.Info("Declaration.SetURI()", "uri", uri, "declaration", d) d.Attributes = NewResource(uri) if d.Attributes == nil { panic("unknown resource") } d.Type = TypeName(d.Attributes.Type()) _,e := d.Attributes.Read(context.Background()) // fix context return e } func (d *Declaration) UnmarshalYAML(value *yaml.Node) error { t := &DeclarationType{} if unmarshalResourceTypeErr := value.Decode(t); unmarshalResourceTypeErr != nil { return unmarshalResourceTypeErr } d.Type = t.Type d.Transition = t.Transition newResource, resourceErr := ResourceTypes.New(fmt.Sprintf("%s://", d.Type)) if resourceErr != nil { return resourceErr } d.Attributes = newResource resourceAttrs := struct { Attributes yaml.Node `json:"attributes"` }{} if unmarshalAttributesErr := value.Decode(&resourceAttrs); unmarshalAttributesErr != nil { return unmarshalAttributesErr } if unmarshalResourceErr := resourceAttrs.Attributes.Decode(d.Attributes); unmarshalResourceErr != nil { return unmarshalResourceErr } return nil } func (d *Declaration) UnmarshalJSON(data []byte) error { t := &DeclarationType{} if unmarshalResourceTypeErr := json.Unmarshal(data, t); unmarshalResourceTypeErr != nil { return unmarshalResourceTypeErr } d.Type = t.Type d.Transition = t.Transition newResource, resourceErr := ResourceTypes.New(fmt.Sprintf("%s://", d.Type)) if resourceErr != nil { return resourceErr } d.Attributes = newResource resourceAttrs := struct { Attributes Resource `json:"attributes"` }{Attributes: newResource} if unmarshalAttributesErr := json.Unmarshal(data, &resourceAttrs); unmarshalAttributesErr != nil { return unmarshalAttributesErr } return nil } /* func (d *Declaration) MarshalJSON() ([]byte, error) { buf := new(bytes.Buffer) buf.WriteByte('"') buf.WriteString("value")) buf.WriteByte('"') return buf.Bytes(), nil } */ func (d *Declaration) MarshalYAML() (any, error) { return d, nil }