func (m *Manager) RunEntityChain(chain string, de *pb.Entity) (*pb.Entity, error) {
	e := new(pb.Entity)
	hookChain := m.entityProcesses[chain]
	for _, h := range hookChain {
		m.log.Trace("Executing entity hook", "chain", chain, "hook", h.Name())
		if err := h.Run(e, de); err != nil {
			m.log.Trace("Error during chain execution", "chain", chain, "hook", h.Name(), "error", err)
			return nil, err
		}
	}
	return e, nil
}
RunEntityChain runs the specified chain with de specifying values
to be consumed by the chain.
package tree
import (
	"sort"
	pb "github.com/netauth/protocol"
)
type EntityHookConstructor func(RefContext) (EntityHook, error)
type EntityHook interface {
	Priority() int
	Name() string
	Run(*pb.Entity, *pb.Entity) error
}
var (
	eHookConstructors map[string]EntityHookConstructor
)
func init() {
	eHookConstructors = make(map[string]EntityHookConstructor)
}
func RegisterEntityHookConstructor(name string, c EntityHookConstructor) {
	if _, ok := eHookConstructors[name]; ok {
		log().Trace("Duplicate EntityHookConstructor registration attempt", "hook", name)
		return
	}
	eHookConstructors[name] = c
	log().Trace("EntityHookConstructor registered", "constructor", name)
}
func (m *Manager) InitializeEntityHooks() {
	m.log.Debug("Executing EntityHookConstructor callbacks")
	for _, v := range eHookConstructors {
		hook, err := v(m.refContext)
		if err != nil {
			m.log.Warn("Error initializing hook", "hook", hook, "error", err)
			continue
		}
		m.entityHooks[hook.Name()] = hook
		m.log.Trace("EntityHook registered", "hook", hook.Name())
	}
}
func (m *Manager) InitializeEntityChains(c ChainConfig) error {
	for chain, hooks := range c {
		m.log.Debug("Initializing Entity Chain", "chain", chain)
		for _, h := range hooks {
			if err := m.RegisterEntityHookToChain(h, chain); err != nil {
				return err
			}
		}
	}
	return nil
}
func (m *Manager) RegisterEntityHookToChain(hook, chain string) error {
	eph, ok := m.entityHooks[hook]
	if !ok {
		m.log.Warn("Missing hook during chain initializtion", "chain", chain, "hook", hook)
		return ErrUnknownHook
	}
	m.entityProcesses[chain] = append(m.entityProcesses[chain], eph)
	sort.Slice(m.entityProcesses[chain], func(i, j int) bool {
		return m.entityProcesses[chain][i].Priority() < m.entityProcesses[chain][j].Priority()
	})
	m.log.Trace("Registered hook to chain", "chain", chain, "hook", hook)
	return nil
}
func (m *Manager) CheckRequiredEntityChains() error {
	for k := range defaultEntityChains {
		if _, ok := m.entityProcesses[k]; !ok {
			m.log.Error("Missing required chain", "chain", k)
			return ErrUnknownHookChain
		}
		if len(m.entityProcesses[k]) == 0 {
			m.log.Error("A required chain is empty", "chain", k)
			return ErrEmptyHookChain
		}
	}
	return nil
}