openhab-jrubyscripting 5.0.0.rc1 → 5.0.0.rc2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/entity_lookup.rb +1 -12
  3. data/lib/openhab/core/items/generic_item.rb +2 -2
  4. data/lib/openhab/core/items/metadata/hash.rb +64 -5
  5. data/lib/openhab/core/items/metadata/namespace_hash.rb +17 -19
  6. data/lib/openhab/core/items/metadata/provider.rb +48 -0
  7. data/lib/openhab/core/items/provider.rb +40 -0
  8. data/lib/openhab/core/items/proxy.rb +10 -0
  9. data/lib/openhab/core/items/registry.rb +16 -7
  10. data/lib/openhab/core/items/state_storage.rb +3 -3
  11. data/lib/openhab/core/profile_factory.rb +1 -1
  12. data/lib/openhab/core/provider.rb +216 -0
  13. data/lib/openhab/core/registry.rb +30 -0
  14. data/lib/openhab/core/script_handling.rb +50 -0
  15. data/lib/openhab/core/things/links/provider.rb +40 -0
  16. data/lib/openhab/core/things/provider.rb +25 -0
  17. data/lib/openhab/core/things/proxy.rb +10 -0
  18. data/lib/openhab/core/things/registry.rb +25 -2
  19. data/lib/openhab/core/timer.rb +12 -0
  20. data/lib/openhab/core/types/quantity_type.rb +5 -2
  21. data/lib/openhab/core.rb +3 -14
  22. data/lib/openhab/core_ext/java/class.rb +34 -0
  23. data/lib/openhab/core_ext/java/local_time.rb +2 -1
  24. data/lib/openhab/core_ext/java/month.rb +2 -1
  25. data/lib/openhab/dsl/items/builder.rb +30 -97
  26. data/lib/openhab/dsl/rules/builder.rb +27 -0
  27. data/lib/openhab/dsl/rules/triggers/changed.rb +7 -4
  28. data/lib/openhab/dsl/rules/triggers/cron/cron.rb +1 -1
  29. data/lib/openhab/dsl/rules/triggers/trigger.rb +1 -1
  30. data/lib/openhab/dsl/rules/triggers/updated.rb +7 -3
  31. data/lib/openhab/dsl/rules.rb +1 -1
  32. data/lib/openhab/dsl/script_handling.rb +0 -49
  33. data/lib/openhab/dsl/things/builder.rb +8 -31
  34. data/lib/openhab/dsl/thread_local.rb +1 -0
  35. data/lib/openhab/dsl/timer_manager.rb +13 -7
  36. data/lib/openhab/dsl/version.rb +1 -1
  37. data/lib/openhab/dsl.rb +132 -22
  38. data/lib/openhab/log.rb +1 -1
  39. data/lib/openhab/rspec/helpers.rb +8 -25
  40. data/lib/openhab/rspec/hooks.rb +15 -18
  41. data/lib/openhab/rspec/mocks/timer.rb +5 -0
  42. metadata +9 -3
  43. data/lib/openhab/rspec/mocks/metadata_provider.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cd7a4eed6a2398fd34734d9b3dc15a8f5e2bcc74f7309aede27be29501c21698
4
- data.tar.gz: a1f70554ada415e7de0325ea259ac9edcad48355ef6000a4877057fa06b343ce
3
+ metadata.gz: 0e925ebd72648fa8efb76592f6053d12f2fe9151173fa91d3f47a2d298f268fc
4
+ data.tar.gz: 6d84217a8505a72e2da686188a741d6644eee645255595d5d2cf455a2840e015
5
5
  SHA512:
6
- metadata.gz: f27aa8940df9441a5318c32d1c0d84f15fdd70b2336cf95dd09383b73b97d14bbc7c924ba3e3df24f48d5f289d410ec1d6d0df9f99a40141ac34d88152e9a76a
7
- data.tar.gz: c369de38091c4486a492b88ef990537b5a4cc667becca6be5a99a56227a8a2b0339b14e9ce1e11e6e73b56d8b055d3876917916ee7ec52b66c5b23e85b33a95b
6
+ metadata.gz: 5330bd233b45839cf1780815e86d170ff8a33b4093debfe85cae7e09e631d7a14c7bb2c7e84500da6a41fd0b89f81a160e4279659312323e6fb207bd0da6e632
7
+ data.tar.gz: 28f42c9a625aa33ef258f4d789e9fe116a1bf36e63bc58e2574d1a884ed8bde74bac03484566abd04909462ec4c9bdef543973416a2420fa02fea274122e3889
@@ -72,7 +72,7 @@ module OpenHAB
72
72
  logger.trace("Looking up thing '#{uid}'")
