configmanager 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,27 +1,28 @@
1
- #
2
- # 16 Jul 2012
3
- #
4
-
5
- require "options_arg"
6
-
7
- require "configmanager/configuration"
8
- require "configmanager/loaders"
9
-
10
- # General purpose configuration manager.
11
- # Loads properties from YAML files and makes them available through a same hash like interface.
12
- # Supports ${} and $() style references. All references are evaluated only when a property's value is requested.
13
- module ConfigManager
14
-
15
- # Loads properties from the specified file.
16
- #
17
- # @param [String] file_path the file to load properties from.
18
- # @param [Object] loader any object that can respond to the 'load_properties(file_path, configuration)' method and return a hash.
19
- # @param [ConfigManager::Configuration] configuration the configuration to load the properties into.
20
- #
21
- # @return [ConfigManager::Configuration] the configuration object wrapping the properties loaded from the file.
22
- def self.load_from_file(file_path, loader = YAMLPropertiesLoader, configuration = ConfigManager::Configuration.new())
23
- loader.load_properties(file_path, configuration)
24
- configuration
25
- end
26
-
1
+ #
2
+ # 16 Jul 2012
3
+ #
4
+
5
+ require "rubygems"
6
+ require "options_arg"
7
+
8
+ require "configmanager/configuration"
9
+ require "configmanager/loaders"
10
+
11
+ # General purpose configuration manager.
12
+ # Loads properties from YAML files and makes them available through a same hash like interface.
13
+ # Supports ${} and $() style references. All references are evaluated only when a property's value is requested.
14
+ module ConfigManager
15
+
16
+ # Loads properties from the specified file.
17
+ #
18
+ # @param [String] file_path the file to load properties from.
19
+ # @param [Object] loader any object that can respond to the 'load_properties(file_path, configuration)' method and return a hash.
20
+ # @param [ConfigManager::Configuration] configuration the configuration to load the properties into.
21
+ #
22
+ # @return [ConfigManager::Configuration] the configuration object wrapping the properties loaded from the file.
23
+ def self.load_from_file(file_path, loader = YAMLPropertiesLoader, configuration = ConfigManager::Configuration.new())
24
+ loader.load_properties(file_path, configuration)
25
+ configuration
26
+ end
27
+
27
28
  end
