go-hep.org/x/hep@v0.38.1/fwk/registry.go (about)

     1  // Copyright ©2017 The go-hep Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package fwk
     6  
     7  import (
     8  	"fmt"
     9  	"reflect"
    10  	"sort"
    11  )
    12  
    13  // FactoryFunc creates a Component of type t and name n, managed by the fwk.App mgr.
    14  type FactoryFunc func(t, n string, mgr App) (Component, error)
    15  
    16  // factoryDb associates a fully-qualified type-name (pkg-path + type-name) with
    17  // a component factory-function.
    18  type factoryDb map[string]FactoryFunc
    19  
    20  var gFactory = make(factoryDb)
    21  
    22  // Register registers a type t with the FactoryFunc fct.
    23  //
    24  // fwk.ComponentMgr will then be able to create new values of that type t
    25  // using the associated FactoryFunc fct.
    26  // If a type t was already registered, the previous FactoryFunc value will be
    27  // silently overridden with the new FactoryFunc value.
    28  func Register(t reflect.Type, fct FactoryFunc) {
    29  	comp := t.PkgPath() + "." + t.Name()
    30  	gFactory[comp] = fct
    31  	//fmt.Printf("### factories ###\n%v\n", gFactory)
    32  }
    33  
    34  // Registry returns the list of all registered and known components.
    35  func Registry() []string {
    36  	comps := make([]string, 0, len(gFactory))
    37  	for k := range gFactory {
    38  		comps = append(comps, k)
    39  	}
    40  	sort.Strings(comps)
    41  	return comps
    42  }
    43  
    44  // New creates a new Component value with type t and name n.
    45  func (app *appmgr) New(t, n string) (Component, error) {
    46  	var err error
    47  	fct, ok := gFactory[t]
    48  	if !ok {
    49  		return nil, fmt.Errorf("no component with type [%s] registered", t)
    50  	}
    51  
    52  	if _, dup := app.props[n]; dup {
    53  		return nil, fmt.Errorf("component with name [%s] already created", n)
    54  	}
    55  	app.props[n] = make(map[string]any)
    56  
    57  	c, err := fct(t, n, app)
    58  	if err != nil {
    59  		return nil, fmt.Errorf("error creating [%s:%s]: %w", t, n, err)
    60  	}
    61  	if c.Name() == "" {
    62  		return nil, fmt.Errorf("factory for [%s] does NOT set the name of the component", t)
    63  	}
    64  
    65  	err = app.addComponent(c)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	switch c := c.(type) {
    71  	case Svc:
    72  		err = app.AddSvc(c)
    73  		if err != nil {
    74  			return nil, err
    75  		}
    76  	case Task:
    77  		err = app.AddTask(c)
    78  		if err != nil {
    79  			return nil, err
    80  		}
    81  	}
    82  
    83  	return c, err
    84  }