73
73
  uid = uid.to_s if uid.is_a?(Symbol)
74
74
 
75
- uid = generate_thing_uid(uid) unless uid.is_a?(org.openhab.core.thing.ThingUID)
75
+ uid = Things::ThingUID.new(uid) unless uid.is_a?(Things::ThingUID)
76
76
  thing = $things.get(uid)
77
77
  return unless thing
78
78
 
@@ -117,17 +117,6 @@ module OpenHAB
117
117
  item = $ir.get(name)
118
118
  Items::Proxy.new(item) unless item.nil?
119
119
  end
120
-
121
- #
122
- # Returns a ThingUID given a string like object
123
- #
124
- # @!visibility private
125
- #
126
- # @return [Things::ThingUID]
127
- #
128
- def self.generate_thing_uid(uid)
129
- org.openhab.core.thing.ThingUID.new(*uid.split(":"))
130
- end
131
120
  end
132
121
  end
133
122
  end
@@ -73,7 +73,7 @@ module OpenHAB
73
73
  def command(command)
74
74
  command = format_command(command)
75
75
  logger.trace "Sending Command #{command} to #{name}"
76
- org.openhab.core.model.script.actions.BusEvent.sendCommand(self, command)
76
+ $events.send_command(self, command)
77
77
  self
78
78
  end
79
79
 
@@ -93,7 +93,7 @@ module OpenHAB
93
93
  def update(state)
94
94
  state = format_update(state)
95
95
  logger.trace "Sending Update #{state} to #{name}"
96
- org.openhab.core.model.script.actions.BusEvent.postUpdate(self, state)
96
+ $events.post_update(self, state)
97
97
  self
98
98
  end
99
99
 
@@ -15,6 +15,8 @@ module OpenHAB
15
15
  #
16
16
  # @!attribute [rw] value
17
17
  # @return [String] The main value for the metadata namespace.
18
+ # @!attribute [r] namespace
19
+ # @return [String]
18
20
  #
19
21
  class Hash
20
22
  java_import org.openhab.core.items.Metadata
@@ -58,6 +60,8 @@ module OpenHAB
58
60
  :value?
59
61
  def_delegators :to_h, :invert, :merge, :transform_keys, :transform_values
60
62
 
63
+ def_delegator :uid, :namespace
64
+
61
65
  class << self
62
66
  # @!visibility private
63
67
  def from_item(item_name, namespace, value)
@@ -72,7 +76,7 @@ module OpenHAB
72
76
 
73
77
  [value.first, (value.last || {}).transform_keys(&:to_s)]
74
78
  when ::Hash then ["", value.transform_keys(&:to_s)]
75
- else [value, {}]
79
+ else [value.to_s, {}]
76
80
  end
77
81
  new(Metadata.new(org.openhab.core.items.MetadataKey.new(namespace.to_s, item_name), *value))
78
82
  end
@@ -108,13 +112,24 @@ module OpenHAB
108
112
  end
109
113
 
110
114
  # @!visibility private
111
- def create
112
- NamespaceHash.registry.add(@metadata) if attached?
115
+ def commit
116
+ return unless attached?
117
+
118
+ javaify
119
+ provider.update(@metadata)
113
120
  end
114
121
 
115
122
  # @!visibility private
116
- def commit
117
- NamespaceHash.registry.update(@metadata) if attached?
123
+ def create_or_update
124
+ return unless attached?
125
+
126
+ javaify
127
+ (p = provider).get(uid) ? p.update(@metadata) : p.add(@metadata)
128
+ end
129
+
130
+ # @!visibility private
131
+ def remove
132
+ provider.remove(uid)
118
133
  end
119
134
 
120
135
  # @!visibility private
@@ -383,6 +398,50 @@ module OpenHAB
383
398
  [value, to_h].inspect
384
399
  end
