70 lines
2.1 KiB
Go
70 lines
2.1 KiB
Go
// Package component holds the main abstraction for components.
|
|
package component
|
|
|
|
import (
|
|
"reflect"
|
|
|
|
"github.com/FAU-CDI/wisski-distillery/pkg/lazy"
|
|
)
|
|
|
|
// Component represents a logical subsystem of the distillery.
|
|
// Every component must embed [ComponentBase] and should be initialized using [Initialize].
|
|
//
|
|
// By convention these are defined within their corresponding subpackage.
|
|
// This subpackage also contains all required resources.
|
|
// Furthermore, a component is typically instantiated using a call on the ["distillery.Distillery"] struct.
|
|
//
|
|
// For example, the web.Web component lives in the web package and can be created like:
|
|
//
|
|
// var dis Distillery
|
|
// web := dis.Web()
|
|
type Component interface {
|
|
// Name returns the name of this component.
|
|
// It should correspond to the appropriate subpackage.
|
|
Name() string
|
|
|
|
// getBase returns the embedded ComponentBase struct.
|
|
getBase() *ComponentBase
|
|
}
|
|
|
|
// ComponentBase should be embedded into every component
|
|
type ComponentBase struct {
|
|
Core // the core of the associated distillery
|
|
}
|
|
|
|
//lint:ignore U1000 used to implement the private methods of [Component]
|
|
func (cb *ComponentBase) getBase() *ComponentBase {
|
|
return cb
|
|
}
|
|
|
|
// Initialize makes or returns a component based on a lazy.
|
|
//
|
|
// C is the type of component to initialize. It must be backed by a pointer, or Initialize will panic.
|
|
//
|
|
// dis is the distillery to initialize components for
|
|
// field is a pointer to the appropriate struct field within the distillery components
|
|
// init is called with a new non-nil component to initialize it.
|
|
// It may be nil, to indicate no additional initialization is required.
|
|
//
|
|
// makeComponent returns the new or existing component instance
|
|
func Initialize[C Component](core Core, field *lazy.Lazy[C], init func(C)) C {
|
|
|
|
// get the typeof C and make sure that it is a pointer type!
|
|
typC := reflect.TypeOf((*C)(nil)).Elem()
|
|
if typC.Kind() != reflect.Pointer {
|
|
panic("Initialize: C must be backed by a pointer")
|
|
}
|
|
|
|
// return the field
|
|
return field.Get(func() (c C) {
|
|
c = reflect.New(typC.Elem()).Interface().(C)
|
|
if init != nil {
|
|
init(c)
|
|
}
|
|
|
|
base := c.getBase()
|
|
base.Core = core
|
|
|
|
return
|
|
})
|
|
}
|