go-hep.org/x/hep@v0.38.1/fwk/job/job.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 job // import "go-hep.org/x/hep/fwk/job"
     6  
     7  import (
     8  	"fmt"
     9  
    10  	"go-hep.org/x/hep/fwk"
    11  )
    12  
    13  // C describes the configuration data of a fwk.Component
    14  type C struct {
    15  	Name  string // name of the fwk.Component to create (eg "my-propagator")
    16  	Type  string // type of the fwk.Component to create (eg "go-hep.org/x/hep/fads.Propagator")
    17  	Props P      // properties of the fwk.Component to create
    18  }
    19  
    20  // P holds the configuration data (the properties) of a fwk.Component
    21  // a map of key-value pairs.
    22  type P map[string]any
    23  
    24  // Job is the go-based scripting interface to create, configure and run a fwk.App.
    25  type Job struct {
    26  	stmts []Stmt
    27  	app   fwk.App
    28  }
    29  
    30  func newJob(app fwk.App, props P) *Job {
    31  	if app == nil {
    32  		app = fwk.NewApp()
    33  	}
    34  
    35  	job := &Job{
    36  		stmts: []Stmt{
    37  			{
    38  				Type: StmtNewApp,
    39  				Data: C{
    40  					Name:  app.Name(),
    41  					Type:  app.Type(),
    42  					Props: props,
    43  				},
    44  			},
    45  		},
    46  		app: app,
    47  	}
    48  	for k, v := range props {
    49  		job.setProp(app, k, v)
    50  	}
    51  	return job
    52  }
    53  
    54  // NewJob create a new Job from the given fwk.App value
    55  // and configures it with the given properties P.
    56  func NewJob(app fwk.App, props P) *Job {
    57  	return newJob(app, props)
    58  }
    59  
    60  // New create a new Job with the default fwk.App implementation
    61  // and configures it with the given properties P.
    62  func New(props P) *Job {
    63  	return newJob(nil, props)
    64  }
    65  
    66  // App returns the underlying fwk.App value of this Job.
    67  func (job *Job) App() fwk.App {
    68  	return job.app
    69  }
    70  
    71  // UI returns a fwk Scripter
    72  func (job *Job) UI() UI {
    73  	return UI{job.app.Scripter()}
    74  }
    75  
    76  // Create creates a fwk.Component according to the configuration
    77  // data held by cfg.
    78  // Create panics if no such component was registered with fwk.
    79  func (job *Job) Create(cfg C) fwk.Component {
    80  	c, err := job.app.New(cfg.Type, cfg.Name)
    81  	if err != nil {
    82  		job.Errorf("could not create [%s:%s]: %w\n", cfg.Type, cfg.Name, err)
    83  		panic(err)
    84  	}
    85  	if cfg.Props == nil {
    86  		return c
    87  	}
    88  
    89  	for k, v := range cfg.Props {
    90  		job.setProp(c, k, v)
    91  	}
    92  
    93  	job.stmts = append(job.stmts, Stmt{
    94  		Type: StmtCreate,
    95  		Data: cfg,
    96  	})
    97  	return c
    98  }
    99  
   100  // SetProp sets the property name of the component c with the value v.
   101  // SetProp panics if the component does not have such property or
   102  // if the types do not match.
   103  func (job *Job) SetProp(c fwk.Component, name string, value any) {
   104  	job.setProp(c, name, value)
   105  	job.stmts = append(job.stmts, Stmt{
   106  		Type: StmtSetProp,
   107  		Data: C{
   108  			Type: c.Type(),
   109  			Name: c.Name(),
   110  			Props: P{
   111  				name: value,
   112  			},
   113  		},
   114  	})
   115  }
   116  
   117  func (job *Job) setProp(c fwk.Component, name string, value any) {
   118  	if !job.app.HasProp(c, name) {
   119  		err := fmt.Errorf("component [%s:%s] has no property named %q",
   120  			c.Type(),
   121  			c.Name(),
   122  			name,
   123  		)
   124  		job.Errorf("%+v", err)
   125  		panic(err)
   126  	}
   127  
   128  	err := job.app.SetProp(c, name, value)
   129  	if err != nil {
   130  		job.Errorf(
   131  			"could not set property name=%q value=%#v on component [%s]: %+v\n",
   132  			name, value,
   133  			c.Name(),
   134  			err,
   135  		)
   136  		panic(err)
   137  	}
   138  }
   139  
   140  // Run runs the underlying fwk.App.
   141  // Run panics if an error occurred during any of the execution
   142  // stages of the application.
   143  func (job *Job) Run() {
   144  	err := job.app.Run()
   145  	if err != nil {
   146  		job.Errorf(
   147  			"could not run job: %+v\n",
   148  			err,
   149  		)
   150  		panic(err)
   151  	}
   152  }
   153  
   154  // Stmts returns the list of statements this Job has seen so far.
   155  func (job *Job) Stmts() []Stmt {
   156  	stmts := make([]Stmt, len(job.stmts))
   157  	copy(stmts, job.stmts)
   158  	return stmts
   159  }
   160  
   161  // Debugf displays a (formated) DBG message
   162  func (job *Job) Debugf(format string, a ...any) {
   163  	job.app.Msg().Debugf(format, a...)
   164  }
   165  
   166  // Infof displays a (formated) INFO message
   167  func (job *Job) Infof(format string, a ...any) {
   168  	job.app.Msg().Infof(format, a...)
   169  }
   170  
   171  // Warnf displays a (formated) WARN message
   172  func (job *Job) Warnf(format string, a ...any) {
   173  	job.app.Msg().Warnf(format, a...)
   174  }
   175  
   176  // Errorf displays a (formated) ERR message
   177  func (job *Job) Errorf(format string, a ...any) {
   178  	job.app.Msg().Errorf(format, a...)
   179  }
   180  
   181  /*
   182  func (job *Job) Load(r io.Reader) error {
   183  	var err error
   184  	panic("not implemented")
   185  	return err
   186  }
   187  
   188  func (job *Job) RunScripts(files ...string) error {
   189  	var err error
   190  	panic("not implemented")
   191  	return err
   192  }
   193  */