385
400
  alias_method :to_s, :inspect
401
+
402
+ #
403
+ # @raise [RuntimeError] if the provider is not a
404
+ # {org.openhab.core.common.registry.ManagedProvider ManagedProvider} that can be updated.
405
+ # @return [org.openhab.core.common.registry.ManagedProvider]
406
+ #
407
+ def provider
408
+ preferred_provider = Provider.current(
409
+ Thread.current[:openhab_providers]&.dig(:metadata_items, uid.item_name) ||
410
+ Thread.current[:openhab_providers]&.dig(:metadata_namespaces, uid.namespace),
411
+ self
412
+ )
413
+
414
+ if attached?
415
+ provider = Provider.registry.provider_for(uid)
416
+ return preferred_provider unless provider
417
+
418
+ unless provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
419
+ raise FrozenError, "Cannot modify metadata from provider #{provider.inspect}"
420
+ end
421
+
422
+ if preferred_provider != provider
423
+ logger.warn("Provider #{preferred_provider.inspect} cannot be used with #{uid}; " \
424
+ "reverting to provider #{provider.inspect}. " \
425
+ "This may cause unexpected issues, like metadata persisting that you did not expect to.")
426
+ preferred_provider = provider
427
+ end
428
+
429
+ end
430
+ preferred_provider
431
+ end
432
+
433
+ private
434
+
435
+ #
436
+ # @see https://github.com/openhab/openhab-core/issues/3169
437
+ #
438
+ # in the meantime, force the serialization round-trip right now
439
+ #
440
+ def javaify
441
+ mapper = Provider.registry.managed_provider.get.storage.entityMapper
442
+
443
+ @metadata = mapper.from_json(mapper.to_json_tree(@metadata), Metadata.java_class)
444
+ end
386
445
  end
387
446
  end
388
447
  end
@@ -96,12 +96,7 @@ module OpenHAB
96
96
  metadata = Hash.from_item(@item_name, namespace, value)
97
97
  return @hash[metadata.uid.namespace] = metadata unless attached? # rubocop:disable Lint/ReturnInVoidContext
98
98
 
99
- # registry.get can be omitted, but registry.update will log a warning for nonexistent metadata
100
- if self.class.registry.managed_provider.get.get(metadata.uid)
101
- metadata.commit
102
- else
103
- metadata.create
104
- end
99
+ metadata.create_or_update
105
100
  metadata # rubocop:disable Lint/Void
106
101
  end
107
102
  alias_method :store, :[]=
@@ -117,7 +112,11 @@ module OpenHAB
117
112
  # @!visibility private
118
113
  def clear
119
114
  if attached?
120
- self.class.registry.remove_item_metadata(@item_name)
115
+ provider = Provider.current(Thread.current[:openhab_providers]&.dig(:metadata_items, @item_name))
116
+ provider.remove_item_metadata(@item_name)
117
+ Thread.current[:openhab_providers]&.[](:metadata_namespaces)&.each_value do |namespace_provider|
118
+ Provider.current(namespace_provider).remove_item_metadata(@item_name)
119
+ end
121
120
  else
122
121
  @hash.clear
123
122
  end
@@ -171,11 +170,10 @@ module OpenHAB
171
170
 
172
171
  # @!visibility private
173
172
  def delete(namespace, &block)
174
- namespace = namespace.to_s
175
-
176
- return @hash.delete(namespace, &block) unless attached?
173
+ return @hash.delete(namespace.to_s, &block) unless attached?
177
174
 
178
- r = self.class.registry.remove(MetadataKey.new(namespace, @item_name))
175
+ metadata = Hash.from_item(@item_name, namespace, nil)
176
+ r = metadata.remove
179
177
  return yield(namespace) if block && !r
180
178
 
181
179
  Hash.new(r) if r
@@ -208,7 +206,7 @@ module OpenHAB
208
206
  return @hash.each(&block) unless attached?
209
207
  return to_enum(:each) unless block
210
208
 
211
- self.class.registry.all.each do |meta|
209
+ Provider.registry.all.each do |meta|
212
210
  yield meta.uid.namespace, Hash.new(meta) if meta.uid.item_name == @item_name
213
211
  end
214
212
  self
