openhab-jrubyscripting 5.0.0.rc11 → 5.0.0.rc.13

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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/lib/openhab/core/actions/exec.rb +41 -41
  3. data/lib/openhab/core/actions/transformation.rb +3 -3
  4. data/lib/openhab/core/actions.rb +1 -1
  5. data/lib/openhab/core/events/item_command_event.rb +31 -31
  6. data/lib/openhab/core/events/item_state_changed_event.rb +41 -18
  7. data/lib/openhab/core/events/item_state_event.rb +46 -18
  8. data/lib/openhab/core/items/date_time_item.rb +3 -2
  9. data/lib/openhab/core/items/generic_item.rb +119 -1
  10. data/lib/openhab/core/items/item.rb +63 -9
  11. data/lib/openhab/core/items/metadata/hash.rb +1 -1
  12. data/lib/openhab/core/items/metadata/namespace_hash.rb +10 -2
  13. data/lib/openhab/core/items/metadata/provider.rb +2 -2
  14. data/lib/openhab/core/items/persistence.rb +48 -4
  15. data/lib/openhab/core/items/provider.rb +4 -0
  16. data/lib/openhab/core/items/registry.rb +10 -1
  17. data/lib/openhab/core/items/semantics/enumerable.rb +29 -6
  18. data/lib/openhab/core/items/state_storage.rb +2 -2
  19. data/lib/openhab/core/items.rb +6 -13
  20. data/lib/openhab/core/provider.rb +2 -2
  21. data/lib/openhab/core/proxy.rb +5 -0
  22. data/lib/openhab/core/registry.rb +12 -2
  23. data/lib/openhab/core/rules/provider.rb +0 -15
  24. data/lib/openhab/core/rules.rb +1 -1
  25. data/lib/openhab/core/script_handling.rb +8 -8
  26. data/lib/openhab/core/things/links/provider.rb +38 -0
  27. data/lib/openhab/core/things/provider.rb +4 -0
  28. data/lib/openhab/core/things/registry.rb +4 -0
  29. data/lib/openhab/core/timer.rb +3 -19
  30. data/lib/openhab/core/types/date_time_type.rb +1 -1
  31. data/lib/openhab/core/types/decimal_type.rb +4 -9
  32. data/lib/openhab/core/types/hsb_type.rb +2 -2
  33. data/lib/openhab/core/types/quantity_type.rb +4 -9
  34. data/lib/openhab/core/types/string_type.rb +1 -1
  35. data/lib/openhab/core/types/type.rb +8 -28
  36. data/lib/openhab/core/types.rb +16 -3
  37. data/lib/openhab/core.rb +3 -3
  38. data/lib/openhab/core_ext/java/duration.rb +2 -0
  39. data/lib/openhab/core_ext/java/local_date.rb +15 -7
  40. data/lib/openhab/core_ext/java/local_time.rb +13 -3
  41. data/lib/openhab/core_ext/java/month.rb +1 -1
  42. data/lib/openhab/core_ext/java/month_day.rb +13 -3
  43. data/lib/openhab/core_ext/java/period.rb +1 -1
  44. data/lib/openhab/core_ext/java/temporal_amount.rb +1 -1
  45. data/lib/openhab/core_ext/java/time.rb +5 -1
  46. data/lib/openhab/core_ext/java/zoned_date_time.rb +15 -2
  47. data/lib/openhab/core_ext/ruby/date.rb +2 -2
  48. data/lib/openhab/core_ext/ruby/{class.rb → module.rb} +3 -3
  49. data/lib/openhab/core_ext/ruby/numeric.rb +6 -1
  50. data/lib/openhab/dsl/items/builder.rb +25 -12
  51. data/lib/openhab/dsl/items/ensure.rb +8 -6
  52. data/lib/openhab/dsl/rules/automation_rule.rb +2 -23
  53. data/lib/openhab/dsl/rules/builder.rb +47 -2
  54. data/lib/openhab/dsl/rules/terse.rb +15 -13
  55. data/lib/openhab/dsl/timer_manager.rb +1 -1
  56. data/lib/openhab/dsl/version.rb +1 -1
  57. data/lib/openhab/dsl.rb +38 -11
  58. data/lib/openhab/osgi.rb +1 -3
  59. data/lib/openhab/rspec/helpers.rb +3 -5
  60. data/lib/openhab/rspec/hooks.rb +1 -0
  61. data/lib/openhab/rspec/mocks/timer.rb +33 -0
  62. data/lib/openhab/rspec.rb +9 -0
  63. metadata +23 -9
