smart_container 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +15 -0
  5. data/.travis.yml +28 -0
  6. data/CHANGELOG.md +6 -0
  7. data/CODE_OF_CONDUCT.md +74 -0
  8. data/Gemfile +4 -0
  9. data/Gemfile.lock +83 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +39 -0
  12. data/Rakefile +21 -0
  13. data/bin/console +8 -0
  14. data/bin/setup +8 -0
  15. data/lib/smart_core/container.rb +135 -0
  16. data/lib/smart_core/container/arbitary_lock.rb +22 -0
  17. data/lib/smart_core/container/definition_dsl.rb +109 -0
  18. data/lib/smart_core/container/definition_dsl/command_set.rb +87 -0
  19. data/lib/smart_core/container/definition_dsl/commands.rb +9 -0
  20. data/lib/smart_core/container/definition_dsl/commands/base.rb +48 -0
  21. data/lib/smart_core/container/definition_dsl/commands/definition.rb +9 -0
  22. data/lib/smart_core/container/definition_dsl/commands/definition/compose.rb +49 -0
  23. data/lib/smart_core/container/definition_dsl/commands/definition/namespace.rb +54 -0
  24. data/lib/smart_core/container/definition_dsl/commands/definition/register.rb +54 -0
  25. data/lib/smart_core/container/definition_dsl/commands/instantiation.rb +8 -0
  26. data/lib/smart_core/container/definition_dsl/commands/instantiation/compose.rb +53 -0
  27. data/lib/smart_core/container/definition_dsl/commands/instantiation/freeze_state.rb +27 -0
  28. data/lib/smart_core/container/definition_dsl/inheritance.rb +23 -0
  29. data/lib/smart_core/container/dependency_compatability.rb +9 -0
  30. data/lib/smart_core/container/dependency_compatability/definition.rb +38 -0
  31. data/lib/smart_core/container/dependency_compatability/general.rb +61 -0
  32. data/lib/smart_core/container/dependency_compatability/registry.rb +36 -0
  33. data/lib/smart_core/container/dependency_resolver.rb +93 -0
  34. data/lib/smart_core/container/dependency_resolver/route.rb +83 -0
  35. data/lib/smart_core/container/dependency_resolver/route/cursor.rb +47 -0
  36. data/lib/smart_core/container/entities.rb +11 -0
  37. data/lib/smart_core/container/entities/base.rb +26 -0
  38. data/lib/smart_core/container/entities/dependency.rb +38 -0
  39. data/lib/smart_core/container/entities/dependency_builder.rb +50 -0
  40. data/lib/smart_core/container/entities/namespace.rb +73 -0
  41. data/lib/smart_core/container/entities/namespace_builder.rb +41 -0
  42. data/lib/smart_core/container/errors.rb +65 -0
  43. data/lib/smart_core/container/key_guard.rb +31 -0
  44. data/lib/smart_core/container/mixin.rb +83 -0
  45. data/lib/smart_core/container/registry.rb +250 -0
  46. data/lib/smart_core/container/registry_builder.rb +51 -0
  47. data/lib/smart_core/container/version.rb +9 -0
  48. data/smart_container.gemspec +38 -0
  49. metadata +191 -0
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Container::ArbitaryLock
6
+ # @return [void]
7
+ #
8
+ # @api private
9
+ # @since 0.1.0
10
+ def initialize
11
+ @lock = Mutex.new
12
+ end
13
+
14
+ # @param block [Proc]
15
+ # @return [Any]
16
+ #
17
+ # @api private
18
+ # @since 0.1.0
19
+ def thread_safe(&block)
20
+ @lock.owned? ? yield : @lock.synchronize(&block)
21
+ end
22
+ end
@@ -0,0 +1,109 @@
1
+ # frozen_string_literal: true
2
+
3
+ class SmartCore::Container
4
+ # @api private
5
+ # @since 0.1.0
6
+ module DefinitionDSL
7
+ require_relative 'definition_dsl/commands'
8
+ require_relative 'definition_dsl/command_set'
9
+ require_relative 'definition_dsl/inheritance'
10
+
11
+ class << self
12
+ # @param base_klass [Class<SmartCore::Container>]
13
+ # @return [void]
14
+ #
15
+ # @api private
16
+ # @since 0.1.0
17
+ def included(base_klass)
18
+ base_klass.instance_variable_set(:@__container_definition_commands__, CommandSet.new)
19
+ base_klass.instance_variable_set(:@__container_instantiation_commands__, CommandSet.new)
20
+ base_klass.instance_variable_set(:@__container_definition_lock__, ArbitaryLock.new)
21
+ base_klass.singleton_class.send(:attr_reader, :__container_definition_commands__)
22
+ base_klass.singleton_class.send(:attr_reader, :__container_instantiation_commands__)
23
+ base_klass.extend(ClassMethods)
24
+ base_klass.singleton_class.prepend(ClassInheritance)
25
+ end
26
+ end
27
+
28
+ # @api private
29
+ # @since 0.1.0
30
+ module ClassInheritance
31
+ # @param child_klass [Class<SmartCore::Container>]
32
+ # @return [void]
33
+ #
34
+ # @api private
35
+ # @since 0.1.0
36
+ def inherited(child_klass)
37
+ child_klass.instance_variable_set(:@__container_definition_commands__, CommandSet.new)
38
+ child_klass.instance_variable_set(:@__container_instantiation_commands__, CommandSet.new)
39
+ child_klass.instance_variable_set(:@__container_definition_lock__, ArbitaryLock.new)
40
+ SmartCore::Container::DefinitionDSL::Inheritance.inherit(base: self, child: child_klass)
41
+ child_klass.singleton_class.prepend(ClassInheritance)
42
+ super
43
+ end
44
+ end
45
+
46
+ # @api private
47
+ # @since 0.1.0
48
+ module ClassMethods
49
+ # @param namespace_name [String, Symbol]
50
+ # @param dependencies_definition [Block]
51
+ # @return [void]
52
+ #
53
+ # @api public
54
+ # @since 0.1.0
55
+ def namespace(namespace_name, &dependencies_definition)
56
+ @__container_definition_lock__.thread_safe do
57
+ DependencyCompatability::Definition.prevent_dependency_overlap!(self, namespace_name)
58
+
59
+ __container_definition_commands__ << Commands::Definition::Namespace.new(
60
+ namespace_name, dependencies_definition
61
+ )
62
+ end
63
+ end
64
+
65
+ # @param dependency_name [String, Symbol]
66
+ # @param dependency_definition [Block]
67
+ # @return [void]
68
+ #
69
+ # @api public
70
+ # @since 0.1.0
71
+ def register(dependency_name, &dependency_definition)
72
+ @__container_definition_lock__.thread_safe do
73
+ DependencyCompatability::Definition.prevent_namespace_overlap!(self, dependency_name)
74
+
75
+ __container_definition_commands__ << Commands::Definition::Register.new(
76
+ dependency_name, dependency_definition
77
+ )
78
+ end
79
+ end
80
+
81
+ # @param container_klass [Class<SmartCore::Container>]
82
+ # @return [void]
83
+ #
84
+ # @api public
85
+ # @since 0.1.0
86
+ def compose(container_klass)
87
+ @__container_definition_lock__.thread_safe do
88
+ __container_definition_commands__ << Commands::Definition::Compose.new(
89
+ container_klass
90
+ )
91
+
92
+ __container_instantiation_commands__ << Commands::Instantiation::Compose.new(
93
+ container_klass
94
+ )
95
+ end
96
+ end
97
+
98
+ # @return [void]
99
+ #
100
+ # @api public
101
+ # @since 0.1.0
102
+ def freeze_state!
103
+ @__container_definition_lock__.thread_safe do
104
+ __container_instantiation_commands__ << Commands::Instantiation::FreezeState.new
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Container::DefinitionDSL::CommandSet
6
+ # @since 0.1.0
7
+ include Enumerable
8
+
9
+ # @return [Array<SmartCore::Container::DefinitionDSL::Commands::Base>]
10
+ #
11
+ # @api private
12
+ # @since 0.1.0
13
+ attr_reader :commands
14
+
15
+ # @return [void]
16
+ #
17
+ # @api private
18
+ # @since 0.1.0
19
+ def initialize
20
+ @commands = []
21
+ @access_lock = SmartCore::Container::ArbitaryLock.new
22
+ end
23
+
24
+ # @param [SmartCore::Container::DefinitionDSL::Commands::Base]
25
+ # @return [void]
26
+ #
27
+ # @api private
28
+ # @since 0.1.0
29
+ def add_command(command)
30
+ thread_safe { commands << command }
31
+ end
32
+ alias_method :<<, :add_command
33
+
34
+ # @param block [Block]
35
+ # @return [Enumerable]
36
+ #
37
+ # @api private
38
+ # @since 0.1.0
39
+ def each(&block)
40
+ thread_safe { block_given? ? commands.each(&block) : commands.each }
41
+ end
42
+
43
+ # @param command_set [SmartCore::Container::DefinitionDSL::CommandSet]
44
+ # @param concat_condition [Block]
45
+ # @yield [command]
46
+ # @yieldparam command [SmartCore::Container::DefinitionDSL::Commands::Base]
47
+ # @return [void]
48
+ #
49
+ # @api private
50
+ # @since 0.1.0
51
+ def concat(command_set, &concat_condition)
52
+ thread_safe do
53
+ if block_given?
54
+ command_set.dup.each { |command| (commands << command) if yield(command) }
55
+ else
56
+ # :nocov:
57
+ commands.concat(command_set.dup.commands) # NOTE: unreachable code at this moment
58
+ # :nocov:
59
+ end
60
+ end
61
+ end
62
+
63
+ # @return [SmartCore::Container::DefinitionDSL::CommandSet]
64
+ #
65
+ # @api private
66
+ # @since 0.1.0
67
+ def dup
68
+ thread_safe do
69
+ self.class.new.tap do |duplicate|
70
+ commands.each do |command|
71
+ duplicate.add_command(command.dup)
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ # @param block [Block]
80
+ # @return [Any]
81
+ #
82
+ # @api private
83
+ # @since 0.1.0
84
+ def thread_safe(&block)
85
+ @access_lock.thread_safe(&block)
86
+ end
87
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Container::DefinitionDSL::Commands
6
+ require_relative 'commands/base'
7
+ require_relative 'commands/instantiation'
8
+ require_relative 'commands/definition'
9
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ class SmartCore::Container::DefinitionDSL::Commands::Base
6
+ class << self
7
+ # @param identifier [Boolean]
8
+ # @return [Boolean]
9
+ #
10
+ # @api private
11
+ # @since 0.19.0
12
+ def inheritable=(identifier)
13
+ @inheritable = identifier
14
+ end
15
+
16
+ # @return [Boolean]
17
+ #
18
+ # @api private
19
+ # @since 0.19.0
20
+ def inheritable?
21
+ @inheritable
22
+ end
23
+
24
+ # @return [Boolean]
25
+ #
26
+ # @api private
27
+ # @since 0.19.0
28
+ def inherited(child_klass)
29
+ child_klass.instance_variable_set(:@inheritable, true)
30
+ super
31
+ end
32
+ end
33
+
34
+ # @param regsitry [SmartCore::Container::Registry]
35
+ # @return [void]
36
+ #
37
+ # @api private
38
+ # @since 0.1.0
39
+ def call(registry); end
40
+
41
+ # @return [Boolean]
42
+ #
43
+ # @api private
44
+ # @since 0.19.0
45
+ def inheritable?
46
+ self.class.inheritable?
47
+ end
48
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # @api private
4
+ # @since 0.1.0
5
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
6
+ require_relative 'definition/namespace'
7
+ require_relative 'definition/register'
8
+ require_relative 'definition/compose'
9
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Compose < SmartCore::Container::DefinitionDSL::Commands::Base
7
+ # @since 0.1.0
8
+ self.inheritable = true
9
+
10
+ # @param container_klass [Class<SmartCore::Container>]
11
+ # @return [void]
12
+ #
13
+ # @api private
14
+ # @since 0.1.0
15
+ def initialize(container_klass)
16
+ raise(
17
+ SmartCore::ArgumentError,
18
+ 'Container class should be a subtype of Quantum::Container'
19
+ ) unless container_klass < SmartCore::Container
20
+
21
+ @container_klass = container_klass
22
+ end
23
+
24
+ # @param registry [SmartCore::Container::Registry]
25
+ # @return [void]
26
+ #
27
+ # @api private
28
+ # @since 0.1.0
29
+ def call(registry)
30
+ SmartCore::Container::RegistryBuilder.build_definitions(container_klass, registry)
31
+ end
32
+
33
+ # @return [SmartCore::Container::DefinitionDSL::Commands::Definition::Compose]
34
+ #
35
+ # @api private
36
+ # @since 0.1.0
37
+ def dup
38
+ self.class.new(container_klass)
39
+ end
40
+
41
+ private
42
+
43
+ # @return [Class<SmartCore::Container>]
44
+ #
45
+ # @api private
46
+ # @since 0.1.0
47
+ attr_reader :container_klass
48
+ end
49
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Namespace < SmartCore::Container::DefinitionDSL::Commands::Base
7
+ # @since 0.1.0
8
+ self.inheritable = true
9
+
10
+ # @return [String]
11
+ #
12
+ # @api private
13
+ # @since 0.1.0
14
+ attr_reader :namespace_name
15
+
16
+ # @param namespace_name [String, Symbol]
17
+ # @param dependencies_definition [Proc]
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.1.0
22
+ def initialize(namespace_name, dependencies_definition)
23
+ SmartCore::Container::KeyGuard.indifferently_accessable_key(namespace_name).tap do |name|
24
+ @namespace_name = name
25
+ @dependencies_definition = dependencies_definition
26
+ end
27
+ end
28
+
29
+ # @param registry [SmartCore::Container::Registry]
30
+ # @return [void]
31
+ #
32
+ # @api private
33
+ # @since 0.1.0
34
+ def call(registry)
35
+ registry.register_namespace(namespace_name, &dependencies_definition)
36
+ end
37
+
38
+ # @return [SmartCore::Container::DefinitionDSL::Commands::Definition::Namespace]
39
+ #
40
+ # @api private
41
+ # @since 0.1.0
42
+ def dup
43
+ self.class.new(namespace_name, dependencies_definition)
44
+ end
45
+
46
+ private
47
+
48
+ # @return [Proc]
49
+ #
50
+ # @api private
51
+ # @since 0.1.0
52
+ attr_reader :dependencies_definition
53
+ end
54
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module SmartCore::Container::DefinitionDSL::Commands::Definition
4
+ # @api private
5
+ # @since 0.1.0
6
+ class Register < SmartCore::Container::DefinitionDSL::Commands::Base
7
+ # @since 0.1.0
8
+ self.inheritable = true
9
+
10
+ # @return [String]
11
+ #
12
+ # @api private
13
+ # @since 0.1.0
14
+ attr_reader :dependency_name
15
+
16
+ # @param dependency_name [String, Symbol]
17
+ # @param dependency_definition [Proc]
18
+ # @return [void]
19
+ #
20
+ # @api private
21
+ # @since 0.1.0
22
+ def initialize(dependency_name, dependency_definition)
23
+ SmartCore::Container::KeyGuard.indifferently_accessable_key(dependency_name).tap do |name|
24
+ @dependency_name = name
25
+ @dependency_definition = dependency_definition
26
+ end
27
+ end
28
+
29
+ # @param registry [SmartCore::Container::Registry]
30
+ # @return [void]
31
+ #
32
+ # @api private
33
+ # @since 0.1.0
34
+ def call(registry)
35
+ registry.register_dependency(dependency_name, &dependency_definition)
36
+ end
37
+
38
+ # @return [SmartCore::Container::DefinitionDSL::Commands::Definition::Register]
39
+ #
40
+ # @api private
41
+ # @since 0.1.0
42
+ def dup
43
+ self.class.new(dependency_name, dependency_definition)
44
+ end
45
+
46
+ private
47
+
48
+ # @return [Proc]
49
+ #
50
+ # @api private
51
+ # @since 0.1.0
52
+ attr_reader :dependency_definition
53
+ end
54
+ end