@@ -220,7 +218,7 @@ module OpenHAB
220
218
  return @hash.each_key(&block) unless attached?
221
219
  return to_enum(:each_key) unless block
222
220
 
223
- self.class.registry.all.each do |meta|
221
+ Provider.registry.all.each do |meta|
224
222
  yield meta.uid.namespace if meta.uid.item_name == @item_name
225
223
  end
226
224
  self
@@ -231,7 +229,7 @@ module OpenHAB
231
229
  return @hash.each_value(&block) unless attached?
232
230
  return to_enum(:each_value) unless block_given?
233
231
 
234
- self.class.registry.all.each do |meta|
232
+ Provider.registry.all.each do |meta|
235
233
  yield Hash.new(meta) if meta.uid.item_name == @item_name
236
234
  end
237
235
  self
@@ -241,7 +239,7 @@ module OpenHAB
241
239
  def empty?
242
240
  return @hash.empty? unless attached?
243
241
 
244
- self.class.registry.all.each do |meta|
242
+ Provider.registry.all.each do |meta|
245
243
  return false if meta.uid.item_name == @item_name
246
244
  end
247
245
  true
@@ -263,7 +261,7 @@ module OpenHAB
263
261
  end
264
262
 
265
263
  logger.trace("Getting metadata for item: #{@item_name}, namespace '#{key}'")
266
- if (m = self.class.registry.get(MetadataKey.new(key, @item_name)))
264
+ if (m = Provider.registry.get(MetadataKey.new(key, @item_name)))
267
265
  Hash.new(m)
268
266
  elsif block
269
267
  yield key
@@ -280,7 +278,7 @@ module OpenHAB
280
278
 
281
279
  keys.each_with_object([]) do |key, res|
282
280
  key = key.to_s
283
- if (m = self.class.registry.get(MetadataKey.new(key, @item_name)))
281
+ if (m = Provider.registry.get(MetadataKey.new(key, @item_name)))
284
282
  res << Hash.new(m)
285
283
  elsif block_given?
286
284
  res << yield(key)
@@ -307,7 +305,7 @@ module OpenHAB
307
305
  key = key.to_s
308
306
  return @hash.key?(key) unless attached?
309
307
 
310
- !self.class.registry.get(MetadataKey.new(key, @item_name)).nil?
308
+ !Provider.registry.get(MetadataKey.new(key, @item_name)).nil?
311
309
  end
312
310
  alias_method :has_key?, :key?
313
311
  alias_method :member?, :key?
@@ -373,7 +371,7 @@ module OpenHAB
373
371
 
374
372
  keys = keys.to_set
375
373
  r = {}
376
- self.class.registry.all.each do |meta|
374
+ Provider.registry.all.each do |meta|
377
375
  if meta.uid.item_name == @item_name && keys.include?(meta.uid.namespace)
378
376
  r[meta.uid.namespace] =
379
377
  Hash.new(meta)
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Items
6
+ module Metadata
7
+ #
8
+ # Provides metadata created in Ruby to openHAB
9
+ #
10
+ class Provider < Core::Provider
11
+ include org.openhab.core.items.ManagedMetadataProvider
12
+
13
+ class << self
14
+ #
15
+ # The Metadata registry
16
+ #
17
+ # @return [org.openhab.core.items.MetadataRegistry]
18
+ #
19
+ def registry
20
+ @registry ||= OSGi.service("org.openhab.core.items.MetadataRegistry")
21
+ end
22
+ end
23
+
24
+ # see Hash#javaify
25
+ registry.managed_provider.get.class.field_reader :storage
26
+ registry.managed_provider.get.storage.class.field_reader :entityMapper
27
+
28
+ #
29
+ # Removes all metadata of a given item.
30
+ #
31
+ # @param [String] item_name
32
+ # @return [void]
33
+ #
34
+ def remove_item_metadata(item_name)
35
+ @elements.delete_if do |k, v|
36
+ next unless k.item_name == item_name
37
+
38
+ notify_listeners_about_removed_element(v)
39
+ true
40
+ end
41
+ nil
42
+ end
43
+ alias_method :removeItemMetadata, :remove_item_metadata
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenHAB
4
+ module Core
5
+ module Items
6
+ #
7
+ # Provides {GenericItem Items} created in Ruby to openHAB
8
+ #
9
+ class Provider < Core::Provider
10
+ include org.openhab.core.items.ItemProvider
11
+
12
+ class << self
13
+ #
14
+ # The Item registry
15
+ #
16
+ # @return [org.openhab.core.items.ItemRegistry]
17
+ #
18
+ def registry
19
+ $ir
20
+ end
21
+ end
22
+
23
+ #
24
+ # Remove an item from this provider
25
+ #
26
+ # @param [String] item_name
27
+ # @param [true, false] recursive
28
+ # @return [GenericItem, nil] The removed item, if found.
29
+ #
30
+ def remove(item_name, recursive = false) # rubocop:disable Style/OptionalBooleanParameter matches Java method
31
+ return nil unless @elements.key?(item_name)
32
+
33
+ item = super(item_name)
34
+ item.members.each { |member| remove(member.name, true) } if recursive && item.is_a?(GroupItem)
35
+ item
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -53,6 +53,16 @@ module OpenHAB
53
53
 
