From 4f80dfb07b253a01a6354bd651759e1e5e73fc24 Mon Sep 17 00:00:00 2001 From: Edward Date: Mon, 11 May 2020 21:23:42 +0800 Subject: [PATCH] Create registry.go --- behavioral/registry/registry.go | 99 +++++++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 behavioral/registry/registry.go diff --git a/behavioral/registry/registry.go b/behavioral/registry/registry.go new file mode 100644 index 0000000..6ea3f8f --- /dev/null +++ b/behavioral/registry/registry.go @@ -0,0 +1,99 @@ +package registry + +import ( + "fmt" + + "github.com/google/uuid" +) + +// IDNotFound is an error thrown when an id is not found in a Registry +type IDNotFound struct { + id string +} + +func (e IDNotFound) Error() string { + return fmt.Sprintf("ID not found in registry: %s", e.id) +} + +// NameAlreadyRegistered is an error thrown when a duplicate id is found durring registration +type NameAlreadyRegistered struct { + id string +} + +func (e NameAlreadyRegistered) Error() string { + return fmt.Sprintf("Identifier was already in registry: %s", e.id) +} + +// Registry acts a generic data registry +// Objects are registered with the underlying struct, which returns an ID string +// The ID string can then be used to retreive the object, or to remove it from the registry +type Registry interface { + + // Deregister removes an item identified by the passed id + Deregister(id string) error + + // Get retreives an item identified by the passed id from the registry + Get(id string) (interface{}, error) + + // Prune removes nil entries from the registry + Prune() + + // Register adds an item to the registry and returns an identifying string + Register(data interface{}) string + + // RegisterName adds an item to the registry under the suppplied identifier and returns an identifying string + // Returns a NameAlreadyRegistered error if the identifier has already been registered + RegisterName(data interface{}, identifier string) error +} + +type registry struct { + registry map[string]interface{} +} + +func (reg *registry) Deregister(id string) error { + if _, ok := reg.registry[id]; ok { + delete(reg.registry, id) + return nil + } + return IDNotFound{id} +} + +func (reg *registry) Get(id string) (interface{}, error) { + if data, ok := reg.registry[id]; ok { + return data, nil + } + return nil, IDNotFound{id} +} + +func (reg *registry) Prune() { + for key, value := range reg.registry { + if value == nil { + delete(reg.registry, key) + } + } +} + +func (reg *registry) Register(data interface{}) string { + // Just in case the impossible happens and there is an id colision + for { + newUUID, _ := uuid.NewRandom() + id := newUUID.String() + if _, ok := reg.registry[id]; !ok { + reg.registry[id] = data + return id + } + } +} + +func (reg *registry) RegisterName(data interface{}, identifier string) error { + if _, ok := reg.registry[identifier]; !ok { + reg.registry[identifier] = data + return nil + } + return NameAlreadyRegistered{identifier} +} + +// New returns a new Registry interface +func New() Registry { + return ®istry{} +}