@@ -24,10 +24,6 @@ module OpenHAB
24
24
  # The item's name.
25
25
  # @return [String]
26
26
 
27
- # @!attribute [r] label
28
- # The item's descriptive label.
29
- # @return [String, nil]
30
-
31
27
  # @!attribute [r] accepted_command_types
32
28
  # @return [Array<Class>] An array of {Command}s that can be sent as commands to this item
33
29
 
@@ -35,7 +31,7 @@ module OpenHAB
35
31
  # @return [Array<Class>] An array of {State}s that can be sent as commands to this item
36
32
 
37
33
  #
38
- # The item's {#label} if one is defined, otherwise it's {#name}.
34
+ # The item's {GenericItem#label label} if one is defined, otherwise its {#name}.
39
35
  #
40
36
  # @return [String]
41
37
  #
@@ -46,14 +42,51 @@ module OpenHAB
46
42
  #
47
43
  # @!attribute [r] groups
48
44
  #
49
- # Return all groups that this item is part of
45
+ # Returns all groups that this item is part of
50
46
  #
51
- # @return [Array<Group>] All groups that this item is part of
47
+ # @return [Array<GroupItem>] All groups that this item is part of
52
48
  #
53
49
  def groups
54
50
  group_names.map { |name| EntityLookup.lookup_item(name) }.compact
55
51
  end
56
52
 
53
+ #
54
+ # Checks if this item is a member of at least one of the given groups.
55
+ #
56
+ # @param groups [String, GroupItem] the group to check membership in
57
+ # @return [true, false]
58
+ #
59
+ # @example
60
+ # event.item.member_of?(gFullOn)
61
+ #
62
+ def member_of?(*groups)
63
+ groups = groups.map! do |group|
64
+ group.is_a?(GroupItem) ? group.name : group
65
+ end
66
+ !(group_names & groups).empty?
67
+ end
68
+
69
+ #
70
+ # @!attribute [r] all_groups
71
+ #
72
+ # Returns all groups that this item is a part of, as well as those groups' groups, recursively
73
+ #
74
+ # @return [Array<GroupItem>]
75
+ #
76
+ def all_groups
77
+ result = []
78
+ new_groups = Set.new(groups)
79
+
80
+ until new_groups.empty?
81
+ result.concat(new_groups.to_a)
82
+ new_groups.replace(new_groups.flat_map(&:groups))
83
+ # remove any groups we already have in the result to avoid loops
84
+ new_groups.subtract(result)
85
+ end
86
+
87
+ result
88
+ end
89
+
57
90
  # rubocop:disable Layout/LineLength
58
91
 
59
92
  # @!attribute [r] metadata
@@ -81,7 +114,7 @@ module OpenHAB
81
114
  # @example Access namespace1's configuration
82
115
  # Item1.metadata["namespace1"]["config1"]
83
116
  #
84
- # @example Safely search for the specified value - no errors are raised, only nil returned if a key in the chain doesn"t exist
117
+ # @example Safely search for the specified value - no errors are raised, only nil returned if a key in the chain doesn't exist
85
118
  # Item1.metadata.dig("namespace1", "config1") # => "foo"
86
119
  # Item1.metadata.dig("namespace2", "config1") # => nil
87
120
  #