54
54
  super
55
55
  end
56
+
57
+ #
58
+ # Non equality comparison
59
+ #
60
+ # @return [true, false]
61
+ #
62
+ # @!visibility private
63
+ def !=(other)
64
+ !(self == other) # rubocop:disable Style/InverseMethods
65
+ end
56
66
  end
57
67
  end
58
68
  end
@@ -32,6 +32,8 @@ module OpenHAB
32
32
  !$ir.getItems(name).empty?
33
33
  end
34
34
  alias_method :include?, :key?
35
+ # @deprecated
36
+ alias_method :has_key?, :key?
35
37
 
36
38
  # Explicit conversion to array
37
39
  # @return [Array]
@@ -39,26 +41,33 @@ module OpenHAB
39
41
  $ir.items.map { |item| Proxy.new(item) }
40
42
  end
41
43
 
44
+ #
42
45
  # Enter the Item Builder DSL.
46
+ #
47
+ # @param (see Core::Provider.current)
43
48
  # @yield Block executed in the context of a {DSL::Items::Builder}
44
49
  # @return [Object] The return value of the block.
45
- def build(&block)
46
- DSL::Items::BaseBuilderDSL.new.instance_eval(&block)
50
+ #
51
+ def build(preferred_provider = nil, &block)
52
+ DSL::Items::BaseBuilderDSL.new(preferred_provider).instance_eval(&block)
47
53
  end
48
54
 
55
+ #
49
56
  # Remove an item.
50
57
  #
51
- # The item must have either been created by this script, or be a
52
- # managed item (typically created in the UI).
58
+ # The item must be a managed item (typically created by Ruby or in the UI).
53
59
  #
60
+ # @param [String, GenericItem] item_name
54
61
  # @param recursive [true, false] Remove the item's members if it's a group
55
62
  # @return [GenericItem, nil] The removed item, if found.
56
63
  def remove(item_name, recursive: false)
57
64
  item_name = item_name.name if item_name.is_a?(GenericItem)
58
- result = DSL::Items::ItemProvider.instance.remove(item_name, recursive: recursive)
59
- return result if result
65
+ provider = Provider.registry.provider_for(item_name)
66
+ unless provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
67
+ raise "Cannot remove item #{item_name} from non-managed provider #{provider.inspect}"
68
+ end
60
69
 
61
- $ir.remove(item_name, recursive)
70
+ provider.remove(item_name, recursive)
62
71
  end
63
72
  end
64
73
  end
@@ -18,7 +18,7 @@ module OpenHAB
18
18
  #
19
19
  # @!visibility private
20
20
  def self.from_items(*items)
21
- StateStorage.new(org.openhab.core.model.script.actions.BusEvent.store_states(*items).to_h)
21
+ StateStorage.new($events.store_states(*items).to_h)
22
22
  end
23
23
 
24
24
  #
@@ -27,7 +27,7 @@ module OpenHAB
27
27
  # @return [void]
28
28
  #
29
29
  def restore
30
- org.openhab.core.model.script.actions.BusEvent.restore_states(to_h)
30
+ $events.restore_states(to_h)
31
31
  end
32
32
 
33
33
  #
@@ -36,7 +36,7 @@ module OpenHAB
36
36
  # @return [void]
