github.com/insolar/vanilla@v0.0.0-20201023172447-248fdf805322/injector/container_rw.go (about)

     1  // Copyright 2020 Insolar Network Ltd.
     2  // All rights reserved.
     3  // This material is licensed under the Insolar License version 1.0,
     4  // available at https://github.com/insolar/assured-ledger/blob/master/LICENSE.md.
     5  
     6  package injector
     7  
     8  import (
     9  	"fmt"
    10  	"sync"
    11  
    12  	"github.com/insolar/vanilla/throw"
    13  )
    14  
    15  func NewDynamicContainer(parentRegistry DependencyRegistry) *DynamicContainer {
    16  	return &DynamicContainer{ parentRegistry: parentRegistry }
    17  }
    18  
    19  type DynamicContainer struct {
    20  	parentRegistry DependencyRegistry
    21  	localRegistry sync.Map
    22  }
    23  
    24  func (m *DynamicContainer) FindDependency(id string) (interface{}, bool) {
    25  	if m == nil {
    26  		return nil, false
    27  	}
    28  
    29  	if v, ok := m.localRegistry.Load(id); ok {
    30  		return v, true
    31  	}
    32  	if m.parentRegistry != nil {
    33  		return m.parentRegistry.FindDependency(id)
    34  	}
    35  	return nil, false
    36  }
    37  
    38  func (m *DynamicContainer) ScanDependencies(fn func(id string, v interface{}) bool) (found bool) {
    39  	if m == nil {
    40  		return false
    41  	}
    42  
    43  	if fn == nil {
    44  		panic(throw.IllegalValue())
    45  	}
    46  
    47  	m.localRegistry.Range(func(key, value interface{}) bool {
    48  		if fn(key.(string), value) {
    49  			found = true
    50  			return false
    51  		}
    52  		return true
    53  	})
    54  
    55  	if found {
    56  		return true
    57  	}
    58  
    59  	if sp, ok := m.parentRegistry.(ScanDependencyRegistry); ok {
    60  		return sp.ScanDependencies(fn)
    61  	}
    62  	return false
    63  }
    64  
    65  func AddDependency(m DependencyContainer, v interface{}) {
    66  	if !m.TryPutDependency(GetDefaultInjectionID(v), v) {
    67  		panic(fmt.Errorf("duplicate dependency: %T %[1]v", v))
    68  	}
    69  }
    70  
    71  func AddInterfaceDependency(m DependencyContainer, v interface{}) {
    72  	vv, vt := GetInterfaceTypeAndValue(v)
    73  	if !m.TryPutDependency(GetDefaultInjectionIDByType(vt), vv) {
    74  		panic(fmt.Errorf("duplicate dependency: %T %[1]v", v))
    75  	}
    76  }
    77  
    78  func NameOfDependency(v interface{}) string {
    79  	return GetDefaultInjectionID(v)
    80  }
    81  
    82  func NameOfInterfaceDependency(v interface{}) string {
    83  	_, vt := GetInterfaceTypeAndValue(v)
    84  	return GetDefaultInjectionIDByType(vt)
    85  }
    86  
    87  func (m *DynamicContainer) AddDependency(v interface{}) {
    88  	AddDependency(m, v)
    89  }
    90  
    91  func (m *DynamicContainer) AddInterfaceDependency(v interface{}) {
    92  	AddInterfaceDependency(m, v)
    93  }
    94  
    95  func (m *DynamicContainer) PutDependency(id string, v interface{}) {
    96  	if id == "" {
    97  		panic(throw.IllegalValue())
    98  	}
    99  	m.localRegistry.Store(id, v)
   100  }
   101  
   102  func (m *DynamicContainer) TryPutDependency(id string, v interface{}) bool {
   103  	if id == "" {
   104  		panic(throw.IllegalValue())
   105  	}
   106  	_, loaded := m.localRegistry.LoadOrStore(id, v)
   107  	return !loaded
   108  }
   109  
   110  func (m *DynamicContainer) DeleteDependency(id string) {
   111  	m.localRegistry.Delete(id)
   112  }
   113  
   114  func (m *DynamicContainer) CopyAsStatic() StaticContainer {
   115  	if m == nil {
   116  		return NewStaticContainer(nil, nil)
   117  	}
   118  	return NewStaticContainer(m.parentRegistry, m)
   119  }
   120  
   121  func (m *DynamicContainer) ReplaceDependency(v interface{}) {
   122  	id := GetDefaultInjectionID(v)
   123  	m.localRegistry.Delete(id)
   124  	m.PutDependency(id, v)
   125  }
   126  
   127  func (m *DynamicContainer) ReplaceInterfaceDependency(v interface{}) {
   128  	vv, vt := GetInterfaceTypeAndValue(v)
   129  	id := GetDefaultInjectionIDByType(vt)
   130  	m.localRegistry.Delete(id)
   131  	m.PutDependency(id, vv)
   132  }
   133