@@ -176,6 +209,22 @@ module OpenHAB
176
209
  end
177
210
  # rubocop:enable Layout/LineLength
178
211
 
212
+ #
213
+ # Checks if this item has at least one of the given tags.
214
+ #
215
+ # @param tags [String, Module] the tag(s) to check
216
+ # @return [true, false]
217
+ #
218
+ # @example
219
+ # event.item.tagged?("Setpoint")
220
+ #
221
+ def tagged?(*tags)
222
+ tags = tags.map! do |tag|
223
+ tag.is_a?(Module) ? tag.simple_name : tag
224
+ end
225
+ !(self.tags.to_a & tags).empty?
226
+ end
227
+
179
228
  # Return the item's thing if this item is linked with a thing. If an item is linked to more than one thing,
180
229
  # this method only returns the first thing.
181
230
  #
@@ -189,7 +238,7 @@ module OpenHAB
189
238
  #
190
239
  # @return [Array<Thing>] An array of things or an empty array
191
240
  def things
192
- registry = OSGi.service("org.openhab.core.thing.link.ItemChannelLinkRegistry")
241
+ registry = Things::Links::Provider.registry
193
242
  channels = registry.get_bound_channels(name).to_a
194
243
  channels.map(&:thing_uid).uniq.map { |tuid| EntityLookup.lookup_thing(tuid) }.compact
195
244
  end
@@ -206,6 +255,11 @@ module OpenHAB
206
255
  "#{s}>"
207
256
  end
208
257
 
258
+ # @return [org.openhab.core.common.registry.Provider]
259
+ def provider
260
+ Provider.registry.provider_for(self)
261
+ end
262
+
209
263
  private
210
264
 
211
265
  # Allows sub-classes to append additional details to the type in an inspect string
@@ -384,7 +384,7 @@ module OpenHAB
384
384
  alias_method :to_s, :inspect
385
385
 
386
386
  #
387
- # @raise [RuntimeError] if the provider is not a
387
+ # @raise [FrozenError] if the provider is not a
388
388
  # {org.openhab.core.common.registry.ManagedProvider ManagedProvider} that can be updated.
389
389
  # @return [org.openhab.core.common.registry.ManagedProvider]
390
390
  #
@@ -218,8 +218,12 @@ module OpenHAB
218
218
  return @hash.each_key(&block) unless attached?
219
219
  return to_enum(:each_key) unless block
220
220
 
221
- Provider.registry.all.each do |meta|
222
- yield meta.uid.namespace if meta.uid.item_name == @item_name
221
+ if Provider.registry.respond_to?(:get_all_namespaces)
222
+ keys.each(&block)
223
+ else
224
+ Provider.registry.all.each do |meta|
225
+ yield meta.uid.namespace if meta.uid.item_name == @item_name
226
+ end
223
227
  end
224
228
  self
225
229
  end
@@ -313,6 +317,10 @@ module OpenHAB
313
317
 
314
318
  # @!visibility private
315
319
  def keys
320
+ if Provider.registry.respond_to?(:get_all_namespaces)
321
+ return Provider.registry.get_all_namespaces(@item_name).to_a
322
+ end
323
+
316
324
  each_key.to_a
317
325
  end
318
326
 
@@ -32,8 +32,8 @@ module OpenHAB
32
32
  # @return [void]
33
33
  #
34
34
  def remove_item_metadata(item_name)
35
- @elements.delete_if do |k, v|
36
- next unless k.item_name == item_name
35
+ @elements.delete_if do |_k, v|
36
+ next unless v.uid.item_name == item_name
37
37
 
38
38
  notify_listeners_about_removed_element(v)
39
39
  true