37
37
  #
38
38
  def restore_changes
39
- org.openhab.core.model.script.actions.BusEvent.restore_states(select { |item, value| item.state != value })
39
+ $events.restore_states(select { |item, value| item.state != value })
40
40
  end
41
41
 
42
42
  #
@@ -113,6 +113,6 @@ module OpenHAB
113
113
  end
114
114
 
115
115
  registration = OSGi.register_service(ProfileFactory.instance)
116
- ScriptHandlingCallbacks.script_unloaded_hooks << -> { registration.unregister }
116
+ ScriptHandling.script_unloaded { registration.unregister }
117
117
  end
118
118
  end
@@ -0,0 +1,216 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "singleton"
4
+
5
+ module OpenHAB
6
+ module Core
7
+ # @interface
8
+ java_import org.openhab.core.common.registry.ManagedProvider
9
+
10
+ # @!visibility private
11
+ module ManagedProvider
12
+ # Maps actual element types to the symbol used in Thread.local[:openhab_providers]
13
+ TYPE_TO_PROVIDER_TYPE = {
14
+ org.openhab.core.items.Item.java_class => :items,
15
+ org.openhab.core.items.Metadata.java_class => :metadata,
16
+ org.openhab.core.thing.Thing.java_class => :things,
17
+ org.openhab.core.thing.link.ItemChannelLink.java_class => :links
18
+ }.freeze
19
+ private_constant :TYPE_TO_PROVIDER_TYPE
20
+
21
+ # @return [Symbol, nil]
22
+ def type
23
+ java_class.generic_ancestors.each do |klass|
24
+ next unless klass.respond_to?(:raw_type)
25
+ next unless klass.raw_type == org.openhab.core.common.registry.Provider.java_class
26
+
27
+ type_arg = klass.actual_type_arguments.first
28
+ next unless type_arg.is_a?(java.lang.Class)
29
+ next unless klass.actual_type_arguments.first.is_a?(java.lang.Class)
30
+
31
+ return TYPE_TO_PROVIDER_TYPE[type_arg]
32
+ end
33
+ nil
34
+ end
35
+ end
36
+
37
+ # @abstract
38
+ class Provider < org.openhab.core.common.registry.AbstractProvider
39
+ include org.openhab.core.common.registry.ManagedProvider
40
+ include Singleton
41
+ public_class_method :new
42
+
43
+ # Known supported provider types
44
+ # @return [Array<Symbol>]
45
+ KNOWN_TYPES = %i[items metadata things links].freeze
46
+
47
+ class << self
48
+ #
49
+ # Determines the current provider that should be used to create elements belonging to this registry.
50
+ #
51
+ # @param [org.openhab.core.common.registry.Provider, Proc, :persistent, :transient, nil] preferred_provider
52
+ # An optional preferred provider to use. Can be one of several types:
53
+ # * An explicit instance of {org.openhab.core.common.registry.ManagedProvider ManagedProvider}
54
+ # * A Proc, which can calculate the preferred provider based on whatever conditions it wants,
55
+ # and then is further processed as this parameter.
56
+ # * `:persistent`, meaning the default {org.openhab.core.common.registry.ManagedProvider ManagedProvider}
57
+ # for this registry. Managed providers persist their objects to JSON, and will survive after the
58
+ # Ruby script is unloaded. This is where objects you configure with MainUI are stored. You should
59
+ # use this provider when you're creating something in response to a one-time event.
60
+ # * `:transient`, meaning a {org.openhab.core.common.registry.ManagedProvider ManagedProvider} that
61
+ # will remove all of its contents when the Ruby script is unloaded. You should use this if you're
62
+ # generating objects dynamically, either based on some sort of other configuration, or simply
63
+ # hard coded and you're using Ruby as a more expressive way to define things than a `.items` or
64
+ # `.things` file. If you _don't_ use this provider for something such as metadata, then you
65
+ # may have issues such as metadata still showing up even though you're no longer creating items
66
+ # with it anymore.
67
+ # * `nil`, meaning to fall back to the current thread setting. See {OpenHAB::DSL.provider}.
68
+ # If there is no thread setting (or the thread setting was Proc that returned `nil`),
69
+ # it defaults to `:transient`.
70
+ # @return [org.openhab.core.common.registry.Provider]
71
+ #
72
+ def current(preferred_provider = nil, element = nil)
73
+ preferred_provider ||= Thread.current[:openhab_providers]&.[](type)
74
+ if preferred_provider.is_a?(Proc)
75
+ preferred_provider = if preferred_provider.arity.zero? || element.nil?
76
+ preferred_provider.call
77
+ else
78
+ preferred_provider.call(element)
79
+ end
80
+ end
81
+
82
+ case preferred_provider
83
+ when nil, :transient
84
+ instance
85
+ when :persistent
86
+ registry.managed_provider.get
87
+ when org.openhab.core.common.registry.ManagedProvider
88
+ preferred_provider
89
+ else
90
+ raise ArgumentError, "#{preferred_provider.inspect} is not a ManagedProvider"
91
+ end
92
+ end
93
+
94
+ # @abstract
95
+ # @!attribute [r] registry
96
+ #
97
+ # The registry that this provider provides elements for.
98
+ #
99
+ # @return [org.openhab.core.common.registry.Registry]
100
+ #
101
+ def registry
102
+ raise NotImplementedError
103
+ end
104
+
105
+ #
106
+ # Creates a new instance of a provider, registers it, sets it as the
107
+ # default for the thread, calls the block, and then unregisters it.
108
+ #
109
+ # @param [true, false] thread_provider Set this new provider as the default for the thread
110
+ # @yieldparam [Provider] provider The provider
111
+ # @return [Object] The result of the block
112
+ #
113
+ # @!visibility private
114
+ def new(thread_provider: true)
115
+ unless @singleton__instance__.nil? || block_given?
116
+ raise NoMethodError,
117
+ "private method `new' called for #{self}:Class"
118
+ end
119
+
120
+ r = provider = super()
121
+ if block_given?
122
+ if thread_provider
123
+ DSL.provider(provider) do
124
+ r = yield provider
125
+ end
126
+ else
127
+ r = yield provider
128
+ end
129
+ provider.unregister
130
+ end
131
+ r
132
+ end
133
+
134
+ # @!attribute [r] type
135
+ # @!visibility private
136
+ # @return [Symbol]
137
+ #
138
+ def type
139
+ name.split("::")[-2].downcase.to_sym
140
+ end
141
+ end
142
+
143
+ # @return [String]
144
+ def inspect
145
+ "#<#{self.class.name}:#{object_id}>"
146
+ end
147
+
148
+ # @!visibility private
149
+ def add(element)
150
+ @elements[element.uid] = element
151
+ notify_listeners_about_added_element(element)
152
+ element
153
+ end
154
+
155
+ #
156
+ # Get an element from this provider
157
+ #
158
+ # @param [Object] key The proper key type for the elements in this provider.
159
+ # @return [Object]
160
+ #
161
+ def [](key)
162
+ @elements[key]
163
+ end
164
+ alias_method :get, :[]
165
+
166
+ #
167
+ # Get all elements in this provider
168
+ #
169
+ # @return [Array<Object>]
170
+ #
171
+ def all
172
+ @elements.values
173
+ end
174
+ alias_method :getAll, :all
175
+
176
+ #
177
+ # Remove an element from this provider
178
+ #
179
+ # @return [Object, nil] the removed element
180
+ #
181
+ # @!visibility private
182
+ #
183
+ def remove(key)
184
+ @elements.delete(key)&.tap do |element|
185
+ notify_listeners_about_removed_element(element)
186
+ end
187
+ end
188
+
189
+ # @return [Object, nil] the previous version of the element
190
+ # @!visibility private
191
+ #
192
+ def update(element)
193
+ old_element = @elements[element.uid]
194
+ if old_element
195
+ @elements[element.uid]
196
+ notify_listeners_about_updated_element(old_element, element)
197
+ end
198
+ old_element
199
+ end
200
+
201
+ # @!visibility private
202
+ def unregister
203
+ self.class.registry.remove_provider(self)
204
+ end
205
+
206
+ private
207
+
208
+ def initialize
209
+ super
210
+ @elements = {}
211
+ self.class.registry.add_provider(self)
212
+ ScriptHandling.script_unloaded { unregister }
213
+ end
214
+ end
215
+ end
216
+ end