package processors import ( "fmt" "strings" ) type Registry struct { byDriver map[string]Factory } func NewRegistry() *Registry { return &Registry{byDriver: map[string]Factory{}} } // Register associates a processor driver name with a factory. // // Register panics for empty driver names, nil factories, and duplicates. func (r *Registry) Register(driver string, f Factory) { if r == nil { panic("processors.Registry.Register: registry cannot be nil") } driver = strings.TrimSpace(driver) if driver == "" { panic("processors.Registry.Register: driver cannot be empty") } if f == nil { panic(fmt.Sprintf("processors.Registry.Register: factory cannot be nil (driver=%q)", driver)) } if r.byDriver == nil { r.byDriver = map[string]Factory{} } if _, exists := r.byDriver[driver]; exists { panic(fmt.Sprintf("processors.Registry.Register: driver %q already registered", driver)) } r.byDriver[driver] = f } // Build constructs a Processor by driver name. func (r *Registry) Build(driver string) (Processor, error) { if r == nil { return nil, fmt.Errorf("processors registry is nil") } driver = strings.TrimSpace(driver) f, ok := r.byDriver[driver] if !ok { return nil, fmt.Errorf("unknown processor driver: %q", driver) } p, err := f() if err != nil { return nil, fmt.Errorf("build processor %q: %w", driver, err) } if p == nil { return nil, fmt.Errorf("build processor %q: factory returned nil processor", driver) } return p, nil } // BuildChain constructs an ordered processor chain from a driver list. func (r *Registry) BuildChain(drivers []string) ([]Processor, error) { out := make([]Processor, 0, len(drivers)) for i, driver := range drivers { p, err := r.Build(driver) if err != nil { return nil, fmt.Errorf("build processor chain[%d] (%q): %w", i, strings.TrimSpace(driver), err) } out = append(out, p) } return out, nil }