@@ -77,7 +77,6 @@ module OpenHAB
77
77
  %i[changed_since?
78
78
  count_since
79
79
  count_state_changes_since
80
- evolution_rate
81
80
  historic_state
82
81
  maximum_since
83
82
  minimum_since
@@ -183,11 +182,22 @@ module OpenHAB
183
182
  # @return [true,false] True if the item's state changed between `start` and `finish`, False otherwise.
184
183
 
185
184
  # @!method evolution_rate(timestamp, service = nil)
186
- # Returns the evolution rate of the item's state since the given time
187
- # @param [#to_zoned_date_time] timestamp The point in time from which to search
188
- # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
185
+ # Returns the evolution rate of the item's state
189
186
  # @return [DecimalType, QuantityType, nil] The evolution rate since `timestamp`,
190
187
  # or nil if no previous state could be found.
188
+ # @overload evolution_rate(timestamp, service = nil)
189
+ # Returns the evolution rate of the item's state since the given time
190
+ # @param [#to_zoned_date_time] timestamp The point in time from which to search
191
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
192
+ # @return [DecimalType, QuantityType, nil] The evolution rate since `timestamp`,
193
+ # or nil if no previous state could be found.
194
+ # @overload evolution_rate(start, finish, service = nil)
195
+ # Returns the evolution rate of the item's state between two points in time
196
+ # @param [#to_zoned_date_time] start The point in time from which to search
197
+ # @param [#to_zoned_date_time] finish The point in time to which to search
198
+ # @param [Symbol, String] service An optional persistence id instead of the default persistence service.
199
+ # @return [DecimalType, QuantityType, nil] The evolution rate between `start` and `finish`,
200
+ # or nil if no previous state could be found.
191
201
 
192
202
  # @!method historic_state(timestamp, service = nil)
193
203
  # Returns the the item's state at the given time
@@ -317,6 +327,40 @@ module OpenHAB
317
327
  end
318
328
  end
319
329
 
330
+ # evolution_rate's "between" method is overloaded with the same name
331
+ method = :evolution_rate
332
+ define_method(method) do |start, finish_or_service = nil, service = nil|
333
+ if service.nil?
334
+ if finish_or_service.respond_to?(:to_zoned_date_time)
335
+ service = persistence_service
336
+ finish = finish_or_service
337
+ else
338
+ service = finish_or_service || persistence_service
339
+ finish = nil
340
+ end
341
+ else
342
+ finish = finish_or_service
343
+ end
344
+
345
+ result = if finish
346
+ Actions::PersistenceExtensions.public_send(
347
+ method,
348
+ self,
349
+ start.to_zoned_date_time,
350
+ finish.to_zoned_date_time,
351
+ service&.to_s
352
+ )
353
+ else
354
+ Actions::PersistenceExtensions.public_send(
355
+ method,
356
+ self,
357
+ start.to_zoned_date_time,
358
+ service&.to_s
359
+ )
360
+ end
361
+ wrap_result(result, method)
362
+ end
363
+
320
364
  alias_method :state_changes_since, :count_state_changes_since
321
365
  alias_method :state_changes_between, :count_state_changes_between
322
366
 
@@ -34,6 +34,10 @@ module OpenHAB
34
34
  item.members.each { |member| remove(member.name, true) } if recursive && item.is_a?(GroupItem)
35
35
  item
36
36
  end
37
+
38
+ def initialize
39
+ super(unload_priority: 50)
40
+ end
37
41
  end
38
42
  end
39
43
  end
@@ -59,16 +59,25 @@ module OpenHAB
59
59
  #
60
60
  # The item must be a managed item (typically created by Ruby or in the UI).
61
61
  #
62
+ # Any associated metadata or channel links are also removed.
63
+ #
62
64
  # @param [String, Item] item_name
63
65
  # @param recursive [true, false] Remove the item's members if it's a group
64
66
  # @return [Item, nil] The removed item, if found.
65
67
  def remove(item_name, recursive: false)
66
68
  item_name = item_name.name if item_name.is_a?(Item)
67
69
  provider = Provider.registry.provider_for(item_name)
68
- unless provider.is_a?(org.openhab.core.common.registry.ManagedProvider)
70
+ unless provider.is_a?(ManagedProvider)
69
71
  raise "Cannot remove item #{item_name} from non-managed provider #{provider.inspect}"
70
72
  end
71
73
 
74
+ Metadata::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
75
+ managed_provider.remove_item_metadata(item_name)
76
+ end
77
+
78
+ Things::Links::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
79
+ managed_provider.remove_links_for_item(item_name)
80
+ end
72
81
  provider.remove(item_name, recursive)
73
82
  end
74
83
  end
@@ -40,33 +40,56 @@ module Enumerable
40
40
  #
41
41
 
42
42
  # Returns a new array of items that have at least one of the given tags
43
+ #
44
+ # @param tags [String, Module]
43
45
  # @return [Array<Item>]
44
46
  def tagged(*tags)
45
- reject { |i| (tags & i.tags.to_a).empty? }
47
+ select { |i| i.tagged?(*tags) }
46
48
  end
47
49
 
48
50
  # Returns a new array of items that do not have any of the given tags
51
+ # @param tags [String, Module]
49
52
  # @return [Array<Item>]
50
53
  def not_tagged(*tags)
51
- select { |i| (tags & i.tags.to_a).empty? }
54
+ reject { |i| i.tagged?(*tags) }
52
55
  end
53
56
 
54
57
  # Returns a new array of items that are a member of at least one of the given groups
58
+ # @param groups [String, GroupItem]
55
59
  # @return [Array<Item>]
56
60
  def member_of(*groups)
57
- reject { |i| (groups.map(&:name) & i.group_names).empty? }
61
+ select { |i| i.member_of?(*groups) }
58
62
  end
59
63
 
60
64
  # Returns a new array of items that are not a member of any of the given groups
65
+ # @param groups [String, GroupItem]
61
66
  # @return [Array<Item>]
62
67
  def not_member_of(*groups)
63
- select { |i| (groups.map(&:name) & i.group_names).empty? }
68
+ reject { |i| i.member_of?(*groups) }
64
69
  end
65
70
 
66
- # Returns the group members the elements
71
+ # Returns the group members of all group elements
67
72
  # @return [Array<Item>]
68
73
  def members
69
- grep(OpenHAB::Core::Items::GroupItem).flat_map(&:members)
74
+ grep(OpenHAB::Core::Items::GroupItem).flat_map(&:members).uniq
75
+ end
76
+
77
+ # Returns all non-group members of all group elements, recursively
78
+ # @return [Array<Item>]
79
+ def all_members
80
+ grep(OpenHAB::Core::Items::GroupItem).flat_map(&:all_members).uniq
81
+ end
82
+
83
+ # Returns the groups of all elements
84
+ # @return [Array<GroupItem>]
85
+ def groups
86
+ flat_map(&:groups).uniq
87
+ end
88
+
89
+ # Returns all groups all elements are a part of, recursively
90
+ # @return [Array<GroupItem>]
91
+ def all_groups
92
+ flat_map(&:all_groups).uniq
70
93
  end
71
94
 
72
95
  # @!group Items State and Command Methods
@@ -12,13 +12,13 @@ module OpenHAB
12
12
  #
13
13
  # Create a StateStorage object that stores the states of the given items
14
14
  #
15
- # @param [Array<Item>] items A list of items
15
+ # @param [Item] items A list of items
16
16
  #
17
17
  # @return [StateStorage] A state storage object
18
18
  #
19
19
  # @!visibility private
20
20
  def self.from_items(*items)
21
- StateStorage.new($events.store_states(*items).to_h)
21
+ StateStorage.new($events.store_states(*items.map(&:to_java)).to_h)
22
22
  end
23
23
 
24
24
  #
@@ -46,9 +46,9 @@ module OpenHAB
46
46
 
47
47
  logger.trace("Defining #{klass}##{state_predicate} for #{state}")
48
48
  klass.class_eval <<~RUBY, __FILE__, __LINE__ + 1
49
- def #{state_predicate} # def on?
50
- raw_state == #{state} # raw_state == ON
51
- end # end
49
+ def #{state_predicate} # def on?
50
+ raw_state.as(#{state.class.java_class.simple_name}).equal?(#{state}) # raw_state.as(OnOffType) == ON
51
+ end # end
52
52
  RUBY
53
53
  end
54
54
  end
@@ -74,18 +74,11 @@ module OpenHAB
74
74
  end # end
75
75
  RUBY
76
76
 
77
- # Override the inherited methods from Enumerable and send it to the base_item
78
- GroupItem.class_eval <<~RUBY, __FILE__, __LINE__ + 1
79
- def #{command} # def on
80
- method_missing(:#{command}) # method_missing(:on)
81
- end # end
82
- RUBY
83
-
84
77
  logger.trace("Defining ItemCommandEvent##{command}? for #{value}")
85
78
  Events::ItemCommandEvent.class_eval <<~RUBY, __FILE__, __LINE__ + 1
86
- def #{command}? # def refresh?
87
- command == #{value} # command == REFRESH
88
- end # end
79
+ def #{command}? # def refresh?
80
+ command.as(#{value.class.java_class.simple_name}).equal?(#{value}) # command.as(RefreshType).equal?(REFRESH)
81
+ end # end
89
82
  RUBY
90
83
  end
91
84
  end
@@ -219,11 +219,11 @@ module OpenHAB
219
219
 
220
220
  private
221
221
 
222
- def initialize(script_unloaded_before: nil)
222
+ def initialize(unload_priority: nil)
223
223
  super()
224
224
  @elements = java.util.concurrent.ConcurrentHashMap.new
225
225
  self.class.registry.add_provider(self)
226
- ScriptHandling.script_unloaded(before: script_unloaded_before) { unregister }
226
+ ScriptHandling.script_unloaded(priority: unload_priority) { unregister }
227
227
  end
228
228
  end
229
229
  end
@@ -120,6 +120,11 @@ module OpenHAB
120
120
  # define a sub-class of EventSubscriber as a child class of the including class
121
121
  klass.const_set(:EventSubscriber, Class.new(EventSubscriber))
122
122
  end
123
+
124
+ # @!visibility private
125
+ def to_java
126
+ __getobj__
127
+ end
123
128
  end
124
129
  end
125
130
  end
@@ -4,7 +4,7 @@ module OpenHAB
4
4
  module Core
5
5
  Registry = org.openhab.core.common.registry.AbstractRegistry
6
6
 
7
- Registry.field_reader :elementToProvider, :elementReadLock, :identifierToElement
7
+ Registry.field_reader :elementToProvider, :elementReadLock, :identifierToElement, :providerToElements
8
8
 
9
9
  # @abstract
10
10
  #
@@ -19,12 +19,22 @@ module OpenHAB
19
19
  #
20
20
  def provider_for(key)
21
21
  elementReadLock.lock
22
- return nil unless (element = identifierToElement[key])
22
+ if key.is_a?(org.openhab.core.common.registry.Identifiable)
23
+ element = key
24
+ else
25
+ return nil unless (element = identifierToElement[key])
26
+ end
23
27
 
24
28
  elementToProvider[element]
25
29
  ensure
26
30
  elementReadLock.unlock
27
31
  end
32
+
33
+ # @!attribute [r] providers
34
+ # @return [Enumerable<org.openhab.core.common.registry.Provider>]
35
+ def providers
36
+ providerToElements.keys
37
+ end
28
38
  end
29
39
  end
30
40
  end
@@ -19,21 +19,6 @@ module OpenHAB
19
19
  $rules
20
20
  end
21
21
  end
22
-
23
- def initialize
24
- super(script_unloaded_before: lambda do |callbacks|
25
- callbacks.index do |cb|
26
- case cb.binding.receiver
27
- when Items::Provider,
28
- Things::Provider,
29
- DSL::TimerManager
30
- true
31
- else
32
- false
33
- end
34
- end
35
- end)
36
- end
37
22
  end
38
23
  end
39
24
  end
@@ -13,7 +13,7 @@ module OpenHAB
13
13
 
14
14
  class << self
15
15
  #
16
- # @!attribute [r] rule_manager
16
+ # @!attribute [r] manager
17
17
  # @return [org.openhab.core.automation.RuleManager] The openHAB rule manager/engine
18
18
  #
19
19
  def manager
@@ -32,8 +32,6 @@ module OpenHAB
32
32
  ScriptHandlingCallbacks.script_loaded_hooks << block
33
33
  end
34
34
 
35
- #
36
- # @!method script_unloaded(&block)
37
35
  #
38
36
  # Add a block of code to be executed when the script is unloaded.
39
37
  #
@@ -42,6 +40,10 @@ module OpenHAB
42
40
  # Multiple hooks can be added by calling {#script_unloaded} multiple times.
43
41
  # They can be used to perform final cleanup.
44
42
  #
43
+ # @param [Integer, nil] priority The order at which the the given hook will be executed.
44
+ # The higher the number, the lower the priority. Higher priority hooks will be executed
45
+ # first, before the lower priority hooks. When nil, the default priority of zero will
46
+ # be used.
45
47
  # @return [void]
46
48
  #
47
49
  # @example
@@ -49,10 +51,8 @@ module OpenHAB
49
51
  # logger.info 'Hi, this script has been unloaded'
50
52
  # end
51
53
  #
52
- def script_unloaded(before: nil, &block)
53
- # `before` is as yet undocumented, because I'm not set on its interface
54
- index = before.call(ScriptHandlingCallbacks.script_unloaded_hooks) if before
55
- ScriptHandlingCallbacks.script_unloaded_hooks.insert(index || -1, block)
54
+ def script_unloaded(priority: nil, &block)
55
+ ScriptHandlingCallbacks.script_unloaded_hooks[priority || 0] << block
56
56
  end
57
57
  end
58
58
 
@@ -82,7 +82,7 @@ module OpenHAB
82
82
  #
83
83
  # @!visibility private
84
84
  def script_unloaded_hooks
85
- @script_unloaded_hooks ||= []
85
+ @script_unloaded_hooks ||= Hash.new { |hash, key| hash[key] = [] }
86
86
  end
87
87
  end
88
88
  self.script_loaded = false
@@ -92,7 +92,7 @@ module OpenHAB
92
92
  #
93
93
  def scriptUnloaded # rubocop:disable Naming/MethodName method name dictated by openHAB
94
94
  logger.trace("Script unloaded")
95
- ScriptHandlingCallbacks.script_unloaded_hooks.each do |hook|
95
+ ScriptHandlingCallbacks.script_unloaded_hooks.sort_by(&:first).flat_map(&:last).each do |hook|
96
96
  hook.call
97
97
  rescue => e
98
98
  logger.error("Failed to call script_unloaded hook #{hook}: #{e}")
@@ -33,6 +33,44 @@ module OpenHAB
33
33
  current.add(link)
34
34
  end
35
35
  end
36
+
37
+ #
38
+ # Removes all links to a given item.
39
+ #
40
+ # @param [String] item_name
41
+ # @return [Integer] how many links were removed
42
+ #
43
+ def remove_links_for_item(item_name)
44
+ count = 0
45
+ @elements.delete_if do |_k, v|
46
+ next unless v.item_name == item_name
47
+
48
+ count += 1
49
+ notify_listeners_about_removed_element(v)
50
+ true
51
+ end
52
+ count
53
+ end
54
+ alias_method :removeLinksForItem, :remove_links_for_item
55
+
56
+ #
57
+ # Removes all links to a given thing.
58
+ #
59
+ # @param [ThingUID] thing_uid
60
+ # @return [Integer] how many links were removed
61
+ #
62
+ def remove_links_for_thing(thing_uid)
63
+ count = 0
64
+ @elements.delete_if do |_k, v|
65
+ next unless v.linked_uid.thing_uid == thing_uid
66
+
67
+ count += 1
68
+ notify_listeners_about_removed_element(v)
69
+ true
70
+ end
71
+ count
72
+ end
73
+ alias_method :removeLinksForThing, :remove_links_for_thing
36
74
  end
37
75
  end
38
76
  end
@@ -19,6 +19,10 @@ module OpenHAB
19
19
  $things
20
20
  end
21
21
  end
22
+
23
+ def initialize
24
+ super(unload_priority: 60)
25
+ end
22
26
  end
23
27
  end
24
28
  end
@@ -61,6 +61,10 @@ module OpenHAB
61
61
  raise "Cannot remove thing #{thing_uid} from non-managed provider #{provider.inspect}"
62
62
  end
63
63
 
64
+ Links::Provider.registry.providers.grep(ManagedProvider).each do |managed_provider|
65
+ managed_provider.remove_links_for_thing(thing_uid)
66
+ end
67
+
64
68
  provider.remove(thing_uid)
65
69
  end
66
70
  end
@@ -28,7 +28,7 @@ module OpenHAB
28
28
  # @return [true,false]
29
29
 
30
30
  def_delegator :@timer, :has_terminated, :terminated?
31
- def_delegators :@timer, :active?, :cancelled?, :running?
31
+ def_delegators :@timer, :active?, :cancelled?, :running?, :execution_time
32
32
 
33
33
  # @return [Object, nil]
34
34
  attr_accessor :id
@@ -49,19 +49,7 @@ module OpenHAB
49
49
  @id = id
50
50
  @thread_locals = thread_locals
51
51
  @block = block
52
- @timer = if defined?(ScriptExecution)
53
- ScriptExecution.create_timer(1.minute.from_now) { execute }
54
- else # DEPRECATED: openHAB 3.4.0
55
- org.openhab.core.model.script.actions.ScriptExecution.create_timer(
56
- # create it far enough in the future so it won't execute until we finish setting it up
57
- 1.minute.from_now,
58
- # when running in rspec, it may have troubles finding this class
59
- # for auto-conversion of block to interface, so use .impl
60
- org.eclipse.xtext.xbase.lib.Procedures::Procedure0.impl { execute }
61
- )
62
- end
63
- # DEPRECATED: openHAB 3.4.0.M6
64
- @timer.class.field_reader :future unless @timer.respond_to?(:future)
52
+ @timer = ScriptExecution.create_timer(1.minute.from_now) { execute }
65
53
  reschedule(@time)
66
54
  end
67
55
 
@@ -79,11 +67,7 @@ module OpenHAB
79
67
  alias_method :to_s, :inspect
80
68
 
81
69
  # @!attribute [r] execution_time
82
- # @return [ZonedDateTime, nil] the scheduled execution time, or `nil` if the timer was cancelled
83
- def execution_time
84
- # DEPRECATED: openHAB 3.4.0.M6 (just remove the entire method)
85
- @timer.future.scheduled_time
86
- end
70
+ # @return [ZonedDateTime, nil] the scheduled execution time, or `nil` if the timer was cancelled
87
71
 
88
72
  #
89
73
  # Reschedule timer
@@ -46,7 +46,7 @@ module OpenHAB
46
46
  rescue java.lang.StringIndexOutOfBoundsException, java.lang.IllegalArgumentException => e
47
47
  # Try Ruby's Time.parse if DateTimeType parser fails
48
48
  begin
49
- ::Time.parse(time_string).to_zoned_date_time
49
+ DateTimeType.new(::Time.parse(time_string).to_zoned_date_time)
50
50
  rescue ArgumentError
51
51
  raise ArgumentError, e.message
52
52
  end