@@ -1,65 +1,65 @@
1
- #
2
- # 20 Jul 2012
3
- #
4
-
5
- require "configmanager/configuration"
6
- require "configmanager/exceptions"
7
-
8
- module ConfigManager
9
-
10
- # A configuration class that can merge multiple configuration trees into a single configuration tree.
11
- # Each addition, overwrites any properties that already existed.
12
- class CombinedConfiguration < ConfigManager::Configuration
13
-
14
- # Creates a new empty combined configuration.
15
- #
16
- # @param [Hash] options configuration options. Supported keys are:
17
- # :interpolator - an object that can respond to the 'interpolate' method. Default is the DefaultInterpolator.
18
- # :use_interpolator - global flag to specify if the interpolator should be used for this configuration. Default is true.
19
- def initialize(options = {})
20
- super
21
-
22
- @configurations = {}
23
- end
24
-
25
- # Adds a configuration to be merged into this configuration. All existing properties are overwritten.
26
- #
27
- # @param [String] name a unique name for this configuration, it can be retrieved later with this name.
28
- # @param [ConfigManager::Configuration] configuration the configuration to be merged.
29
- #
30
- # @return [NilClass]
31
- def add_configuration(name, configuration)
32
- raise ConfigManager::KeyError.new("Cannot add - Configuration '#{name}' already exists!") if @configurations.has_key?(name)
33
- @configurations[name] = configuration
34
- merge_configuration(configuration)
35
-
36
- nil
37
- end
38
-
39
- # Get the configuration identified by the specified name. Raises an exception if the configuration does not exist.
40
- # Modifying the returned configuration does not update this combined configuration.
41
- #
42
- # @param [String] name the configuration to get.
43
- #
44
- # @return [ConfigManager::Configuration] the configuration.
45
- def get_configuration(name)
46
- raise ConfigManager::PropertyNotFoundError("Cannot get - Configuration '#{name}' does not exist!") unless @configurations.has_key?(name)
47
- @configurations[name]
48
- end
49
-
50
- private
51
-
52
- # Merges the specified configuration with this configuration. Existing nodes are overwritten!
53
- #
54
- # @param [ConfigManager::Configuration] configuration the configuration to merge.
55
- #
56
- # @return [NilClass]
57
- def merge_configuration(configuration)
58
- values = configuration.get_property("")
59
- at = ""
60
- add_properties(values, at, :overwrite => true)
61
- end
62
-
63
- end
64
-
65
- end
1
+ #
2
+ # 20 Jul 2012
3
+ #
4
+
5
+ require "configmanager/configuration"
6
+ require "configmanager/exceptions"
7
+
8
+ module ConfigManager
9
+
10
+ # A configuration class that can merge multiple configuration trees into a single configuration tree.
11
+ # Each addition, overwrites any properties that already existed.
12
+ class CombinedConfiguration < ConfigManager::Configuration
13
+
14
+ # Creates a new empty combined configuration.
15
+ #
16
+ # @param [Hash] options configuration options. Supported keys are:
17
+ # :interpolator - an object that can respond to the 'interpolate' method. Default is the DefaultInterpolator.
18
+ # :use_interpolator - global flag to specify if the interpolator should be used for this configuration. Default is true.
19
+ def initialize(options = {})
20
+ super
21
+
22
+ @configurations = {}
23
+ end
24
+
25
+ # Adds a configuration to be merged into this configuration. All existing properties are overwritten.
26
+ #
27
+ # @param [String] name a unique name for this configuration, it can be retrieved later with this name.
28
+ # @param [ConfigManager::Configuration] configuration the configuration to be merged.
29
+ #
30
+ # @return [NilClass]
31
+ def add_configuration(name, configuration)
32
+ raise ConfigManager::KeyError.new("Cannot add - Configuration '#{name}' already exists!") if @configurations.has_key?(name)
33
+ @configurations[name] = configuration
34
+ merge_configuration(configuration)
35
+
36
+ nil
37
+ end
38
+
39
+ # Get the configuration identified by the specified name. Raises an exception if the configuration does not exist.
40
+ # Modifying the returned configuration does not update this combined configuration.
41
+ #
42
+ # @param [String] name the configuration to get.
43
+ #
44
+ # @return [ConfigManager::Configuration] the configuration.
45
+ def get_configuration(name)
46
+ raise ConfigManager::PropertyNotFoundError("Cannot get - Configuration '#{name}' does not exist!") unless @configurations.has_key?(name)
47
+ @configurations[name]
48
+ end
49
+
50
+ private
51
+
52
+ # Merges the specified configuration with this configuration. Existing nodes are overwritten!
53
+ #
54
+ # @param [ConfigManager::Configuration] configuration the configuration to merge.
55
+ #
56
+ # @return [NilClass]
57
+ def merge_configuration(configuration)
58
+ values = configuration.get_property("")
59
+ at = ""
60
+ add_properties(values, at, :overwrite => true)
61
+ end
62
+
63
+ end
64
+
65
+ end
@@ -1,165 +1,168 @@
1
- #
2
- # 20 Jul 2012
3
- #
4
-
5
- require "configmanager/exceptions"
6
- require "configmanager/interpolators"
7
-
8
- module ConfigManager
9
-
10
- # Represents a collection of properties stored as a hash.
11
- class Configuration
12
-
13
- # Creates a new empty configuration.
14
- #
15
- # @param [Hash] options configuration options. Supported keys are:
16
- # :interpolator - an object that can respond to the 'interpolate' method. Default is the DefaultInterpolator.
17
- # :use_interpolator - global flag to specify if the interpolator should be used for this configuration. Default is true.
18
- def initialize(options = {})
19
- @root = {}
20
- @use_interpolator = get_option(options, :use_interpolator, false, true)
21
- @interpolator = get_option(options, :interpolator, false, ConfigManager::DefaultInterpolator)
22
- end
23
-
24
- # Adds a hash of properties to this configuration.
25
- #
26
- # @param [Hash] values the values to add to this configuration.
27
- # @param [String] at the node under which to add these properties. Default is the root node.
28
- # @param [Hash] options configuration options. Supported key are
29
- # :overwrite - true to overwrite existing properties, false to raise an exception if a property exists. Default is false.
30
- #
31
- # @return [NilClass]
32
- def add_properties(values, at = "", options = {})
33
- # Add each item in the hash - Nested hashes call this method recursively.
34
- at_array = at.split(".")
35
- values.each_pair do |key, value|
36
- full_key = (at_array + [key]).join(".")
37
- value.kind_of?(Hash) ? add_properties(value, full_key, options) : add_property(full_key, value, options)
38
- end
39
-
40
- nil
41
- end
42
-
43
- # Adds a property to this configuration. The key is a '.' separated string that fully qualifies this property.
44
- # So the property a.b identifies the property 'b' inside the group 'a'. Similarly a.b.c identifies the property
45
- # 'c' inside the group 'b' which is inside the group 'a'.
46
- #
47
- # @param [String] key the unique key to identify this property.
48
- # @param [Object] value the value of this property.
49
- # @param [Hash] options configuration options. Supported keys are:
50
- # :overwrite - true to overwrite existing properties, false to raise an exception if a property exists. Default is false.
51
- # :at - an optional node's name under which to add this property. Default is the root node.
52
- #
53
- # @return [NilClass]
54
- def add_property(key, value, options = {})
55
- # Default options.
56
- at = get_option(options, :at, false, "")
57
- overwrite = get_option(options, :overwrite, false, false)
58
- # Create and add the property.
59
- key_array = key.split(".")
60
- at_array = at.split(".")
61
- leaf = key_array[-1]
62
- at_array = at_array + key_array[0..-2]
63
- at_node = get_node(at_array, create = true)
64
- # Got the node, now add the property, unless it already exists.
65
- raise ConfigManager::KeyError.new("Cannot add - '#{at_array.join(".")}.#{leaf}' already exists!") if at_node.has_key?(leaf) and not overwrite
66
- at_node[leaf] = value
67
-
68
- nil
69
- end
70
-
71
- # Get the value of the specified property. The key is a '.' separated string that fully qualifies this property.
72
- # So the property a.b identifies the property 'b' inside the group 'a'. Similarly a.b.c identifies the property
73
- # 'c' inside the group 'b' which is inside the group 'a'.
74
- #
75
- # If enabled, the property's value is interpolated.
76
- # Finally the list of post-processors are invoked and the value is returned.
77
- #
78
- # @param [String] key the property to get.
79
- # @param [Hash] options configuration options. Supported keys are:
80
- # :use_interpolator - flag to indicate if the interpolator should be used. Uses the value specified when creating this configuration by default.
81
- # :interpolator - the interpolator to use. Uses the value specified when creating this configuration by default.
82
- # :post_processors - an array of callable procs. Each one is invoked with the output of the previous one. The first one is invoked with the fully interpolated value.
83
- # :replacements - a hash containing replacement values for references. References are looked up in this before being looked up in this configuration.
84
- # :tolerate_missing_references: a flag to indicate if missing references should raise an exception.
85
- #
86
- # Note : Interpolator implementations may support additional options too.
87
- #
88
- # @return [Object] the property's value.
89
- def get_property(key, options = {})
90
- use_interpolator = get_option(options, :use_interpolator, false, @use_interpolator)
91
- interpolator = get_option(options, :interpolator, false, @interpolator)
92
- post_processors = pop_option(options, :post_processors, false, [])
93
- # Get the required property's raw value.
94
- key_array = key.split(".")
95
- create = false
96
- raw_value = get_node(key_array, create)
97
- # Interpolate.
98
- raw_value = interpolator.interpolate(key, raw_value, self, options) if use_interpolator
99
- # Post-process.
100
- final_value = raw_value
101
- post_processors.each { |processor| final_value = processor.call(final_value) }
102
- # All done.
103
- final_value
104
- end
105
-
106
- # Check to see if the specified property is defined for this configuration. This method will throw an exception if
107
- # the key is invalid.
108
- #
109
- # @param [String] key the property to check.
110
- #
111
- # @return [TrueClass, FalseClass] true if the property exists, false otherwise.
112
- def has_property?(key)
113
- key_array = key.split(".")
114
- create = false
115
- get_node(key_array, create)
116
- return true
117
- rescue ConfigManager::PropertyNotFoundError
118
- return false
119
- end
120
-
121
- private
122
-
123
- # Gets the node identified by the specified key. If the 'create' flag is true, missing nodes will be created.
124
- #
125
- # @param [Array] key_array the array representing the full key.
126
- # @param [TrueClass, FalseClass] create true to create missing nodes, false otherwise.
127
- #
128
- # @return [Hash] the node identified by this key.
129
- def get_node(key_array, create = false)
130
- return @root if key_array.empty?
131
-
132
- key_str = key_array.join(".")
133
- processed_parts = []
134
- current_node = @root
135
- # Walk the property tree. What's left at the end, is the required node.
136
- key_array.each do |part|
137
- # If the current node is not a hash, it means the key is invalid.
138
- unless current_node.kind_of?(Hash)
139
- raise ConfigManager::KeyError.new("Invalid key '#{key_str}' - Reached leaf at '#{processed_parts.join(".")}'!")
140
- end
141
-
142
- # If the current node is a hash, then check if the next part of the key is present.
143
- # If it present, make that the current node.
144
- # If it isn't present and the create flag is true, create an empty node and make it the current node.
145
- # If the create flag is false, raise an exception.
146
- processed_parts << part
147
- if current_node.has_key?(part)
148
- current_node = current_node[part]
149
- elsif create
150
- current_node = current_node[part] = {}
151
- else
152
- raise ConfigManager::PropertyNotFoundError.new("Key '#{processed_parts.join(".")}' does not exist!")
153
- end
154
- end
155
- # The required node.
156
- current_node
157
- end
158
-
159
- alias_method :[], :get_property
160
- alias_method :[]=, :add_property
161
- alias_method :set_property, :add_property
162
-
163
- end
164
-
165
- end
1
+ #
2
+ # 20 Jul 2012
3
+ #
4
+
5
+ require "configmanager/exceptions"
6
+ require "configmanager/interpolators"
7
+
8
+ module ConfigManager
9
+
10
+ # Represents a collection of properties stored as a hash.
11
+ class Configuration
12
+
13
+ # Creates a new empty configuration.
14
+ #
15
+ # @param [Hash] options configuration options. Supported keys are:
16
+ # :interpolator - an object that can respond to the 'interpolate' method. Default is the DefaultInterpolator.
17
+ # :use_interpolator - global flag to specify if the interpolator should be used for this configuration. Default is true.
18
+ # :tolerate_missing_reference - global flag to specify if missing references should raise an exception.
19
+ def initialize(options = {})
20
+ @root = {}
21
+ @use_interpolator = get_option(options, :use_interpolator, false, true)
22
+ @interpolator = get_option(options, :interpolator, false, ConfigManager::DefaultInterpolator)
23
+ @tolerate_missing_references = get_option(options, :tolerate_missing_references, false, false)
24
+ end
25
+
26
+ # Adds a hash of properties to this configuration.
27
+ #
28
+ # @param [Hash] values the values to add to this configuration.
29
+ # @param [String] at the node under which to add these properties. Default is the root node.
30
+ # @param [Hash] options configuration options. Supported key are
31
+ # :overwrite - true to overwrite existing properties, false to raise an exception if a property exists. Default is false.
32
+ #
33
+ # @return [NilClass]
34
+ def add_properties(values, at = "", options = {})
35
+ # Add each item in the hash - Nested hashes call this method recursively.
36
+ at_array = at.split(".")
37
+ values.each_pair do |key, value|
38
+ full_key = (at_array + [key]).join(".")
39
+ value.kind_of?(Hash) ? add_properties(value, full_key, options) : add_property(full_key, value, options)
40
+ end
41
+
42
+ nil
43
+ end
44
+
45
+ # Adds a property to this configuration. The key is a '.' separated string that fully qualifies this property.
46
+ # So the property a.b identifies the property 'b' inside the group 'a'. Similarly a.b.c identifies the property
47
+ # 'c' inside the group 'b' which is inside the group 'a'.
48
+ #
49
+ # @param [String] key the unique key to identify this property.
50
+ # @param [Object] value the value of this property.
51
+ # @param [Hash] options configuration options. Supported keys are:
52
+ # :overwrite - true to overwrite existing properties, false to raise an exception if a property exists. Default is false.
53
+ # :at - an optional node's name under which to add this property. Default is the root node.
54
+ #
55
+ # @return [NilClass]
56
+ def add_property(key, value, options = {})
57
+ # Default options.
58
+ at = get_option(options, :at, false, "")
59
+ overwrite = get_option(options, :overwrite, false, false)
60
+ # Create and add the property.
61
+ key_array = key.split(".")
62
+ at_array = at.split(".")
63
+ leaf = key_array[-1]
64
+ at_array = at_array + key_array[0..-2]
65
+ at_node = get_node(at_array, create = true)
66
+ # Got the node, now add the property, unless it already exists.
67
+ raise ConfigManager::KeyError.new("Cannot add - '#{at_array.join(".")}.#{leaf}' already exists!") if at_node.has_key?(leaf) and not overwrite
68
+ at_node[leaf] = value
69
+
70
+ nil
71
+ end
72
+
73
+ # Get the value of the specified property. The key is a '.' separated string that fully qualifies this property.
74
+ # So the property a.b identifies the property 'b' inside the group 'a'. Similarly a.b.c identifies the property
75
+ # 'c' inside the group 'b' which is inside the group 'a'.
76
+ #
77
+ # If enabled, the property's value is interpolated.
78
+ # Finally the list of post-processors are invoked and the value is returned.
79
+ #
80
+ # @param [String] key the property to get.
81
+ # @param [Hash] options configuration options. Supported keys are:
82
+ # :use_interpolator - flag to indicate if the interpolator should be used. Uses the value specified when creating this configuration by default.
83
+ # :interpolator - the interpolator to use. Uses the value specified when creating this configuration by default.
84
+ # :post_processors - an array of callable procs. Each one is invoked with the output of the previous one. The first one is invoked with the fully interpolated value.
85
+ # :replacements - a hash containing replacement values for references. References are looked up in this before being looked up in this configuration.
86
+ # :tolerate_missing_references: a flag to indicate if missing references should raise an exception.
87
+ #
88
+ # Note : Interpolator implementations may support additional options too.
89
+ #
90
+ # @return [Object] the property's value.
91
+ def get_property(key, options = {})
92
+ use_interpolator = get_option(options, :use_interpolator, false, @use_interpolator)
93
+ interpolator = get_option(options, :interpolator, false, @interpolator)
94
+ tolerate_missing_references = set_option(options, :tolerate_missing_references, @tolerate_missing_references, false)
95
+ post_processors = pop_option(options, :post_processors, false, [])
96
+ # Get the required property's raw value.
97
+ key_array = key.split(".")
98
+ create = false
99
+ raw_value = get_node(key_array, create)
100
+ # Interpolate.
101
+ raw_value = interpolator.interpolate(key, raw_value, self, options) if use_interpolator
102
+ # Post-process.
103
+ final_value = raw_value
104
+ post_processors.each { |processor| final_value = processor.call(final_value) }
105
+ # All done.
106
+ final_value
107
+ end
108
+
109
+ # Check to see if the specified property is defined for this configuration. This method will throw an exception if
110
+ # the key is invalid.
111
+ #
112
+ # @param [String] key the property to check.
113
+ #
114
+ # @return [TrueClass, FalseClass] true if the property exists, false otherwise.
115
+ def has_property?(key)
116
+ key_array = key.split(".")
117
+ create = false
118
+ get_node(key_array, create)
119
+ return true
120
+ rescue ConfigManager::PropertyNotFoundError
121
+ return false
122
+ end
123
+
124
+ private
125
+
126
+ # Gets the node identified by the specified key. If the 'create' flag is true, missing nodes will be created.
127
+ #
128
+ # @param [Array] key_array the array representing the full key.
129
+ # @param [TrueClass, FalseClass] create true to create missing nodes, false otherwise.
130
+ #
131
+ # @return [Hash] the node identified by this key.
132
+ def get_node(key_array, create = false)
133
+ return @root if key_array.empty?
134
+
135
+ key_str = key_array.join(".")
136
+ processed_parts = []
137
+ current_node = @root
138
+ # Walk the property tree. What's left at the end, is the required node.
139
+ key_array.each do |part|
140
+ # If the current node is not a hash, it means the key is invalid.
141
+ unless current_node.kind_of?(Hash)
142
+ raise ConfigManager::KeyError.new("Invalid key '#{key_str}' - Reached leaf at '#{processed_parts.join(".")}'!")
143
+ end
144
+
145
+ # If the current node is a hash, then check if the next part of the key is present.
146
+ # If it present, make that the current node.
147
+ # If it isn't present and the create flag is true, create an empty node and make it the current node.
148
+ # If the create flag is false, raise an exception.
149
+ processed_parts << part
150
+ if current_node.has_key?(part)
151
+ current_node = current_node[part]
152
+ elsif create
153
+ current_node = current_node[part] = {}
154
+ else
155
+ raise ConfigManager::PropertyNotFoundError.new("Key '#{processed_parts.join(".")}' does not exist!")
156
+ end
157
+ end
158
+ # The required node.
159
+ current_node
160
+ end
161
+
162
+ alias_method :[], :get_property
163
+ alias_method :[]=, :add_property
164
+ alias_method :set_property, :add_property
165
+
166
+ end
167
+
168
+ end